intel: Replace intel_texture_image::stencil_irb with intel_mipmap_tree::stencil_mt [v3]

For depthstencil textures using separate stencil, we embedded a stencil
buffer in intel_texture_image. The intention was that the embedded stencil
buffer would be the golden copy of the texture's stencil bits. When
necessary, we scattered/gathered the stencil bits between the texture
miptree and the embedded stencil buffer.

This approach had a serious deficiency for mipmapped or multi-layer
textures. Any given moment the embedded stencil buffer was consistent with
exactly one miptree slice, the most recent one to be scattered. This
permitted tests of type A to pass, but broke tests of type B.

Test A:
    1. Create a depthstencil texture.
    2. Upload data into (level=x1,layer=y1).
    3. Read and test stencil data at (level=x1, layer=y1).
    4. Upload data into (level=x2,layer=y2).
    5. Read and test stencil data at (level=x2, layer=y2).

Test B:
    1. Create a depthstencil texture.
    2. Upload data into (level=x1,layer=y1).
    3. Upload data into (level=x2,layer=y2).
    4. Read and test stencil data at (level=x1, layer=y1).
    5. Read and test stencil data at (level=x2, layer=y2).

v2:
   Only allocate stencil miptree if intel->must_use_separate_stencil,
   because we don't make the conversion from must_use_separate_stencil to
   has_separate_stencil until commit
        intel: Use separate stencil whenever possible

v3:
   Don't call ChooseNewTexture in intel_renderbuffer_wrap_miptree() in
   order to determine the renderbuffer format. Instead, pass the format as
   a param to that function.

CC: Eric Anholt <eric@anholt.net>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
This commit is contained in:
Chad Versace
2011-11-15 22:17:34 -08:00
parent c80b31fdee
commit 3eb12dfaee
6 changed files with 250 additions and 234 deletions

View File

