diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_texture.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 461 |
1 files changed, 269 insertions, 192 deletions
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index e7bac615df..4439e35d67 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -28,7 +28,9 @@ #include "util/u_memory.h" #include "r300_context.h" +#include "r300_reg.h" #include "r300_texture.h" +#include "r300_transfer.h" #include "r300_screen.h" #include "r300_winsys.h" @@ -71,7 +73,8 @@ static boolean r300_format_is_plain(enum pipe_format format) * * The FORMAT specifies how the texture sampler will treat the texture, and * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ -static uint32_t r300_translate_texformat(enum pipe_format format) +uint32_t r300_translate_texformat(enum pipe_format format, + const unsigned char *swizzle) { uint32_t result = 0; const struct util_format_description *desc; @@ -83,7 +86,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) R300_TX_FORMAT_B_SHIFT, R300_TX_FORMAT_A_SHIFT }; - const uint32_t swizzle[4] = { + const uint32_t swizzle_bit[4] = { R300_TX_FORMAT_X, R300_TX_FORMAT_Y, R300_TX_FORMAT_Z, @@ -130,24 +133,50 @@ static uint32_t r300_translate_texformat(enum pipe_format format) result |= R300_TX_FORMAT_GAMMA; break; - default:; + default: + switch (format) { + /* Same as YUV but without the YUR->RGB conversion. */ + case PIPE_FORMAT_R8G8_B8G8_UNORM: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result; + case PIPE_FORMAT_G8R8_G8B8_UNORM: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result; + default:; + } } /* Add swizzle. */ + if (!swizzle) { + swizzle = desc->swizzle; + } /*else { + if (swizzle[0] != desc->swizzle[0] || + swizzle[1] != desc->swizzle[1] || + swizzle[2] != desc->swizzle[2] || + swizzle[3] != desc->swizzle[3]) + { + const char n[6] = "RGBA01"; + fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, " + "View: %c%c%c%c\n", + n[desc->swizzle[0]], n[desc->swizzle[1]], + n[desc->swizzle[2]], n[desc->swizzle[3]], + n[swizzle[0]], n[swizzle[1]], n[swizzle[2]], + n[swizzle[3]]); + } + }*/ + for (i = 0; i < 4; i++) { - switch (desc->swizzle[i]) { + switch (swizzle[i]) { case UTIL_FORMAT_SWIZZLE_X: case UTIL_FORMAT_SWIZZLE_NONE: - result |= swizzle[0] << swizzle_shift[i]; + result |= swizzle_bit[0] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Y: - result |= swizzle[1] << swizzle_shift[i]; + result |= swizzle_bit[1] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Z: - result |= swizzle[2] << swizzle_shift[i]; + result |= swizzle_bit[2] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_W: - result |= swizzle[3] << swizzle_shift[i]; + result |= swizzle_bit[3] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_0: result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; @@ -186,6 +215,13 @@ static uint32_t r300_translate_texformat(enum pipe_format format) } } + /* This is truly a special format. + * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2) + * in the sampler unit. Also known as D3DFMT_CxV8U8. */ + if (format == PIPE_FORMAT_R8G8Bx_SNORM) { + return R300_TX_FORMAT_CxV8U8 | result; + } + /* RGTC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (format) { @@ -310,7 +346,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) return ~0; /* Unsupported/unknown. */ } -static uint32_t r500_tx_format_msb_bit(enum pipe_format format) +uint32_t r500_tx_format_msb_bit(enum pipe_format format) { switch (format) { case PIPE_FORMAT_RGTC1_UNORM: @@ -339,10 +375,13 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) /* 16-bit buffers. */ case PIPE_FORMAT_B5G6R5_UNORM: return R300_COLOR_FORMAT_RGB565; + case PIPE_FORMAT_B5G5R5A1_UNORM: case PIPE_FORMAT_B5G5R5X1_UNORM: return R300_COLOR_FORMAT_ARGB1555; + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: return R300_COLOR_FORMAT_ARGB4444; /* 32-bit buffers. */ @@ -353,9 +392,14 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_A8B8G8R8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_X8B8G8R8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; + case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: return R500_COLOR_FORMAT_ARGB2101010; /* R5xx-only? */ /* 64-bit buffers. */ @@ -457,8 +501,10 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) case PIPE_FORMAT_B5G5R5A1_UNORM: case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A; @@ -478,9 +524,12 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) R300_C2_SEL_G | R300_C3_SEL_R; /* RGBA outputs. */ + case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */ @@ -507,75 +556,83 @@ boolean r300_is_zs_format_supported(enum pipe_format format) boolean r300_is_sampler_format_supported(enum pipe_format format) { - return r300_translate_texformat(format) != ~0; + return r300_translate_texformat(format, 0) != ~0; } -static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) +static void r300_texture_setup_immutable_state(struct r300_screen* screen, + struct r300_texture* tex) { - struct r300_texture_format_state* state = &tex->state; - struct pipe_texture *pt = &tex->tex; - unsigned i; - boolean is_r500 = screen->caps->is_r500; + struct r300_texture_format_state* f = &tex->tx_format; + struct pipe_resource *pt = &tex->b.b; + boolean is_r500 = screen->caps.is_r500; /* Set sampler state. */ - state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | - R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); + f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | + R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); - if (tex->is_npot) { + if (tex->uses_pitch) { /* rectangles love this */ - state->format0 |= R300_TX_PITCH_EN; - state->format2 = (tex->pitch[0] - 1) & 0x1fff; + f->format0 |= R300_TX_PITCH_EN; + f->format2 = (tex->pitch[0] - 1) & 0x1fff; } else { /* power of two textures (3D, mipmaps, and no pitch) */ - state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); + f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); } - state->format1 = r300_translate_texformat(pt->format); + f->format1 = 0; if (pt->target == PIPE_TEXTURE_CUBE) { - state->format1 |= R300_TX_FORMAT_CUBIC_MAP; + f->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { - state->format1 |= R300_TX_FORMAT_3D; + f->format1 |= R300_TX_FORMAT_3D; } /* large textures on r500 */ if (is_r500) { if (pt->width0 > 2048) { - state->format2 |= R500_TXWIDTH_BIT11; + f->format2 |= R500_TXWIDTH_BIT11; } if (pt->height0 > 2048) { - state->format2 |= R500_TXHEIGHT_BIT11; + f->format2 |= R500_TXHEIGHT_BIT11; } - state->format2 |= r500_tx_format_msb_bit(pt->format); } + f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | + R300_TXO_MICRO_TILE(tex->microtile); + SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", pt->width0, pt->height0, pt->last_level); +} + +static void r300_texture_setup_fb_state(struct r300_screen* screen, + struct r300_texture* tex) +{ + unsigned i; /* Set framebuffer state. */ - if (util_format_is_depth_or_stencil(tex->tex.format)) { - for (i = 0; i <= tex->tex.last_level; i++) { + if (util_format_is_depth_or_stencil(tex->b.b.format)) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.depthpitch[i] = tex->pitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } - tex->fb_state.zb_format = r300_translate_zsformat(tex->tex.format); + tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format); } else { - for (i = 0; i <= tex->tex.last_level; i++) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.colorpitch[i] = tex->pitch[i] | - r300_translate_colorformat(tex->tex.format) | + r300_translate_colorformat(tex->b.b.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } - tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->tex.format); + tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format); } } void r300_texture_reinterpret_format(struct pipe_screen *screen, - struct pipe_texture *tex, + struct pipe_resource *tex, enum pipe_format new_format) { struct r300_screen *r300screen = r300_screen(screen); @@ -585,7 +642,7 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, tex->format = new_format; - r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex); + r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex)); } unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, @@ -593,7 +650,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, { unsigned offset = tex->offset[level]; - switch (tex->tex.target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_3D: assert(face == 0); return offset + zslice * tex->layer_size[level]; @@ -617,7 +674,7 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, { unsigned pixsize, tile_size; - pixsize = util_format_get_blocksize(tex->tex.format); + pixsize = util_format_get_blocksize(tex->b.b.format); tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim]; if (macrotile) { @@ -638,9 +695,9 @@ static boolean r300_texture_macro_switch(struct r300_texture *tex, tile = r300_texture_get_tile_size(tex, dim, TRUE); if (dim == TILE_WIDTH) { - texdim = u_minify(tex->tex.width0, level); + texdim = u_minify(tex->b.b.width0, level); } else { - texdim = u_minify(tex->tex.height0, level); + texdim = u_minify(tex->b.b.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -664,22 +721,22 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, return tex->stride_override; /* Check the level. */ - if (level > tex->tex.last_level) { + if (level > tex->b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", - __FUNCTION__, level, tex->tex.last_level); + __FUNCTION__, level, tex->b.b.last_level); return 0; } - width = u_minify(tex->tex.width0, level); + width = u_minify(tex->b.b.width0, level); - if (r300_format_is_plain(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, tex->mip_macrotile[level]); width = align(width, tile_width); - return util_format_get_stride(tex->tex.format, width); + return util_format_get_stride(tex->b.b.format, width); } else { - return align(util_format_get_stride(tex->tex.format, width), 32); + return align(util_format_get_stride(tex->b.b.format, width), 32); } } @@ -688,23 +745,49 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, { unsigned height, tile_height; - height = u_minify(tex->tex.height0, level); + height = u_minify(tex->b.b.height0, level); - if (r300_format_is_plain(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, tex->mip_macrotile[level]); height = align(height, tile_height); + + /* This is needed for the kernel checker, unfortunately. */ + height = util_next_power_of_two(height); } - return util_format_get_nblocksy(tex->tex.format, height); + return util_format_get_nblocksy(tex->b.b.format, height); +} + +static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, + struct r300_texture *tex) +{ + /* The kernels <= 2.6.34-rc3 compute the size of mipmapped 3D textures + * incorrectly. This is a workaround to prevent CS from being rejected. */ + + unsigned i, size; + + if (screen->rws->get_value(screen->rws, R300_VID_TEX3D_MIP_BUG) && + tex->b.b.target == PIPE_TEXTURE_3D && + tex->b.b.last_level > 0) { + size = 0; + + for (i = 0; i <= tex->b.b.last_level; i++) { + size += r300_texture_get_stride(screen, tex, i) * + r300_texture_get_nblocksy(tex, i); + } + + size *= tex->b.b.depth0; + tex->size = size; + } } static void r300_setup_miptree(struct r300_screen* screen, struct r300_texture* tex) { - struct pipe_texture* base = &tex->tex; + struct pipe_resource* base = &tex->b.b; unsigned stride, size, layer_size, nblocksy, i; - boolean rv350_mode = screen->caps->family >= CHIP_FAMILY_RV350; + boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_RV350; SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", util_format_name(base->format)); @@ -741,23 +824,24 @@ static void r300_setup_miptree(struct r300_screen* screen, static void r300_setup_flags(struct r300_texture* tex) { - tex->is_npot = !util_is_power_of_two(tex->tex.width0) || - !util_is_power_of_two(tex->tex.height0); + tex->uses_pitch = !util_is_power_of_two(tex->b.b.width0) || + !util_is_power_of_two(tex->b.b.height0) || + tex->stride_override; } static void r300_setup_tiling(struct pipe_screen *screen, struct r300_texture *tex) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - enum pipe_format format = tex->tex.format; - boolean rv350_mode = r300_screen(screen)->caps->family >= CHIP_FAMILY_RV350; + enum pipe_format format = tex->b.b.format; + boolean rv350_mode = r300_screen(screen)->caps.family >= CHIP_FAMILY_RV350; if (!r300_format_is_plain(format)) { return; } - if (tex->tex.width0 == 1 || - tex->tex.height0 == 1) { + if (tex->b.b.width0 == 1 || + tex->b.b.height0 == 1) { return; } @@ -783,9 +867,72 @@ static void r300_setup_tiling(struct pipe_screen *screen, } } +static unsigned r300_texture_is_referenced(struct pipe_context *context, + struct pipe_resource *texture, + unsigned face, unsigned level) +{ + struct r300_context *r300 = r300_context(context); + struct r300_texture *rtex = (struct r300_texture *)texture; + + if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer)) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + + return PIPE_UNREFERENCED; +} + +static void r300_texture_destroy(struct pipe_screen *screen, + struct pipe_resource* texture) +{ + struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; + + rws->buffer_reference(rws, &tex->buffer, NULL); + FREE(tex); +} + + + + +static boolean + r300_texture_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + struct r300_texture* tex = (struct r300_texture*)texture; + unsigned stride; + + if (!tex) { + return FALSE; + } + + stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + + rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + + return TRUE; +} + + + +struct u_resource_vtbl r300_texture_vtbl = +{ + r300_texture_get_handle, /* get_handle */ + r300_texture_destroy, /* resource_destroy */ + r300_texture_is_referenced, /* is_resource_referenced */ + r300_texture_get_transfer, /* get_transfer */ + r300_texture_transfer_destroy, /* transfer_destroy */ + r300_texture_transfer_map, /* transfer_map */ + u_default_transfer_flush_region, /* transfer_flush_region */ + r300_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + /* Create a new texture. */ -static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, - const struct pipe_texture* template) +struct pipe_resource* r300_texture_create(struct pipe_screen* screen, + const struct pipe_resource* base) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); struct r300_screen* rscreen = r300_screen(screen); @@ -795,19 +942,23 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, return NULL; } - tex->tex = *template; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *base; + tex->b.vtbl = &r300_texture_vtbl; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; r300_setup_flags(tex); - if (!(template->tex_usage & R300_TEXTURE_USAGE_TRANSFER)) { + if (!(base->flags & R300_RESOURCE_FLAG_TRANSFER) && + !(base->bind & PIPE_BIND_SCANOUT)) { r300_setup_tiling(screen, tex); } r300_setup_miptree(rscreen, tex); - r300_setup_texture_state(rscreen, tex); + r300_texture_3d_fix_mipmapping(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); tex->buffer = rws->buffer_create(rws, 2048, - PIPE_BUFFER_USAGE_PIXEL, + PIPE_BIND_SAMPLER_VIEW, /* XXX */ tex->size); rws->buffer_set_tiling(rws, tex->buffer, tex->pitch[0], @@ -819,26 +970,21 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, return NULL; } - return (struct pipe_texture*)tex; + return (struct pipe_resource*)tex; } -static void r300_texture_destroy(struct pipe_texture* texture) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; - rws->buffer_reference(rws, &tex->buffer, NULL); - FREE(tex); -} -static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, - struct pipe_texture* texture, - unsigned face, - unsigned level, - unsigned zslice, - unsigned flags) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, + struct pipe_resource* texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned flags) { - struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_texture* tex = r300_texture(texture); struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); unsigned offset; @@ -846,7 +992,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, if (surface) { pipe_reference_init(&surface->reference, 1); - pipe_texture_reference(&surface->texture, texture); + pipe_resource_reference(&surface->texture, texture); surface->format = texture->format; surface->width = u_minify(texture->width0, level); surface->height = u_minify(texture->height0, level); @@ -861,23 +1007,25 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, return surface; } -static void r300_tex_surface_destroy(struct pipe_surface* s) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +void r300_tex_surface_destroy(struct pipe_surface* s) { - pipe_texture_reference(&s->texture, NULL); + pipe_resource_reference(&s->texture, NULL); FREE(s); } - -static struct pipe_texture* - r300_texture_from_handle(struct pipe_screen* screen, - const struct pipe_texture* base, - struct winsys_handle *whandle) +struct pipe_resource* +r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_resource* base, + struct winsys_handle *whandle) { struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen* rscreen = r300_screen(screen); struct r300_winsys_buffer *buffer; struct r300_texture* tex; unsigned stride; + boolean override_zb_flags; /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -896,122 +1044,51 @@ static struct pipe_texture* return NULL; } - tex->tex = *base; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *base; + tex->b.vtbl = &r300_texture_vtbl; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; tex->stride_override = stride; - tex->pitch[0] = stride / util_format_get_blocksize(base->format); - - r300_setup_flags(tex); - r300_setup_texture_state(rscreen, tex); /* one ref already taken */ tex->buffer = buffer; - return (struct pipe_texture*)tex; -} - -static boolean - r300_texture_get_handle(struct pipe_screen* screen, - struct pipe_texture *texture, - struct winsys_handle *whandle) -{ - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_texture* tex = (struct r300_texture*)texture; - unsigned stride; - - if (!tex) { - return FALSE; - } - - stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - - rws->buffer_get_handle(rws, tex->buffer, stride, whandle); - - return TRUE; -} - -static struct pipe_video_surface * -r300_video_surface_create(struct pipe_screen *screen, - enum pipe_video_chroma_format chroma_format, - unsigned width, unsigned height) -{ - struct r300_video_surface *r300_vsfc; - struct pipe_texture template; - - assert(screen); - assert(width && height); - - r300_vsfc = CALLOC_STRUCT(r300_video_surface); - if (!r300_vsfc) - return NULL; - - pipe_reference_init(&r300_vsfc->base.reference, 1); - r300_vsfc->base.screen = screen; - r300_vsfc->base.chroma_format = chroma_format; - r300_vsfc->base.width = width; - r300_vsfc->base.height = height; - - memset(&template, 0, sizeof(struct pipe_texture)); - template.target = PIPE_TEXTURE_2D; - template.format = PIPE_FORMAT_B8G8R8X8_UNORM; - template.last_level = 0; - template.width0 = util_next_power_of_two(width); - template.height0 = util_next_power_of_two(height); - template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_RENDER_TARGET; - - r300_vsfc->tex = screen->texture_create(screen, &template); - if (!r300_vsfc->tex) - { - FREE(r300_vsfc); - return NULL; - } - - return &r300_vsfc->base; -} + rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile); + r300_setup_flags(tex); -static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) -{ - struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc); - pipe_texture_reference(&r300_vsfc->tex, NULL); - FREE(r300_vsfc); -} + /* Enforce microtiled zbuffer. */ + override_zb_flags = util_format_is_depth_or_stencil(base->format) && + tex->microtile == R300_BUFFER_LINEAR; -void r300_init_screen_texture_functions(struct pipe_screen* screen) -{ - screen->texture_create = r300_texture_create; - screen->texture_from_handle = r300_texture_from_handle; - screen->texture_get_handle = r300_texture_get_handle; - screen->texture_destroy = r300_texture_destroy; - screen->get_tex_surface = r300_get_tex_surface; - screen->tex_surface_destroy = r300_tex_surface_destroy; - - screen->video_surface_create = r300_video_surface_create; - screen->video_surface_destroy= r300_video_surface_destroy; -} + if (override_zb_flags) { + switch (util_format_get_blocksize(base->format)) { + case 4: + tex->microtile = R300_BUFFER_TILED; + break; -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct r300_winsys_buffer** buffer, - unsigned* stride) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_winsys_buffer *buf; + case 2: + if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { + tex->microtile = R300_BUFFER_SQUARETILED; + break; + } + /* Pass through. */ - if (!tex) { - return FALSE; + default: + override_zb_flags = FALSE; + } } - rws->buffer_reference(rws, &buf, tex->buffer); - - if (stride) { - *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + r300_setup_miptree(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); + + if (override_zb_flags) { + rws->buffer_set_tiling(rws, tex->buffer, + tex->pitch[0], + tex->microtile, + tex->macrotile); } - - *buffer = buf; - return TRUE; + return (struct pipe_resource*)tex; } + |