summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c150
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);