@@ -36,6 +36,8 @@
#include "main/renderbuffer.h" #include "main/renderbuffer.h"
#include "main/context.h" #include "main/context.h"
#include "main/teximage.h" #include "main/teximage.h"
#include "main/image.h"
#include "swrast/swrast.h" #include "swrast/swrast.h"
#include "drivers/common/meta.h" #include "drivers/common/meta.h"
@@ -946,12 +948,26 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx,
intel_draw_buffer(ctx); intel_draw_buffer(ctx);
} }
static struct intel_renderbuffer*
intel_renderbuffer_wrap_miptree(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer,
gl_format format,
GLenum internal_format);
/** /**
* NOTE: The 'att' parameter is a kludge that will soon be removed. Its * \par Special case for separate stencil
* presence allows us to refactor the wrapping of depthstencil textures that *
* use separate stencil in two easily manageable steps, rather than in one * When wrapping a depthstencil texture that uses separate stencil, this
* large, hairy step. First, refactor the common wrapping code used by all * function is recursively called twice: once to create \c
* texture formats. Second, refactor the separate stencil code paths. * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the
* call to create \c irb->wrapped_depth, the \c format and \c
* internal_format parameters do not match \c mt->format. In that case, \c
* mt->format is MESA_FORMAT_S8_Z24 and \c format is \c
* MESA_FORMAT_X8_Z24.
*
* @return true on success
*/ */
static bool static bool
intel_renderbuffer_update_wrapper(struct intel_context *intel, intel_renderbuffer_update_wrapper(struct intel_context *intel,
@@ -960,17 +976,10 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
uint32_t level, uint32_t level,
uint32_t layer, uint32_t layer,
gl_format format, gl_format format,
GLenum internal_format, GLenum internal_format)
struct gl_renderbuffer_attachment *att)
{ {
struct gl_renderbuffer *rb = &irb->Base; struct gl_renderbuffer *rb = &irb->Base;
/* The image variables are a kludge. See the note above for the att
* parameter.
*/
struct gl_texture_image *texImage = _mesa_get_attachment_teximage(att);
struct intel_texture_image *intel_image = intel_texture_image(texImage);
rb->Format = format; rb->Format = format;
if (!intel_span_supports_format(rb->Format)) { if (!intel_span_supports_format(rb->Format)) {
DBG("Render to texture BAD FORMAT %s\n", DBG("Render to texture BAD FORMAT %s\n",
@@ -993,35 +1002,50 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
irb->mt_level = level; irb->mt_level = level;
irb->mt_layer = layer; irb->mt_layer = layer;
if (intel_image->stencil_rb) { if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) {
/* The tex image has packed depth/stencil format, but is using separate assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL));
* stencil. It shares its embedded depth and stencil renderbuffers with
* the renderbuffer wrapper.
*
* FIXME: glFramebufferTexture*() is broken for depthstencil textures
* FIXME: with separate stencil. To fix this, we must create a separate
* FIXME: pair of depth/stencil renderbuffers for each attached slice
* FIXME: of the miptree.
*/
struct intel_renderbuffer *depth_irb; struct intel_renderbuffer *depth_irb;
struct intel_renderbuffer *stencil_irb; struct intel_renderbuffer *stencil_irb;
_mesa_reference_renderbuffer(&irb->wrapped_depth, if (!irb->wrapped_depth) {
intel_image->depth_rb); depth_irb = intel_renderbuffer_wrap_miptree(intel,
_mesa_reference_renderbuffer(&irb->wrapped_stencil, mt, level, layer,
intel_image->stencil_rb); MESA_FORMAT_X8_Z24,
GL_DEPTH_COMPONENT24);
stencil_irb = intel_renderbuffer_wrap_miptree(intel,
mt->stencil_mt,
level, layer,
MESA_FORMAT_S8,
GL_STENCIL_INDEX8);
_mesa_reference_renderbuffer(&irb->wrapped_depth, &depth_irb->Base);
_mesa_reference_renderbuffer(&irb->wrapped_stencil, &stencil_irb->Base);
depth_irb = intel_renderbuffer(intel_image->depth_rb); if (!irb->wrapped_depth || !irb->wrapped_stencil)
depth_irb->mt_level = irb->mt_level; return false;
depth_irb->mt_layer = irb->mt_layer; } else {
intel_renderbuffer_set_draw_offset(depth_irb); bool ok = true;
stencil_irb = intel_renderbuffer(intel_image->stencil_rb); depth_irb = intel_renderbuffer(irb->wrapped_depth);
stencil_irb->mt_level = irb->mt_level; stencil_irb = intel_renderbuffer(irb->wrapped_stencil);
stencil_irb->mt_layer = irb->mt_layer;
intel_renderbuffer_set_draw_offset(stencil_irb); ok &= intel_renderbuffer_update_wrapper(intel,
depth_irb,
mt,
level, layer,
MESA_FORMAT_X8_Z24,
GL_DEPTH_COMPONENT24);
ok &= intel_renderbuffer_update_wrapper(intel,
stencil_irb,
mt->stencil_mt,
level, layer,
MESA_FORMAT_S8,
GL_STENCIL_INDEX8);
if (!ok)
return false;
}
} else { } else {
intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_reference(&irb->mt, mt);
intel_renderbuffer_set_draw_offset(irb); intel_renderbuffer_set_draw_offset(irb);
} }
@@ -1035,12 +1059,6 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
* ``struct intel_renderbuffer`` then calls * ``struct intel_renderbuffer`` then calls
* intel_renderbuffer_update_wrapper() to do the real work. * intel_renderbuffer_update_wrapper() to do the real work.
* *
* NOTE: The 'att' parameter is a kludge that will soon be removed. Its
* presence allows us to refactor the wrapping of depthstencil textures that
* use separate stencil in two easily manageable steps, rather than in one
* large, hairy step. First, refactor the common wrapping code used by all
* texture formats. Second, refactor the separate stencil code paths.
*
* \see intel_renderbuffer_update_wrapper() * \see intel_renderbuffer_update_wrapper()
*/ */
static struct intel_renderbuffer* static struct intel_renderbuffer*
@@ -1049,8 +1067,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel,
uint32_t level, uint32_t level,
uint32_t layer, uint32_t layer,
gl_format format, gl_format format,
GLenum internal_format, GLenum internal_format)
struct gl_renderbuffer_attachment *att)
{ {
const GLuint name = ~0; /* not significant, but distinct for debugging */ const GLuint name = ~0; /* not significant, but distinct for debugging */
@@ -1070,8 +1087,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel,
if (!intel_renderbuffer_update_wrapper(intel, irb, if (!intel_renderbuffer_update_wrapper(intel, irb,
mt, level, layer, mt, level, layer,
format, internal_format, format, internal_format)) {
att)) {
free(irb); free(irb);
return NULL; return NULL;
} }
@@ -1189,8 +1205,7 @@ intel_render_texture(struct gl_context * ctx,
att->TextureLevel, att->TextureLevel,
layer, layer,
image->TexFormat, image->TexFormat,
image->InternalFormat, image->InternalFormat);
att);
if (irb) { if (irb) {
/* bind the wrapper to the attachment point */ /* bind the wrapper to the attachment point */
@@ -1206,8 +1221,7 @@ intel_render_texture(struct gl_context * ctx,
if (!intel_renderbuffer_update_wrapper(intel, irb, if (!intel_renderbuffer_update_wrapper(intel, irb,
mt, att->TextureLevel, layer, mt, att->TextureLevel, layer,
image->TexFormat, image->TexFormat,
image->InternalFormat, image->InternalFormat)) {
att)) {
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
_swrast_render_texture(ctx, fb, att); _swrast_render_texture(ctx, fb, att);
return; return;

View File

@@ -25,14 +25,18 @@
* *
**************************************************************************/ **************************************************************************/
#include "intel_batchbuffer.h"
#include "intel_context.h" #include "intel_context.h"
#include "intel_mipmap_tree.h" #include "intel_mipmap_tree.h"
#include "intel_regions.h" #include "intel_regions.h"
#include "intel_span.h"
#include "intel_tex_layout.h" #include "intel_tex_layout.h"
#include "intel_tex.h" #include "intel_tex.h"
#include "intel_blit.h" #include "intel_blit.h"
#include "main/enums.h" #include "main/enums.h"
#include "main/formats.h" #include "main/formats.h"
#include "main/image.h"
#include "main/teximage.h" #include "main/teximage.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE #define FILE_DEBUG_FLAG DEBUG_MIPTREE
@@ -54,7 +58,6 @@ target_to_target(GLenum target)
} }
} }
static struct intel_mipmap_tree * static struct intel_mipmap_tree *
intel_miptree_create_internal(struct intel_context *intel, intel_miptree_create_internal(struct intel_context *intel,
GLenum target, GLenum target,
@@ -93,6 +96,16 @@ intel_miptree_create_internal(struct intel_context *intel,
mt->depth0 = depth0; mt->depth0 = depth0;
} }
if (format == MESA_FORMAT_S8) {
/* The stencil buffer has quirky pitch requirements. From Vol 2a,
* 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
* The pitch must be set to 2x the value computed based on width, as
* the stencil buffer is stored with two rows interleaved.
*/
assert(intel->has_separate_stencil);
mt->cpp = 2;
}
#ifdef I915 #ifdef I915
(void) intel; (void) intel;
if (intel->is_945) if (intel->is_945)
@@ -103,6 +116,23 @@ intel_miptree_create_internal(struct intel_context *intel,
brw_miptree_layout(intel, mt); brw_miptree_layout(intel, mt);
#endif #endif
if (intel->must_use_separate_stencil &&
_mesa_is_depthstencil_format(_mesa_get_format_base_format(format))) {
mt->stencil_mt = intel_miptree_create(intel,
mt->target,
MESA_FORMAT_S8,
mt->first_level,
mt->last_level,
mt->width0,
mt->height0,
mt->depth0,
true);
if (!mt->stencil_mt) {
intel_miptree_release(&mt);
return NULL;
}
}
return mt; return mt;
} }
@@ -127,6 +157,8 @@ intel_miptree_create(struct intel_context *intel,
(base_format == GL_DEPTH_COMPONENT || (base_format == GL_DEPTH_COMPONENT ||
base_format == GL_DEPTH_STENCIL_EXT)) base_format == GL_DEPTH_STENCIL_EXT))
tiling = I915_TILING_Y; tiling = I915_TILING_Y;
else if (format == MESA_FORMAT_S8)
tiling = I915_TILING_NONE;
else if (width0 >= 64) else if (width0 >= 64)
tiling = I915_TILING_X; tiling = I915_TILING_X;
} }
@@ -230,6 +262,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
intel_region_release(&((*mt)->region)); intel_region_release(&((*mt)->region));
intel_region_release(&((*mt)->hiz_region)); intel_region_release(&((*mt)->hiz_region));
intel_miptree_release(&(*mt)->stencil_mt);
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
free((*mt)->level[i].slice); free((*mt)->level[i].slice);
@@ -423,6 +456,12 @@ intel_miptree_copy_slice(struct intel_context *intel,
intel_region_unmap(intel, dst_mt->region); intel_region_unmap(intel, dst_mt->region);
intel_region_unmap(intel, src_mt->region); intel_region_unmap(intel, src_mt->region);
} }
if (src_mt->stencil_mt) {
intel_miptree_copy_slice(intel,
dst_mt->stencil_mt, src_mt->stencil_mt,
level, face, depth);
}
} }
/** /**
@@ -446,3 +485,96 @@ intel_miptree_copy_teximage(struct intel_context *intel,
intel_miptree_reference(&intelImage->mt, dst_mt); intel_miptree_reference(&intelImage->mt, dst_mt);
} }
/**
* \param scatter Scatter if true. Gather if false.
*
* \see intel_miptree_s8z24_scatter()
* \see intel_miptree_s8z24_gather()
*/
static void
intel_miptree_s8z24_scattergather(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer,
bool scatter)
{
/* Check function inputs. */
assert(level >= mt->first_level);
assert(level <= mt->last_level);
assert(layer < mt->level[level].depth);
/* Label everything and its bit layout, just to make the code easier to
* read.
*/
struct intel_mipmap_tree *s8_mt = mt->stencil_mt;
struct intel_mipmap_level *s8_level = &s8_mt->level[level];
struct intel_mipmap_slice *s8_slice = &s8_mt->level[level].slice[layer];
struct intel_mipmap_tree *s8z24_mt = mt;
struct intel_mipmap_level *s8z24_level = &s8z24_mt->level[level];
struct intel_mipmap_slice *s8z24_slice = &s8z24_mt->level[level].slice[layer];
/* Check that both miptree levels have the same dimensions. */
assert(s8_level->width == s8z24_level->width);
assert(s8_level->height == s8z24_level->height);
assert(s8_level->depth == s8z24_level->depth);
/* Map the buffers. */
if (drm_intel_bo_references(intel->batch.bo, s8_mt->region->bo) ||
drm_intel_bo_references(intel->batch.bo, s8z24_mt->region->bo)) {
intel_batchbuffer_flush(intel);
}
drm_intel_gem_bo_map_gtt(s8_mt->region->bo);
drm_intel_gem_bo_map_gtt(s8z24_mt->region->bo);
/* Define the invariant values outside the for loop, because I don't trust
* GCC to do it for us.
*/
uint8_t *s8_map = s8_mt->region->bo->virtual
+ s8_slice->x_offset
+ s8_slice->y_offset;
uint8_t *s8z24_map = s8z24_mt->region->bo->virtual
+ s8z24_slice->x_offset
+ s8z24_slice->y_offset;
ptrdiff_t s8z24_stride = s8z24_mt->region->pitch * s8z24_mt->region->cpp;
uint32_t w = s8_level->width;
uint32_t h = s8_level->height;
for (uint32_t y = 0; y < h; ++y) {
for (uint32_t x = 0; x < w; ++x) {
ptrdiff_t s8_offset = intel_offset_S8(s8_mt->region->pitch, x, y);
ptrdiff_t s8z24_offset = y * s8z24_stride
+ x * 4
+ 3;
if (scatter) {
s8_map[s8_offset] = s8z24_map[s8z24_offset];
} else {
s8z24_map[s8z24_offset] = s8_map[s8_offset];
}
}
}
drm_intel_gem_bo_unmap_gtt(s8_mt->region->bo);
drm_intel_gem_bo_unmap_gtt(s8z24_mt->region->bo);
}
void
intel_miptree_s8z24_scatter(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer)
{
intel_miptree_s8z24_scattergather(intel, mt, level, layer, true);
}
void
intel_miptree_s8z24_gather(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer)
{
intel_miptree_s8z24_scattergather(intel, mt, level, layer, false);
}

