X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fdrivers%2Fi915%2Fi915_resource_texture.c;h=aad5235a6ad3c2bb26632f627bde0f525f5d62f7;hb=69cfc16cb670804b272e88abac5ed3856bb70fa8;hp=f3ab4a4e381a3b6c35304f78ae9c181ee49ab594;hpb=ed94e744d359df8235345cbdfee92e211fd2c9cb;p=mesa.git diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index f3ab4a4e381..aad5235a6ad 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -42,6 +42,7 @@ #include "i915_resource.h" #include "i915_screen.h" #include "i915_winsys.h" +#include "i915_debug.h" #define DEBUG_TEXTURES 0 @@ -87,17 +88,38 @@ static const int bottom_offsets[6] = { [PIPE_TEX_FACE_NEG_Z] = 16 + 5 * 8, }; +static INLINE unsigned +align_nblocksx(enum pipe_format format, unsigned width, unsigned align_to) +{ + return align(util_format_get_nblocksx(format, width), align_to); +} + +static INLINE unsigned +align_nblocksy(enum pipe_format format, unsigned width, unsigned align_to) +{ + return align(util_format_get_nblocksy(format, width), align_to); +} -/* XXX really need twice the size if x is already pot? - Otherwise just use util_next_power_of_two? -*/ -static unsigned -power_of_two(unsigned x) +static INLINE unsigned +get_pot_stride(enum pipe_format format, unsigned width) { - unsigned value = 1; - while (value < x) - value = value << 1; - return value; + return util_next_power_of_two(util_format_get_stride(format, width)); +} + +static INLINE const char* +get_tiling_string(enum i915_winsys_buffer_tile tile) +{ + switch(tile) { + case I915_TILE_NONE: + return "none"; + case I915_TILE_X: + return "x"; + case I915_TILE_Y: + return "y"; + default: + assert(FALSE); + return "?"; + } } @@ -115,28 +137,56 @@ i915_texture_set_level_info(struct i915_texture *tex, assert(!tex->image_offset[level]); tex->nr_images[level] = nr_images; - tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned)); - tex->image_offset[level][0] = 0; + tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair)); + tex->image_offset[level][0].nblocksx = 0; + tex->image_offset[level][0].nblocksy = 0; +} + +INLINE unsigned i915_texture_offset(struct i915_texture *tex, + unsigned level, unsigned layer) +{ + unsigned x, y; + x = tex->image_offset[level][layer].nblocksx + * util_format_get_blocksize(tex->b.b.format); + y = tex->image_offset[level][layer].nblocksy; + + return y * tex->stride + x; } static void i915_texture_set_image_offset(struct i915_texture *tex, unsigned level, unsigned img, - unsigned x, unsigned y) + unsigned nblocksx, unsigned nblocksy) { /* for the first image and level make sure offset is zero */ - assert(!(img == 0 && level == 0) || (x == 0 && y == 0)); + assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0)); assert(img < tex->nr_images[level]); - tex->image_offset[level][img] = y * tex->stride + x * util_format_get_blocksize(tex->b.b.format); + tex->image_offset[level][img].nblocksx = nblocksx; + tex->image_offset[level][img].nblocksy = nblocksy; #if DEBUG_TEXTURES - debug_printf("%s: %p level %u, img %u (%u, %u) %p\n", __FUNCTION__, - tex, level, img, x, y, - (void*)(uintptr_t)tex->image_offset[level][img]); + debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, + tex, level, img, x, y); #endif } +static enum i915_winsys_buffer_tile +i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex) +{ + if (!is->debug.tiling) + return I915_TILE_NONE; + + if (tex->b.b.target == PIPE_TEXTURE_1D) + return I915_TILE_NONE; + + if (util_format_is_s3tc(tex->b.b.format)) + /* XXX X-tiling might make sense */ + return I915_TILE_NONE; + + return I915_TILE_X; +} + /* * Shared layout functions @@ -158,12 +208,13 @@ i9x5_scanout_layout(struct i915_texture *tex) i915_texture_set_image_offset(tex, 0, 0, 0, 0); if (pt->width0 >= 240) { - tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0)); - tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8); - tex->hw_tiled = I915_TILE_X; + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); + tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); + tex->tiling = I915_TILE_X; + /* special case for cursors */ } else if (pt->width0 == 64 && pt->height0 == 64) { - tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0)); - tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8); + tex->stride = get_pot_stride(pt->format, pt->width0); + tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); } else { return FALSE; } @@ -195,9 +246,9 @@ i9x5_display_target_layout(struct i915_texture *tex) i915_texture_set_level_info(tex, 0, 1); i915_texture_set_image_offset(tex, 0, 0, 0, 0); - tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0)); - tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8); - tex->hw_tiled = I915_TILE_X; + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); + tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); + tex->tiling = I915_TILE_X; #if DEBUG_TEXTURE debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, @@ -298,7 +349,7 @@ i915_texture_layout_2d(struct i915_texture *tex) width = u_minify(width, 1); height = u_minify(height, 1); - nblocksy = align(util_format_get_nblocksy(pt->format, height), align_y); + nblocksy = align_nblocksy(pt->format, height, align_y); } } @@ -350,11 +401,10 @@ i915_texture_layout_3d(struct i915_texture *tex) static boolean i915_texture_layout(struct i915_texture * tex) { - struct pipe_resource *pt = &tex->b.b; - - switch (pt->target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: if (!i9x5_special_layout(tex)) i915_texture_layout_2d(tex); break; @@ -405,7 +455,7 @@ i945_texture_layout_2d(struct i915_texture *tex) */ if (pt->last_level > 0) { unsigned mip1_nblocksx = - align(util_format_get_nblocksx(pt->format, u_minify(pt->width0, 1)), align_x) + + align_nblocksx(pt->format, u_minify(pt->width0, 1), align_x) + util_format_get_nblocksx(pt->format, u_minify(pt->width0, 2)); if (mip1_nblocksx > nblocksx) @@ -436,8 +486,8 @@ i945_texture_layout_2d(struct i915_texture *tex) width = u_minify(width, 1); height = u_minify(height, 1); - nblocksx = align(util_format_get_nblocksx(pt->format, width), align_x); - nblocksy = align(util_format_get_nblocksy(pt->format, height), align_y); + nblocksx = align_nblocksx(pt->format, width, align_x); + nblocksy = align_nblocksy(pt->format, height, align_y); } } @@ -595,11 +645,10 @@ i945_texture_layout_cube(struct i915_texture *tex) static boolean i945_texture_layout(struct i915_texture * tex) { - struct pipe_resource *pt = &tex->b.b; - - switch (pt->target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: if (!i9x5_special_layout(tex)) i945_texture_layout_2d(tex); break; @@ -607,7 +656,7 @@ i945_texture_layout(struct i915_texture * tex) i945_texture_layout_3d(tex); break; case PIPE_TEXTURE_CUBE: - if (!util_format_is_s3tc(pt->format)) + if (!util_format_is_s3tc(tex->b.b.format)) i9x5_texture_layout_cube(tex); else i945_texture_layout_cube(tex); @@ -643,7 +692,7 @@ i915_texture_get_handle(struct pipe_screen * screen, static void i915_texture_destroy(struct pipe_screen *screen, - struct pipe_resource *pt) + struct pipe_resource *pt) { struct i915_texture *tex = i915_texture(pt); struct i915_winsys *iws = i915_screen(screen)->iws; @@ -659,49 +708,53 @@ i915_texture_destroy(struct pipe_screen *screen, } static struct pipe_transfer * -i915_texture_get_transfer(struct pipe_context *context, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) +i915_texture_get_transfer(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { + struct i915_context *i915 = i915_context(pipe); struct i915_texture *tex = i915_texture(resource); - struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); + struct pipe_transfer *transfer = util_slab_alloc(&i915->transfer_pool); + if (transfer == NULL) return NULL; transfer->resource = resource; - transfer->sr = sr; + transfer->level = level; transfer->usage = usage; transfer->box = *box; transfer->stride = tex->stride; + /* FIXME: layer_stride */ return transfer; } +static void +i915_transfer_destroy(struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct i915_context *i915 = i915_context(pipe); + util_slab_free(&i915->transfer_pool, transfer); +} static void * i915_texture_transfer_map(struct pipe_context *pipe, - struct pipe_transfer *transfer) + struct pipe_transfer *transfer) { struct pipe_resource *resource = transfer->resource; struct i915_texture *tex = i915_texture(resource); struct i915_winsys *iws = i915_screen(pipe->screen)->iws; - struct pipe_subresource sr = transfer->sr; struct pipe_box *box = &transfer->box; enum pipe_format format = resource->format; unsigned offset; char *map; - if (resource->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[sr.level][sr.face]; - } else if (resource->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[sr.level][box->z]; - } else { - offset = tex->image_offset[sr.level][0]; - assert(sr.face == 0); + if (resource->target != PIPE_TEXTURE_3D && + resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); - } + offset = i915_texture_offset(tex, transfer->level, box->z); map = iws->buffer_map(iws, tex->buffer, (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE); @@ -730,7 +783,7 @@ struct u_resource_vtbl i915_texture_vtbl = i915_texture_destroy, /* resource_destroy */ NULL, /* is_resource_referenced */ i915_texture_get_transfer, /* get_transfer */ - u_default_transfer_destroy, /* transfer_destroy */ + i915_transfer_destroy, /* transfer_destroy */ i915_texture_transfer_map, /* transfer_map */ u_default_transfer_flush_region, /* transfer_flush_region */ i915_texture_transfer_unmap, /* transfer_unmap */ @@ -747,7 +800,6 @@ i915_texture_create(struct pipe_screen *screen, struct i915_screen *is = i915_screen(screen); struct i915_winsys *iws = is->iws; struct i915_texture *tex = CALLOC_STRUCT(i915_texture); - size_t tex_size; unsigned buf_usage = 0; if (!tex) @@ -758,6 +810,8 @@ i915_texture_create(struct pipe_screen *screen, pipe_reference_init(&tex->b.b.reference, 1); tex->b.b.screen = screen; + tex->tiling = i915_texture_tiling(is, tex); + if (is->is_i945) { if (!i945_texture_layout(tex)) goto fail; @@ -766,8 +820,6 @@ i915_texture_create(struct pipe_screen *screen, goto fail; } - tex_size = tex->stride * tex->total_nblocksy; - /* for scanouts and cursors, cursors arn't scanouts */ /* XXX: use a custom flag for cursors, don't rely on magically @@ -778,30 +830,15 @@ i915_texture_create(struct pipe_screen *screen, else buf_usage = I915_NEW_TEXTURE; - tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage); + tex->buffer = iws->buffer_create_tiled(iws, &tex->stride, tex->total_nblocksy, + &tex->tiling, buf_usage); if (!tex->buffer) goto fail; - /* setup any hw fences */ - if (tex->hw_tiled) { - assert(tex->sw_tiled == I915_TILE_NONE); - iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled); - } - - -#if 0 - void *ptr = ws->buffer_map(ws, tex->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE); - memset(ptr, 0x80, tex_size); - ws->buffer_unmap(ws, tex->buffer); -#endif - -#if DEBUG_TEXTURES - debug_printf("%s: %p size %u, stride %u, blocks (%u, %u)\n", __func__, - tex, (unsigned int)tex_size, tex->stride, - tex->stride / util_format_get_blocksize(tex->b.b.format), - tex->total_nblocksy); -#endif + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, + tex, tex->stride, + tex->stride / util_format_get_blocksize(tex->b.b.format), + tex->total_nblocksy, get_tiling_string(tex->tiling)); return &tex->b.b; @@ -820,13 +857,15 @@ i915_texture_from_handle(struct pipe_screen * screen, struct i915_winsys *iws = is->iws; struct i915_winsys_buffer *buffer; unsigned stride; + enum i915_winsys_buffer_tile tiling; assert(screen); - buffer = iws->buffer_from_handle(iws, whandle, &stride); + buffer = iws->buffer_from_handle(iws, whandle, &tiling, &stride); /* Only supports one type */ - if (template->target != PIPE_TEXTURE_2D || + if ((template->target != PIPE_TEXTURE_2D && + template->target != PIPE_TEXTURE_RECT) || template->last_level != 0 || template->depth0 != 1) { return NULL; @@ -842,12 +881,19 @@ i915_texture_from_handle(struct pipe_screen * screen, tex->b.b.screen = screen; tex->stride = stride; + tex->tiling = tiling; + tex->total_nblocksy = align_nblocksy(tex->b.b.format, tex->b.b.height0, 8); i915_texture_set_level_info(tex, 0, 1); i915_texture_set_image_offset(tex, 0, 0, 0, 0); tex->buffer = buffer; + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, + tex, tex->stride, + tex->stride / util_format_get_blocksize(tex->b.b.format), + tex->total_nblocksy, get_tiling_string(tex->tiling)); + return &tex->b.b; }