-/**
- * Return pointer to texture image data (either linear or tiled layout)
- * for a particular cube face or 3D texture slice.
- *
- * \param face_slice the cube face or 3D slice of interest
- * \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
- * \param layout either LP_TEX_LAYOUT_LINEAR or _TILED or _NONE
- */
-void *
-llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- enum lp_texture_usage usage,
- enum lp_texture_layout layout)
-{
- /*
- * 'target' refers to the image which we're retrieving (either in
- * tiled or linear layout).
- * 'other' refers to the same image but in the other layout. (it may
- * or may not exist.
- */
- struct llvmpipe_texture_image *target_img;
- struct llvmpipe_texture_image *other_img;
- void *target_data;
- void *other_data;
- const unsigned width = u_minify(lpr->base.width0, level);
- const unsigned height = u_minify(lpr->base.height0, level);
- const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
- const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
- unsigned target_offset, other_offset;
- unsigned *target_off_ptr, *other_off_ptr;
- enum lp_texture_layout other_layout;
- boolean only_allocate;
-
- assert(layout == LP_TEX_LAYOUT_NONE ||
- layout == LP_TEX_LAYOUT_TILED ||
- layout == LP_TEX_LAYOUT_LINEAR);
-
- assert(usage == LP_TEX_USAGE_READ ||
- usage == LP_TEX_USAGE_READ_WRITE ||
- usage == LP_TEX_USAGE_WRITE_ALL);
-
- /* check for the special case of layout == LP_TEX_LAYOUT_NONE */
- if (layout == LP_TEX_LAYOUT_NONE) {
- only_allocate = TRUE;
- layout = LP_TEX_LAYOUT_TILED;
- }
- else {
- only_allocate = FALSE;
- }
-
- if (lpr->dt) {
- assert(lpr->linear_img.data);
- }
-
- /* which is target? which is other? */
- if (layout == LP_TEX_LAYOUT_LINEAR) {
- target_img = &lpr->linear_img;
- target_off_ptr = lpr->linear_mip_offsets;
- other_img = &lpr->tiled_img;
- other_off_ptr = lpr->tiled_mip_offsets;
- other_layout = LP_TEX_LAYOUT_TILED;
- }
- else {
- target_img = &lpr->tiled_img;
- target_off_ptr = lpr->tiled_mip_offsets;
- other_img = &lpr->linear_img;
- other_off_ptr = lpr->linear_mip_offsets;
- other_layout = LP_TEX_LAYOUT_LINEAR;
- }
-
- target_data = target_img->data;
- other_data = other_img->data;
-
- if (!target_data) {
- /* allocate memory for the target image now */
- alloc_image_data(lpr, layout);
- target_data = target_img->data;
- }
-
- target_offset = target_off_ptr[level];
- other_offset = other_off_ptr[level];
-
- if (face_slice > 0) {
- target_offset += face_slice * tex_image_face_size(lpr, level, layout);
- other_offset += face_slice * tex_image_face_size(lpr, level, other_layout);
- }
-
- if (target_data) {
- target_data = (uint8_t *) target_data + target_offset;
- }
- if (other_data) {
- other_data = (uint8_t *) other_data + other_offset;
- }
-
- if (only_allocate) {
- /* Just allocating tiled memory. Don't initialize it from the
- * linear data if it exists.
- */
- return target_data;
- }
-
- if (other_data) {
- /* may need to convert other data to the requested layout */
- enum lp_texture_layout new_layout;
- unsigned x, y;
-
- /* loop over all image tiles, doing layout conversion where needed */
- for (y = 0; y < height_t; y++) {
- for (x = 0; x < width_t; x++) {
- enum lp_texture_layout cur_layout =
- llvmpipe_get_texture_tile_layout(lpr, face_slice, level, x, y);
- boolean convert;
-
- layout_logic(cur_layout, layout, usage, &new_layout, &convert);
-
- if (convert && other_data && target_data) {
- if (layout == LP_TEX_LAYOUT_TILED) {
- lp_linear_to_tiled(other_data, target_data,
- x * TILE_SIZE, y * TILE_SIZE,
- TILE_SIZE, TILE_SIZE,
- lpr->base.format,
- lpr->row_stride[level],
- lpr->tiles_per_row[level]);
- }
- else {
- assert(layout == LP_TEX_LAYOUT_LINEAR);
- lp_tiled_to_linear(other_data, target_data,
- x * TILE_SIZE, y * TILE_SIZE,
- TILE_SIZE, TILE_SIZE,
- lpr->base.format,
- lpr->row_stride[level],
- lpr->tiles_per_row[level]);
- }
- }
-
- if (new_layout != cur_layout)
- llvmpipe_set_texture_tile_layout(lpr, face_slice, level, x, y,
- new_layout);
- }
- }
- }
- else {
- /* no other data */
- llvmpipe_set_texture_image_layout(lpr, face_slice, level,
- width_t, height_t, layout);
- }
-
- return target_data;
-}
-
-
-/**
- * Return pointer to start of a texture image (1D, 2D, 3D, CUBE).
- * All cube faces and 3D slices will be converted to the requested
- * layout if needed.
- * This is typically used when we're about to sample from a texture.
- */
-void *
-llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
- unsigned level,
- enum lp_texture_usage usage,
- enum lp_texture_layout layout)
-{
- const int slices = lpr->num_slices_faces[level];
- int slice;
- void *map = NULL;
-
- assert(slices > 0);
-
- for (slice = slices - 1; slice >= 0; slice--) {
- map = llvmpipe_get_texture_image(lpr, slice, level, usage, layout);
- }
-
- return map;
-}
-
-
-/**
- * Get pointer to a linear image (not the tile!) where the tile at (x,y)
- * is known to be in linear layout.
- * Conversion from tiled to linear will be done if necessary.
- * \return pointer to start of image/face (not the tile)
- */
-ubyte *
-llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- enum lp_texture_usage usage,
- unsigned x, unsigned y)
-{
- struct llvmpipe_texture_image *linear_img = &lpr->linear_img;
- enum lp_texture_layout cur_layout, new_layout;
- const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
- boolean convert;
- uint8_t *tiled_image, *linear_image;
-
- assert(llvmpipe_resource_is_texture(&lpr->base));
- assert(x % TILE_SIZE == 0);
- assert(y % TILE_SIZE == 0);
-
- if (!linear_img->data) {
- /* allocate memory for the linear image now */
- alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR);
- }
-
- /* compute address of the slice/face of the image that contains the tile */
- tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
- LP_TEX_LAYOUT_TILED);
- linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
- LP_TEX_LAYOUT_LINEAR);
-
- /* get current tile layout and determine if data conversion is needed */
- cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty);
-
- layout_logic(cur_layout, LP_TEX_LAYOUT_LINEAR, usage,
- &new_layout, &convert);
-
- if (convert && tiled_image && linear_image) {
- lp_tiled_to_linear(tiled_image, linear_image,
- x, y, TILE_SIZE, TILE_SIZE, lpr->base.format,
- lpr->row_stride[level],
- lpr->tiles_per_row[level]);
- }
-
- if (new_layout != cur_layout)
- llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout);
-
- return linear_image;
-}
-
-
-/**
- * Get pointer to tiled data for rendering.
- * \return pointer to the tiled data at the given tile position
- */
-ubyte *
-llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- enum lp_texture_usage usage,
- unsigned x, unsigned y)
-{
- struct llvmpipe_texture_image *tiled_img = &lpr->tiled_img;
- enum lp_texture_layout cur_layout, new_layout;
- const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
- boolean convert;
- uint8_t *tiled_image, *linear_image;
- unsigned tile_offset;
-
- assert(x % TILE_SIZE == 0);
- assert(y % TILE_SIZE == 0);
-
- if (!tiled_img->data) {
- /* allocate memory for the tiled image now */
- alloc_image_data(lpr, LP_TEX_LAYOUT_TILED);
- }
-
- /* compute address of the slice/face of the image that contains the tile */
- tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
- LP_TEX_LAYOUT_TILED);
- linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
- LP_TEX_LAYOUT_LINEAR);
-
- /* get current tile layout and see if we need to convert the data */
- cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty);
-
- layout_logic(cur_layout, LP_TEX_LAYOUT_TILED, usage, &new_layout, &convert);
- if (convert && linear_image && tiled_image) {
- lp_linear_to_tiled(linear_image, tiled_image,
- x, y, TILE_SIZE, TILE_SIZE, lpr->base.format,
- lpr->row_stride[level],
- lpr->tiles_per_row[level]);
- }
-
- if (!tiled_image)
- return NULL;
-
- if (new_layout != cur_layout)
- llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout);
-
- /* compute, return address of the 64x64 tile */
- tile_offset = (ty * lpr->tiles_per_row[level] + tx)
- * TILE_SIZE * TILE_SIZE * 4;