View File

@@ -152,6 +152,19 @@ struct intel_mipmap_tree
*/ */
struct intel_region *hiz_region; struct intel_region *hiz_region;
/**
* \brief Stencil miptree for depthstencil textures.
*
* This miptree is used for depthstencil textures that require separate
* stencil. The stencil miptree's data is the golden copy of the
* parent miptree's stencil bits. When necessary, we scatter/gather the
* stencil bits between the parent miptree and the stencil miptree.
*
* \see intel_miptree_s8z24_scatter()
* \see intel_miptree_s8z24_gather()
*/
struct intel_mipmap_tree *stencil_mt;
/* These are also refcounted: /* These are also refcounted:
*/ */
GLuint refcount; GLuint refcount;
@@ -239,6 +252,30 @@ intel_miptree_copy_teximage(struct intel_context *intel,
struct intel_texture_image *intelImage, struct intel_texture_image *intelImage,
struct intel_mipmap_tree *dst_mt); struct intel_mipmap_tree *dst_mt);
/**
* Copy the stencil data from \c mt->stencil_mt->region to \c mt->region for
* the given miptree slice.
*
* \see intel_mipmap_tree::stencil_mt
*/
void
intel_miptree_s8z24_scatter(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t slice);
/**
* Copy the stencil data in \c mt->stencil_mt->region to \c mt->region for the
* given miptree slice.
*
* \see intel_mipmap_tree::stencil_mt
*/
void
intel_miptree_s8z24_gather(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer);
/* i915_mipmap_tree.c: /* i915_mipmap_tree.c:
*/ */
void i915_miptree_layout(struct intel_mipmap_tree *mt); void i915_miptree_layout(struct intel_mipmap_tree *mt);

