- if (layout == LP_TEX_LAYOUT_LINEAR) {
- img = &lpr->linear_img;
- offset = lpr->linear_mip_offsets[level];
- }
- else {
- assert (layout == LP_TEX_LAYOUT_TILED);
- img = &lpr->tiled_img;
- offset = lpr->tiled_mip_offsets[level];
- }
-
- if (face_slice > 0)
- offset += face_slice * tex_image_face_size(lpr, level, layout);
-
- return (ubyte *) img->data + offset;
-}
-
-
-static INLINE enum lp_texture_layout
-llvmpipe_get_texture_tile_layout(const struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- unsigned x, unsigned y)
-{
- uint i;
- assert(llvmpipe_resource_is_texture(&lpr->base));
- assert(x < lpr->tiles_per_row[level]);
- i = face_slice * lpr->tiles_per_image[level]
- + y * lpr->tiles_per_row[level] + x;
- return lpr->layout[level][i];
-}
-
-
-static INLINE void
-llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- unsigned x, unsigned y,
- enum lp_texture_layout layout)
-{
- uint i;
- assert(llvmpipe_resource_is_texture(&lpr->base));
- assert(x < lpr->tiles_per_row[level]);
- i = face_slice * lpr->tiles_per_image[level]
- + y * lpr->tiles_per_row[level] + x;
- lpr->layout[level][i] = layout;
-}
-
-
-/**
- * Set the layout mode for all tiles in a particular image.
- */
-static INLINE void
-llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr,
- unsigned face_slice, unsigned level,
- unsigned width_t, unsigned height_t,
- enum lp_texture_layout layout)
-{
- const unsigned start = face_slice * lpr->tiles_per_image[level];
- unsigned i;
-
- for (i = 0; i < width_t * height_t; i++) {
- lpr->layout[level][start + i] = layout;
- }
-}
-
-
-/**
- * Allocate storage for a linear or tile texture image (all cube
- * faces and all 3D slices, all levels).
- */
-static void
-alloc_image_data(struct llvmpipe_resource *lpr,
- enum lp_texture_layout layout)
-{
- uint alignment = MAX2(16, util_cpu_caps.cacheline);
- uint level;
- uint offset = 0;
-
- if (lpr->dt)
- assert(lpr->base.last_level == 0);
-
- if (layout == LP_TEX_LAYOUT_TILED) {
- /* tiled data is stored in regular memory */
- for (level = 0; level <= lpr->base.last_level; level++) {
- uint buffer_size = tex_image_size(lpr, level, layout);
- lpr->tiled_mip_offsets[level] = offset;
- offset += align(buffer_size, alignment);
- }
- lpr->tiled_img.data = align_malloc(offset, alignment);
- if (lpr->tiled_img.data) {
- memset(lpr->tiled_img.data, 0, offset);
- }
- }
- else {
- assert(layout == LP_TEX_LAYOUT_LINEAR);
- if (lpr->dt) {
- /* we get the linear memory from the winsys, and it has
- * already been zeroed
- */
- struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen);
- struct sw_winsys *winsys = screen->winsys;
-
- lpr->linear_img.data =
- winsys->displaytarget_map(winsys, lpr->dt,
- PIPE_TRANSFER_READ_WRITE);
- }
- else {
- /* not a display target - allocate regular memory */
- /*
- * Offset calculation for start of a specific mip/layer is always
- * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
- */
- for (level = 0; level <= lpr->base.last_level; level++) {
- uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
- lpr->linear_mip_offsets[level] = offset;
- offset += align(buffer_size, alignment);
- }
- lpr->linear_img.data = align_malloc(offset, alignment);
- if (lpr->linear_img.data) {
- memset(lpr->linear_img.data, 0, offset);
- }
- }
- }
-}
-
-
-
-/**
- * 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;
-