diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_texture.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_texture.c | 147 |
1 files changed, 136 insertions, 11 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 0d526ead89d..25112c10a66 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -36,6 +36,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" +#include "util/u_cpu_detect.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -55,6 +56,7 @@ #ifdef DEBUG static struct llvmpipe_resource resource_list; #endif +static unsigned id_counter = 0; static INLINE boolean @@ -183,8 +185,8 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, */ const unsigned width = align(lpr->base.width0, TILE_SIZE); const unsigned height = align(lpr->base.height0, TILE_SIZE); - const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; - const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; + const unsigned width_t = width / TILE_SIZE; + const unsigned height_t = height / TILE_SIZE; lpr->tiles_per_row[0] = width_t; lpr->tiles_per_image[0] = width_t * height_t; @@ -209,7 +211,6 @@ static struct pipe_resource * llvmpipe_resource_create(struct pipe_screen *_screen, const struct pipe_resource *templat) { - static unsigned id_counter = 0; struct llvmpipe_screen *screen = llvmpipe_screen(_screen); struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); if (!lpr) @@ -389,7 +390,6 @@ llvmpipe_resource_map(struct pipe_resource *resource, map = llvmpipe_get_texture_image(lpr, face + zslice, level, tex_usage, layout); - assert(map); return map; } else { @@ -446,6 +446,10 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, { struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); + unsigned width, height, width_t, height_t; + + /* XXX Seems like from_handled depth textures doesn't work that well */ + if (!lpr) return NULL; @@ -453,6 +457,25 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, pipe_reference_init(&lpr->base.reference, 1); lpr->base.screen = screen; + width = align(lpr->base.width0, TILE_SIZE); + height = align(lpr->base.height0, TILE_SIZE); + width_t = width / TILE_SIZE; + height_t = height / TILE_SIZE; + + /* + * Looks like unaligned displaytargets work just fine, + * at least sampler/render ones. + */ +#if 0 + assert(lpr->base.width0 == width); + assert(lpr->base.height0 == height); +#endif + + lpr->tiles_per_row[0] = width_t; + lpr->tiles_per_image[0] = width_t * height_t; + lpr->num_slices_faces[0] = 1; + lpr->img_stride[0] = 0; + lpr->dt = winsys->displaytarget_from_handle(winsys, template, whandle, @@ -460,6 +483,17 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, if (!lpr->dt) goto fail; + lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0); + + assert(lpr->layout[0]); + assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); + + lpr->id = id_counter++; + +#ifdef DEBUG + insert_at_tail(&resource_list, lpr); +#endif + return &lpr->base; fail: @@ -899,13 +933,15 @@ static void alloc_image_data(struct llvmpipe_resource *lpr, unsigned level, enum lp_texture_layout layout) { + uint alignment = MAX2(16, util_cpu_caps.cacheline); + if (lpr->dt) assert(level == 0); if (layout == LP_TEX_LAYOUT_TILED) { /* tiled data is stored in regular memory */ uint buffer_size = tex_image_size(lpr, level, layout); - lpr->tiled[level].data = align_malloc(buffer_size, 16); + lpr->tiled[level].data = align_malloc(buffer_size, alignment); } else { assert(layout == LP_TEX_LAYOUT_LINEAR); @@ -921,7 +957,7 @@ alloc_image_data(struct llvmpipe_resource *lpr, unsigned level, else { /* not a display target - allocate regular memory */ uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR); - lpr->linear[level].data = align_malloc(buffer_size, 16); + lpr->linear[level].data = align_malloc(buffer_size, alignment); } } } @@ -1035,7 +1071,7 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, layout_logic(cur_layout, layout, usage, &new_layout, &convert); - if (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, @@ -1067,8 +1103,6 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, width_t, height_t, layout); } - assert(target_data); - return target_data; } @@ -1138,7 +1172,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, layout_logic(cur_layout, LP_TEX_LAYOUT_LINEAR, usage, &new_layout, &convert); - if (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], @@ -1187,13 +1221,16 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, 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) { + 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); @@ -1206,6 +1243,94 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, /** + * Get pointer to tiled data for rendering. + * \return pointer to the tiled data at the given tile position + */ +void +llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr, + unsigned face_slice, unsigned level, + unsigned x, unsigned y, + uint8_t *tile) +{ + struct llvmpipe_texture_image *linear_img = &lpr->linear[level]; + const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; + uint8_t *linear_image; + + 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, level, LP_TEX_LAYOUT_LINEAR); + } + + /* compute address of the slice/face of the image that contains the tile */ + linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, + LP_TEX_LAYOUT_LINEAR); + + { + uint ii = x, jj = y; + uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE; + uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4; + + /* Note that lp_tiled_to_linear expects the tile parameter to + * point at the first tile in a whole-image sized array. In + * this code, we have only a single tile and have to do some + * pointer arithmetic to figure out where the "image" would have + * started. + */ + lp_tiled_to_linear(tile - byte_offset, linear_image, + x, y, TILE_SIZE, TILE_SIZE, + lpr->base.format, + lpr->row_stride[level], + 1); /* tiles per row */ + } + + llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, + LP_TEX_LAYOUT_LINEAR); +} + + +/** + * Get pointer to tiled data for rendering. + * \return pointer to the tiled data at the given tile position + */ +void +llvmpipe_swizzle_cbuf_tile(struct llvmpipe_resource *lpr, + unsigned face_slice, unsigned level, + unsigned x, unsigned y, + uint8_t *tile) +{ + uint8_t *linear_image; + + assert(x % TILE_SIZE == 0); + assert(y % TILE_SIZE == 0); + + /* compute address of the slice/face of the image that contains the tile */ + linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level, + LP_TEX_LAYOUT_LINEAR); + + if (linear_image) { + uint ii = x, jj = y; + uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE; + uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4; + + /* Note that lp_linear_to_tiled expects the tile parameter to + * point at the first tile in a whole-image sized array. In + * this code, we have only a single tile and have to do some + * pointer arithmetic to figure out where the "image" would have + * started. + */ + lp_linear_to_tiled(linear_image, tile - byte_offset, + x, y, TILE_SIZE, TILE_SIZE, + lpr->base.format, + lpr->row_stride[level], + 1); /* tiles per row */ + } +} + + +/** * Return size of resource in bytes */ unsigned |