View File

@@ -69,11 +69,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
*/ */
ctx->Driver.FreeTextureImageBuffer(ctx, image); ctx->Driver.FreeTextureImageBuffer(ctx, image);
if (intel->must_use_separate_stencil
&& image->TexFormat == MESA_FORMAT_S8_Z24) {
intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
}
/* Allocate the swrast_texture_image::ImageOffsets array now */ /* Allocate the swrast_texture_image::ImageOffsets array now */
switch (texobj->Target) { switch (texobj->Target) {
case GL_TEXTURE_3D: case GL_TEXTURE_3D:
@@ -107,11 +102,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
*/ */
intel_miptree_reference(&intel_texobj->mt, intel_image->mt); intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
if (intel->must_use_separate_stencil
&& image->TexFormat == MESA_FORMAT_S8_Z24) {
intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
}
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
__FUNCTION__, texobj, image->Level, __FUNCTION__, texobj, image->Level,
width, height, depth, intel_image->mt); width, height, depth, intel_image->mt);
@@ -139,9 +129,6 @@ intel_free_texture_image_buffer(struct gl_context * ctx,
free(intelImage->base.ImageOffsets); free(intelImage->base.ImageOffsets);
intelImage->base.ImageOffsets = NULL; intelImage->base.ImageOffsets = NULL;
} }
_mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
_mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
} }
/** /**
@@ -174,13 +161,14 @@ intel_map_texture_image(struct gl_context *ctx,
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
h == 1); h == 1);
if (intel_image->stencil_rb) { if (mt->stencil_mt) {
/* /* The miptree has depthstencil format, but uses separate stencil. The
* The texture has packed depth/stencil format, but uses separate * embedded stencil miptree contains the real stencil data, so gather
* stencil. The texture's embedded stencil buffer contains the real * that into the depthstencil miptree.
* stencil data, so copy that into the miptree. *
* FIXME: Avoid the gather if the texture is mapped as write-only.
*/ */
intel_tex_image_s8z24_gather(intel, intel_image); intel_miptree_s8z24_gather(intel, mt, tex_image->Level, slice);
} }
/* For compressed formats, the stride is the number of bytes per /* For compressed formats, the stride is the number of bytes per
@@ -211,16 +199,19 @@ intel_unmap_texture_image(struct gl_context *ctx,
{ {
struct intel_context *intel = intel_context(ctx); struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(tex_image); struct intel_texture_image *intel_image = intel_texture_image(tex_image);
struct intel_mipmap_tree *mt = intel_image->mt;
intel_region_unmap(intel, intel_image->mt->region); intel_region_unmap(intel, intel_image->mt->region);
if (intel_image->stencil_rb) { if (mt->stencil_mt) {
/* /* The miptree has depthstencil format, but uses separate stencil. The
* The texture has packed depth/stencil format, but uses separate * embedded stencil miptree must contain the real stencil data after
* stencil. The texture's embedded stencil buffer contains the real * unmapping, so copy it from the depthstencil miptree into the stencil
* stencil data, so copy that into the miptree. * miptree.
*
* FIXME: Avoid the scatter if the texture was mapped as read-only.
*/ */
intel_tex_image_s8z24_scatter(intel, intel_image); intel_miptree_s8z24_scatter(intel, mt, tex_image->Level, slice);
} }
} }

