From cc502aa9419a6fb127b264dbb131c786281cb8c7 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 17:36:30 -0800 Subject: [PATCH] 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 Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 150 ++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) 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 @@ -293,6 +293,91 @@ intel_map_renderbuffer_s8(struct gl_context *ctx, x, y, w, h, *out_map, *out_stride); } +/** + * \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 */ @@ -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) { @@ -375,6 +463,64 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx, irb->map_buffer = NULL; } +/** + * \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 */ @@ -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); -- 2.30.2