diff options
author | Chad Versace <[email protected]> | 2011-11-13 17:36:30 -0800 |
---|---|---|
committer | Chad Versace <[email protected]> | 2011-11-15 06:42:09 -0800 |
commit | cc502aa9419a6fb127b264dbb131c786281cb8c7 (patch) | |
tree | f90d4800c8d22aaf7a335db8f8bcb907b5d1d0c1 | |
parent | 5365ba19db8e9d714604bb63f037800ba2ff2f4d (diff) |
intel: Fix intel_map_renderbuffer() for depthstencil buffers with separate stencil
For a depthstencil buffer with separate stencil,
intel_renderbuffer::region is null. (The regions are kept in hidden depth
and stencil buffers). Since the region is null, intel_map_renderbuffer()
assumed there was no data and returned a null map pointer, which in turn
was dereferenced (!) by MapRenderbuffer's caller.
This patch fixes intel_map_renderbuffer() to map the hidden depth buffer
through the GTT and return that as the mapped pointer. Also, the stencil
bits are scattered and gathered when needed.
Fixes the following Piglit tests on gen7:
fbo/fbo-readpixels-depth-formats
hiz/hiz-depth-read-fbo-d24s8
hiz/hiz-stencil-read-fbo-d24s8
EXT_packed_depth_stencil/fbo-clear-formats
EXT_packed_depth_stencil/fbo-depth-GL_DEPTH24_STENCIL8-blit
EXT_packed_depth_stencil/fbo-depth-GL_DEPTH24_STENCIL8-drawpixels
EXT_packed_depth_stencil/fbo-depth-GL_DEPTH24_STENCIL8-readpixels
EXT_packed_depth_stencil/fbo-depthstencil-GL_DEPTH24_STENCIL8-readpixels-24_8
EXT_packed_depth_stencil/fbo-depthstencil-GL_DEPTH24_STENCIL8-readpixels-FLOAT-and-USHORT
EXT_packed_depth_stencil/fbo-stencil-GL_DEPTH24_STENCIL8-readpixels
Reviewed-by: Eric Anholt <[email protected]>
Signed-off-by: Chad Versace <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/intel/intel_fbo.c | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 2a78edfb6be..dbd5163b5f1 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -294,6 +294,91 @@ intel_map_renderbuffer_s8(struct gl_context *ctx, } /** + * \brief Map a depthstencil buffer with separate stencil. + * + * A depthstencil renderbuffer, if using separate stencil, consists of a depth + * renderbuffer and a hidden stencil renderbuffer. This function maps the + * depth buffer, whose format is MESA_FORMAT_X8_Z24, through the GTT and + * returns that as the mapped pointer. The caller need not be aware of the + * hidden stencil buffer and may safely assume that the mapped pointer points + * to a MESA_FORMAT_S8_Z24 buffer + * + * The consistency between the depth buffer's S8 bits and the hidden stencil + * buffer is managed within intel_map_renderbuffer() and + * intel_unmap_renderbuffer() by scattering or gathering the stencil bits + * according to the map mode. + * + * \see intel_map_renderbuffer() + * \see intel_unmap_renderbuffer_separate_s8z24() + */ +static void +intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLuint x, GLuint y, GLuint w, GLuint h, + GLbitfield mode, + GLubyte **out_map, + GLint *out_stride) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + + GLbitfield adjusted_mode; + + uint8_t *s8z24_map; + int32_t s8z24_stride; + + assert(rb->Name != 0); + assert(rb->Format == MESA_FORMAT_S8_Z24); + assert(irb->wrapped_depth != NULL); + assert(irb->wrapped_stencil != NULL); + + irb->map_mode = mode; + irb->map_x = x; + irb->map_y = y; + irb->map_w = w; + irb->map_h = h; + + if (mode & GL_MAP_READ_BIT) { + /* Since the caller may read the stencil bits, we must copy the stencil + * buffer's contents into the depth buffer. This necessitates that the + * depth buffer be mapped in write mode. + */ + adjusted_mode = mode | GL_MAP_WRITE_BIT; + } else { + adjusted_mode = mode; + } + + intel_map_renderbuffer_gtt(ctx, irb->wrapped_depth, + x, y, w, h, adjusted_mode, + &s8z24_map, &s8z24_stride); + + if (mode & GL_MAP_READ_BIT) { + struct intel_renderbuffer *s8_irb; + uint8_t *s8_map; + + s8_irb = intel_renderbuffer(irb->wrapped_stencil); + s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_READ_BIT); + + for (uint32_t pix_y = 0; pix_y < h; ++pix_y) { + for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { + ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, + x + pix_x, + y + pix_y); + ptrdiff_t s8z24_offset = pix_y * s8z24_stride + + pix_x * 4 + + 3; + s8z24_map[s8z24_offset] = s8_map[s8_offset]; + } + } + + intel_region_unmap(intel, s8_irb->region); + } + + *out_map = s8z24_map; + *out_stride = s8z24_stride; +} + +/** * \see dd_function_table::MapRenderbuffer */ static void @@ -308,7 +393,7 @@ intel_map_renderbuffer(struct gl_context *ctx, struct intel_renderbuffer *irb = intel_renderbuffer(rb); /* We sometimes get called with this by our intel_span.c usage. */ - if (!irb->region) { + if (!irb->region && !irb->wrapped_depth) { *out_map = NULL; *out_stride = 0; return; @@ -317,6 +402,9 @@ intel_map_renderbuffer(struct gl_context *ctx, if (rb->Format == MESA_FORMAT_S8) { intel_map_renderbuffer_s8(ctx, rb, x, y, w, h, mode, out_map, out_stride); + } else if (irb->wrapped_depth) { + intel_map_renderbuffer_separate_s8z24(ctx, rb, x, y, w, h, mode, + out_map, out_stride); } else if (intel->gen >= 6 && !(mode & GL_MAP_WRITE_BIT) && irb->region->tiling == I915_TILING_X) { @@ -376,6 +464,64 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx, } /** + * \brief Unmap a depthstencil renderbuffer with separate stencil. + * + * \see intel_map_renderbuffer_separate_s8z24() + * \see intel_unmap_renderbuffer() + */ +static void +intel_unmap_renderbuffer_separate_s8z24(struct gl_context *ctx, + struct gl_renderbuffer *rb) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + struct intel_renderbuffer *s8z24_irb; + + assert(rb->Name != 0); + assert(rb->Format == MESA_FORMAT_S8_Z24); + assert(irb->wrapped_depth != NULL); + assert(irb->wrapped_stencil != NULL); + + s8z24_irb = intel_renderbuffer(irb->wrapped_depth); + + if (irb->map_mode & GL_MAP_WRITE_BIT) { + /* Copy the stencil bits from the depth buffer into the stencil buffer. + */ + uint32_t map_x = irb->map_x; + uint32_t map_y = irb->map_y; + uint32_t map_w = irb->map_w; + uint32_t map_h = irb->map_h; + + struct intel_renderbuffer *s8_irb; + uint8_t *s8_map; + + s8_irb = intel_renderbuffer(irb->wrapped_stencil); + s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_WRITE_BIT); + + int32_t s8z24_stride = 4 * s8z24_irb->region->pitch; + uint8_t *s8z24_map = s8z24_irb->region->bo->virtual + + map_y * s8z24_stride + + map_x * 4; + + for (uint32_t pix_y = 0; pix_y < map_h; ++pix_y) { + for (uint32_t pix_x = 0; pix_x < map_w; ++pix_x) { + ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, + map_x + pix_x, + map_y + pix_y); + ptrdiff_t s8z24_offset = pix_y * s8z24_stride + + pix_x * 4 + + 3; + s8_map[s8_offset] = s8z24_map[s8z24_offset]; + } + } + + intel_region_unmap(intel, s8_irb->region); + } + + drm_intel_gem_bo_unmap_gtt(s8z24_irb->region->bo); +} + +/** * \see dd_function_table::UnmapRenderbuffer */ static void @@ -389,6 +535,8 @@ intel_unmap_renderbuffer(struct gl_context *ctx, if (rb->Format == MESA_FORMAT_S8) { intel_unmap_renderbuffer_s8(ctx, rb); + } else if (irb->wrapped_depth) { + intel_unmap_renderbuffer_separate_s8z24(ctx, rb); } else if (irb->map_bo) { /* Paired with intel_map_renderbuffer_blit(). */ drm_intel_bo_unmap(irb->map_bo); |