X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr600%2Fr600_texture.c;h=4673d86fd02d71089d12f4cf42793cadfa843eef;hb=897d2351322e4c516eee622b3f49eedca7a2e308;hp=2d041b04e49cdd3465374f488b6a73c8c22a83aa;hpb=d38768fe3882ac4bc29d4cb7aca975f20c981c0c;p=mesa.git diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 2d041b04e49..4673d86fd02 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -24,18 +24,12 @@ * Jerome Glisse * Corbin Simpson */ +#include "r600_formats.h" +#include "r600d.h" + #include -#include "pipe/p_screen.h" -#include "util/u_format.h" #include "util/u_format_s3tc.h" -#include "util/u_math.h" -#include "util/u_inlines.h" #include "util/u_memory.h" -#include "pipebuffer/pb_buffer.h" -#include "r600_pipe.h" -#include "r600_resource.h" -#include "r600d.h" -#include "r600_formats.h" /* Copy from a full GPU texture to a transfer's staging one. */ static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_transfer *rtransfer) @@ -43,7 +37,7 @@ static void r600_copy_to_staging_texture(struct pipe_context *ctx, struct r600_t struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer; struct pipe_resource *texture = transfer->resource; - ctx->resource_copy_region(ctx, rtransfer->staging_texture, + ctx->resource_copy_region(ctx, &rtransfer->staging->b.b, 0, 0, 0, 0, texture, transfer->level, &transfer->box); } @@ -63,7 +57,7 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600 sbox.depth = 1; ctx->resource_copy_region(ctx, texture, transfer->level, transfer->box.x, transfer->box.y, transfer->box.z, - rtransfer->staging_texture, + &rtransfer->staging->b.b, 0, &sbox); } @@ -72,7 +66,7 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, { unsigned offset = rtex->offset[level]; - switch (rtex->resource.b.b.b.target) { + switch (rtex->resource.b.b.target) { case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: default: @@ -169,7 +163,7 @@ static unsigned r600_texture_get_nblocksx(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned level) { - struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct pipe_resource *ptex = &rtex->resource.b.b; unsigned nblocksx, block_align, width; unsigned blocksize = util_format_get_blocksize(rtex->real_format); @@ -189,7 +183,7 @@ static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned level) { - struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct pipe_resource *ptex = &rtex->resource.b.b; unsigned height, tile_height; height = mip_minify(ptex->height0, level); @@ -214,7 +208,7 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned level, unsigned array_mode) { - struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct pipe_resource *ptex = &rtex->resource.b.b; switch (array_mode) { case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -241,11 +235,136 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen, } } +static int r600_init_surface(struct radeon_surface *surface, + const struct pipe_resource *ptex, + unsigned array_mode) +{ + surface->npix_x = ptex->width0; + surface->npix_y = ptex->height0; + surface->npix_z = ptex->depth0; + surface->blk_w = util_format_get_blockwidth(ptex->format); + surface->blk_h = util_format_get_blockheight(ptex->format); + surface->blk_d = 1; + surface->array_size = 1; + surface->last_level = ptex->last_level; + surface->bpe = util_format_get_blocksize(ptex->format); + /* align byte per element on dword */ + if (surface->bpe == 3) { + surface->bpe = 4; + } + surface->nsamples = 1; + surface->flags = 0; + switch (array_mode) { + case V_038000_ARRAY_1D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + break; + case V_038000_ARRAY_2D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + break; + case V_038000_ARRAY_LINEAR_ALIGNED: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); + break; + case V_038000_ARRAY_LINEAR_GENERAL: + default: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + break; + } + switch (ptex->target) { + case PIPE_TEXTURE_1D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE); + break; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + break; + case PIPE_TEXTURE_3D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE); + break; + case PIPE_TEXTURE_1D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_2D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_CUBE: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE); + break; + case PIPE_BUFFER: + default: + return -EINVAL; + } + if (ptex->bind & PIPE_BIND_SCANOUT) { + surface->flags |= RADEON_SURF_SCANOUT; + } + if (util_format_is_depth_and_stencil(ptex->format)) { + surface->flags |= RADEON_SURF_ZBUFFER; + surface->flags |= RADEON_SURF_SBUFFER; + } + + return 0; +} + +static int r600_setup_surface(struct pipe_screen *screen, + struct r600_resource_texture *rtex, + unsigned array_mode, + unsigned pitch_in_bytes_override) +{ + struct pipe_resource *ptex = &rtex->resource.b.b; + struct r600_screen *rscreen = (struct r600_screen*)screen; + unsigned i; + int r; + + if (util_format_is_depth_or_stencil(rtex->real_format)) { + rtex->surface.flags |= RADEON_SURF_ZBUFFER; + rtex->surface.flags |= RADEON_SURF_SBUFFER; + } + + r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface); + if (r) { + return r; + } + rtex->size = rtex->surface.bo_size; + if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) { + /* old ddx on evergreen over estimate alignment for 1d, only 1 level + * for those + */ + rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe; + rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override; + rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y; + if (rtex->surface.flags & RADEON_SURF_SBUFFER) { + rtex->surface.stencil_offset = rtex->surface.level[0].slice_size; + } + } + for (i = 0; i <= ptex->last_level; i++) { + rtex->offset[i] = rtex->surface.level[i].offset; + rtex->layer_size[i] = rtex->surface.level[i].slice_size; + rtex->pitch_in_bytes[i] = rtex->surface.level[i].pitch_bytes; + switch (rtex->surface.level[i].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + rtex->array_mode[i] = V_038000_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + rtex->array_mode[i] = V_038000_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + rtex->array_mode[i] = V_038000_ARRAY_2D_TILED_THIN1; + break; + default: + case RADEON_SURF_MODE_LINEAR: + rtex->array_mode[i] = 0; + break; + } + } + return 0; +} + static void r600_setup_miptree(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode) { - struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct pipe_resource *ptex = &rtex->resource.b.b; enum chip_class chipc = ((struct r600_screen*)screen)->chip_class; unsigned size, layer_size, i, offset; unsigned nblocksx, nblocksy; @@ -304,7 +423,7 @@ static boolean permit_hardware_blit(struct pipe_screen *screen, /* hackaround for S3TC */ if (util_format_is_compressed(res->format)) return TRUE; - + if (!screen->is_format_supported(screen, res->format, res->target, @@ -319,14 +438,7 @@ static boolean permit_hardware_blit(struct pipe_screen *screen, PIPE_BIND_SAMPLER_VIEW)) return FALSE; - switch (res->usage) { - case PIPE_USAGE_STREAM: - case PIPE_USAGE_STAGING: - return FALSE; - - default: - return TRUE; - } + return TRUE; } static boolean r600_texture_get_handle(struct pipe_screen* screen, @@ -364,9 +476,9 @@ static const struct u_resource_vtbl r600_texture_vtbl = r600_texture_get_transfer, /* get_transfer */ r600_texture_transfer_destroy, /* transfer_destroy */ r600_texture_transfer_map, /* transfer_map */ - u_default_transfer_flush_region,/* transfer_flush_region */ + NULL, /* transfer_flush_region */ r600_texture_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + NULL /* transfer_inline_write */ }; static struct r600_resource_texture * @@ -376,28 +488,31 @@ r600_texture_create_object(struct pipe_screen *screen, unsigned pitch_in_bytes_override, unsigned max_buffer_size, struct pb_buffer *buf, - boolean alloc_bo) + boolean alloc_bo, + struct radeon_surface *surface) { struct r600_resource_texture *rtex; struct r600_resource *resource; struct r600_screen *rscreen = (struct r600_screen*)screen; + int r; rtex = CALLOC_STRUCT(r600_resource_texture); if (rtex == NULL) return NULL; resource = &rtex->resource; - resource->b.b.b = *base; - resource->b.b.vtbl = &r600_texture_vtbl; - pipe_reference_init(&resource->b.b.b.reference, 1); - resource->b.b.b.screen = screen; + resource->b.b = *base; + resource->b.vtbl = &r600_texture_vtbl; + pipe_reference_init(&resource->b.b.reference, 1); + resource->b.b.screen = screen; rtex->pitch_override = pitch_in_bytes_override; rtex->real_format = base->format; /* We must split depth and stencil into two separate buffers on Evergreen. */ if (!(base->flags & R600_RESOURCE_FLAG_TRANSFER) && ((struct r600_screen*)screen)->chip_class >= EVERGREEN && - util_format_is_depth_and_stencil(base->format)) { + util_format_is_depth_and_stencil(base->format) && + !rscreen->use_surface_alloc) { struct pipe_resource stencil; unsigned stencil_pitch_override = 0; @@ -429,7 +544,7 @@ r600_texture_create_object(struct pipe_screen *screen, stencil.format = PIPE_FORMAT_S8_UINT; rtex->stencil = r600_texture_create_object(screen, &stencil, array_mode, stencil_pitch_override, - max_buffer_size, NULL, FALSE); + max_buffer_size, NULL, FALSE, surface); if (!rtex->stencil) { FREE(rtex); return NULL; @@ -439,9 +554,17 @@ r600_texture_create_object(struct pipe_screen *screen, /* only mark depth textures the HW can hit as depth textures */ if (util_format_is_depth_or_stencil(rtex->real_format) && permit_hardware_blit(screen, base)) - rtex->depth = 1; + rtex->is_depth = true; r600_setup_miptree(screen, rtex, array_mode); + if (rscreen->use_surface_alloc) { + rtex->surface = *surface; + r = r600_setup_surface(screen, rtex, array_mode, pitch_in_bytes_override); + if (r) { + FREE(rtex); + return NULL; + } + } /* If we initialized separate stencil for Evergreen. place it after depth. */ if (rtex->stencil) { @@ -450,7 +573,7 @@ r600_texture_create_object(struct pipe_screen *screen, stencil_align = r600_get_base_alignment(screen, rtex->stencil->real_format, array_mode); stencil_offset = align(rtex->size, stencil_align); - for (unsigned i = 0; i <= rtex->stencil->resource.b.b.b.last_level; i++) + for (unsigned i = 0; i <= rtex->stencil->resource.b.b.last_level; i++) rtex->stencil->offset[i] += stencil_offset; rtex->size = stencil_offset + rtex->stencil->size; @@ -458,9 +581,15 @@ r600_texture_create_object(struct pipe_screen *screen, /* Now create the backing buffer. */ if (!buf && alloc_bo) { - struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct pipe_resource *ptex = &rtex->resource.b.b; unsigned base_align = r600_get_base_alignment(screen, ptex->format, array_mode); + if (rscreen->use_surface_alloc) { + base_align = rtex->surface.bo_alignment; + } else if (util_format_is_depth_or_stencil(rtex->real_format)) { + /* ugly work around depth buffer need stencil room at end of bo */ + rtex->size += ptex->width0 * ptex->height0; + } if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { pipe_resource_reference((struct pipe_resource**)&rtex->stencil, NULL); FREE(rtex); @@ -469,37 +598,47 @@ r600_texture_create_object(struct pipe_screen *screen, } else if (buf) { resource->buf = buf; resource->cs_buf = rscreen->ws->buffer_get_cs_handle(buf); + resource->domains = RADEON_DOMAIN_GTT | RADEON_DOMAIN_VRAM; } if (rtex->stencil) { pb_reference(&rtex->stencil->resource.buf, rtex->resource.buf); rtex->stencil->resource.cs_buf = rtex->resource.cs_buf; + rtex->stencil->resource.domains = rtex->resource.domains; } return rtex; } -DEBUG_GET_ONCE_BOOL_OPTION(tiling_enabled, "R600_TILING", FALSE); - struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r600_screen *rscreen = (struct r600_screen*)screen; + struct radeon_surface surface; unsigned array_mode = 0; + int r; - if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && - !(templ->bind & PIPE_BIND_SCANOUT)) { - if (util_format_is_compressed(templ->format)) { - array_mode = V_038000_ARRAY_1D_TILED_THIN1; - } - else if (debug_get_option_tiling_enabled() && - rscreen->info.drm_minor >= 9 && - permit_hardware_blit(screen, templ)) { + if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER)) { + if (rscreen->use_surface_alloc && + !(templ->bind & PIPE_BIND_SCANOUT) && + templ->usage != PIPE_USAGE_STAGING && + templ->usage != PIPE_USAGE_STREAM && + permit_hardware_blit(screen, templ)) { array_mode = V_038000_ARRAY_2D_TILED_THIN1; + } else if (util_format_is_compressed(templ->format)) { + array_mode = V_038000_ARRAY_1D_TILED_THIN1; } } + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } + r = rscreen->ws->surface_best(rscreen->ws, &surface); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - 0, 0, NULL, TRUE); + 0, 0, NULL, TRUE, &surface); } static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, @@ -513,8 +652,6 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); if (surface == NULL) return NULL; - /* XXX no offset */ -/* offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/ pipe_reference_init(&surface->base.reference, 1); pipe_resource_reference(&surface->base.texture, texture); surface->base.context = pipe; @@ -548,6 +685,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, unsigned stride = 0; unsigned array_mode = 0; enum radeon_bo_layout micro, macro; + struct radeon_surface surface; + int r; /* Support only 2D textures without mipmaps */ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) || @@ -558,7 +697,11 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, if (!buf) return NULL; - rscreen->ws->buffer_get_tiling(buf, µ, ¯o); + rscreen->ws->buffer_get_tiling(buf, µ, ¯o, + &surface.bankw, &surface.bankh, + &surface.tile_split, + &surface.stencil_tile_split, + &surface.mtilea); if (macro == RADEON_LAYOUT_TILED) array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; @@ -567,8 +710,12 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, else array_mode = 0; + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - stride, 0, buf, FALSE); + stride, 0, buf, FALSE, &surface); } int r600_texture_depth_flush(struct pipe_context *ctx, @@ -622,6 +769,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, unsigned usage, const struct pipe_box *box) { + struct r600_context *rctx = (struct r600_context*)ctx; struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; struct pipe_resource resource; struct r600_transfer *trans; @@ -641,15 +789,10 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024) use_staging_texture = TRUE; - /* XXX: Use a staging texture for uploads if the underlying BO - * is busy. No interface for checking that currently? so do - * it eagerly whenever the transfer doesn't require a readback - * and might block. - */ - if ((usage & PIPE_TRANSFER_WRITE) && - !(usage & (PIPE_TRANSFER_READ | - PIPE_TRANSFER_DONTBLOCK | - PIPE_TRANSFER_UNSYNCHRONIZED))) + /* Use a staging texture for uploads if the underlying BO is busy. */ + if (!(usage & PIPE_TRANSFER_READ) && + (rctx->ws->cs_is_buffer_referenced(rctx->cs, rtex->resource.cs_buf, RADEON_USAGE_READWRITE) || + rctx->ws->buffer_is_busy(rtex->resource.buf, RADEON_USAGE_READWRITE))) use_staging_texture = TRUE; if (!permit_hardware_blit(ctx->screen, texture) || @@ -666,7 +809,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, trans->transfer.level = level; trans->transfer.usage = usage; trans->transfer.box = *box; - if (rtex->depth) { + if (rtex->is_depth) { /* XXX: only readback the rectangle which is being mapped? */ /* XXX: when discard is true, no need to read back from depth texture @@ -704,8 +847,8 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, resource.bind |= PIPE_BIND_SAMPLER_VIEW; } /* Create the temporary texture. */ - trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource); - if (trans->staging_texture == NULL) { + trans->staging = (struct r600_resource*)ctx->screen->resource_create(ctx->screen, &resource); + if (trans->staging == NULL) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); @@ -713,7 +856,7 @@ struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, } trans->transfer.stride = - ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0]; + ((struct r600_resource_texture *)trans->staging)->pitch_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { r600_copy_to_staging_texture(ctx, trans); /* Always referenced in the blit. */ @@ -734,14 +877,14 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx, struct pipe_resource *texture = transfer->resource; struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; - if (rtransfer->staging_texture) { + if (rtransfer->staging) { if (transfer->usage & PIPE_TRANSFER_WRITE) { r600_copy_from_staging_texture(ctx, rtransfer); } - pipe_resource_reference(&rtransfer->staging_texture, NULL); + pipe_resource_reference((struct pipe_resource**)&rtransfer->staging, NULL); } - if (rtex->depth && !rtex->is_flushing_texture) { + if (rtex->is_depth && !rtex->is_flushing_texture) { if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtex->flushed_depth_texture) r600_blit_push_depth(ctx, rtex); } @@ -753,29 +896,29 @@ void r600_texture_transfer_destroy(struct pipe_context *ctx, void* r600_texture_transfer_map(struct pipe_context *ctx, struct pipe_transfer* transfer) { - struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + struct r600_context *rctx = (struct r600_context *)ctx; struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct pb_buffer *buf; + struct radeon_winsys_cs_handle *buf; enum pipe_format format = transfer->resource->format; unsigned offset = 0; char *map; - if (rtransfer->staging_texture) { - buf = ((struct r600_resource *)rtransfer->staging_texture)->buf; + if (rtransfer->staging) { + buf = ((struct r600_resource *)rtransfer->staging)->cs_buf; } else { struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; if (rtex->flushed_depth_texture) - buf = ((struct r600_resource *)rtex->flushed_depth_texture)->buf; + buf = ((struct r600_resource *)rtex->flushed_depth_texture)->cs_buf; else - buf = ((struct r600_resource *)transfer->resource)->buf; + buf = ((struct r600_resource *)transfer->resource)->cs_buf; offset = rtransfer->offset + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } - if (!(map = rctx->ws->buffer_map(buf, rctx->ctx.cs, transfer->usage))) { + if (!(map = rctx->ws->buffer_map(buf, rctx->cs, transfer->usage))) { return NULL; } @@ -786,24 +929,24 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer* transfer) { struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct r600_pipe_context *rctx = (struct r600_pipe_context*)ctx; - struct pb_buffer *buf; + struct r600_context *rctx = (struct r600_context*)ctx; + struct radeon_winsys_cs_handle *buf; - if (rtransfer->staging_texture) { - buf = ((struct r600_resource *)rtransfer->staging_texture)->buf; + if (rtransfer->staging) { + buf = ((struct r600_resource *)rtransfer->staging)->cs_buf; } else { struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; if (rtex->flushed_depth_texture) { - buf = ((struct r600_resource *)rtex->flushed_depth_texture)->buf; + buf = ((struct r600_resource *)rtex->flushed_depth_texture)->cs_buf; } else { - buf = ((struct r600_resource *)transfer->resource)->buf; + buf = ((struct r600_resource *)transfer->resource)->cs_buf; } } rctx->ws->buffer_unmap(buf); } -void r600_init_surface_functions(struct r600_pipe_context *r600) +void r600_init_surface_functions(struct r600_context *r600) { r600->context.create_surface = r600_create_surface; r600->context.surface_destroy = r600_surface_destroy; @@ -863,6 +1006,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, const struct util_format_description *desc; boolean uniform = TRUE; static int r600_enable_s3tc = -1; + bool is_srgb_valid = FALSE; int i; const uint32_t sign_bit[4] = { @@ -917,7 +1061,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, default: break; } - goto out_unknown; /* TODO */ + goto out_unknown; /* XXX */ case UTIL_FORMAT_COLORSPACE_SRGB: word4 |= S_038010_FORCE_DEGAMMA(1); @@ -974,14 +1118,32 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, case PIPE_FORMAT_DXT1_SRGB: case PIPE_FORMAT_DXT1_SRGBA: result = FMT_BC1; + is_srgb_valid = TRUE; goto out_word4; case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT3_SRGBA: result = FMT_BC2; + is_srgb_valid = TRUE; goto out_word4; case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_DXT5_SRGBA: result = FMT_BC3; + is_srgb_valid = TRUE; + goto out_word4; + default: + goto out_unknown; + } + } + + if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) { + switch (format) { + case PIPE_FORMAT_R8G8_B8G8_UNORM: + case PIPE_FORMAT_G8R8_B8R8_UNORM: + result = FMT_GB_GR; + goto out_word4; + case PIPE_FORMAT_G8R8_G8B8_UNORM: + case PIPE_FORMAT_R8G8_R8B8_UNORM: + result = FMT_BG_RG; goto out_word4; default: goto out_unknown; @@ -1003,7 +1165,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, } } - /* R8G8Bx_SNORM - TODO CxV8U8 */ + /* R8G8Bx_SNORM - XXX CxV8U8 */ /* See whether the components are of the same size. */ for (i = 1; i < desc->nr_channels; i++) { @@ -1089,6 +1251,7 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, goto out_word4; case 4: result = FMT_8_8_8_8; + is_srgb_valid = TRUE; goto out_word4; } goto out_unknown; @@ -1152,6 +1315,9 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, } out_word4: + + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB && !is_srgb_valid) + return ~0; if (word4_p) *word4_p = word4; if (yuv_format_p)