View File

@@ -197,134 +197,6 @@ try_pbo_upload(struct gl_context *ctx,
return true; return true;
} }
/**
* \param scatter Scatter if true. Gather if false.
*
* \see intel_tex_image_x8z24_scatter
* \see intel_tex_image_x8z24_gather
*/
static void
intel_tex_image_s8z24_scattergather(struct intel_context *intel,
struct intel_texture_image *intel_image,
bool scatter)
{
struct gl_context *ctx = &intel->ctx;
struct gl_renderbuffer *depth_rb = intel_image->depth_rb;
struct gl_renderbuffer *stencil_rb = intel_image->stencil_rb;
int w, h, d;
intel_miptree_get_dimensions_for_image(&intel_image->base.Base, &w, &h, &d);
assert(d == 1); /* FINISHME */
uint32_t depth_row[w];
uint8_t stencil_row[w];
intel_renderbuffer_map(intel, depth_rb);
intel_renderbuffer_map(intel, stencil_rb);
if (scatter) {
for (int y = 0; y < h; ++y) {
depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row);
for (int x = 0; x < w; ++x) {
stencil_row[x] = depth_row[x] >> 24;
}
stencil_rb->PutRow(ctx, stencil_rb, w, 0, y, stencil_row, NULL);
}
} else { /* gather */
for (int y = 0; y < h; ++y) {
depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row);
stencil_rb->GetRow(ctx, stencil_rb, w, 0, y, stencil_row);
for (int x = 0; x < w; ++x) {
uint32_t s8_x24 = stencil_row[x] << 24;
uint32_t x8_z24 = depth_row[x] & 0x00ffffff;
depth_row[x] = s8_x24 | x8_z24;
}
depth_rb->PutRow(ctx, depth_rb, w, 0, y, depth_row, NULL);
}
}
intel_renderbuffer_unmap(intel, depth_rb);
intel_renderbuffer_unmap(intel, stencil_rb);
}
/**
* Copy the x8 bits from intel_image->depth_rb to intel_image->stencil_rb.
*/
void
intel_tex_image_s8z24_scatter(struct intel_context *intel,
struct intel_texture_image *intel_image)
{
intel_tex_image_s8z24_scattergather(intel, intel_image, true);
}
/**
* Copy the data in intel_image->stencil_rb to the x8 bits in
* intel_image->depth_rb.
*/
void
intel_tex_image_s8z24_gather(struct intel_context *intel,
struct intel_texture_image *intel_image)
{
intel_tex_image_s8z24_scattergather(intel, intel_image, false);
}
bool
intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel,
struct intel_texture_image *image)
{
struct gl_context *ctx = &intel->ctx;
bool ok = true;
int width, height, depth;
struct gl_renderbuffer *drb;
struct gl_renderbuffer *srb;
struct intel_renderbuffer *idrb;
struct intel_renderbuffer *isrb;
intel_miptree_get_dimensions_for_image(&image->base.Base,
&width, &height, &depth);
assert(depth == 1); /* FINISHME */
assert(intel->has_separate_stencil);
assert(image->base.Base.TexFormat == MESA_FORMAT_S8_Z24);
assert(image->mt != NULL);
drb = intel_create_wrapped_renderbuffer(ctx, width, height,
MESA_FORMAT_X8_Z24);
srb = intel_create_wrapped_renderbuffer(ctx, width, height,
MESA_FORMAT_S8);
if (!drb || !srb) {
if (drb) {
drb->Delete(drb);
}
if (srb) {
srb->Delete(srb);
}
return false;
}
idrb = intel_renderbuffer(drb);
isrb = intel_renderbuffer(srb);
intel_miptree_reference(&idrb->mt, image->mt);
ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8,
width, height);
if (!ok) {
drb->Delete(drb);
srb->Delete(srb);
return false;
}
intel_renderbuffer_set_draw_offset(idrb);
intel_renderbuffer_set_draw_offset(isrb);
_mesa_reference_renderbuffer(&image->depth_rb, drb);
_mesa_reference_renderbuffer(&image->stencil_rb, srb);
return true;
}
static void static void
intelTexImage(struct gl_context * ctx, intelTexImage(struct gl_context * ctx,
GLint dims, GLint dims,

View File

@@ -66,36 +66,6 @@ struct intel_texture_image
*/ */
struct intel_mipmap_tree *mt; struct intel_mipmap_tree *mt;
bool used_as_render_target; bool used_as_render_target;
/**
* \name Renderbuffers for faking packed depth/stencil
*
* These renderbuffers are non-null only if the intel_context is using
* separate stencil and this texture has a packed depth/stencil format. When
* glFramebufferTexture is called on this image, the resultant renderbuffer
* wrapper reuses these renderbuffers as its own.
*
* \see intel_wrap_texture
* \see intel_tex_image_s8z24_create_renderbuffers
* \see intel_tex_image_s8z24_scatter
* \see intel_tex_image_s8z24_gather
*
* \{
*/
/**
* The depth buffer has format X8_Z24. The x8 bits are undefined unless
* intel_tex_image_s8z24_gather has been immediately called. The depth
* buffer reuses the image miptree's region and hiz_region as its own.
*/
struct gl_renderbuffer *depth_rb;
/**
* The stencil buffer has format S8 and keeps its data in its own region.
*/
struct gl_renderbuffer *stencil_rb;
/** \} */
}; };
static INLINE struct intel_texture_object * static INLINE struct intel_texture_object *