intel: Add an implementation of MapRenderbuffer.
authorEric Anholt <eric@anholt.net>
Tue, 11 Oct 2011 21:22:45 +0000 (14:22 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 1 Nov 2011 22:42:17 +0000 (15:42 -0700)
v2: Add separate stencil S8 W-tile swizzling/deswizzling.  Tested for
    the swizzling case with env INTEL_SEPARATE_STENCIL=1 INTEL_HIZ=1
    ./bin/hiz-depth-stencil-test-fbo-d24-s8
v3: Apply Chad's fix for S8 window system buffers.

Reviewed-by: Chad Versace <chad@chad-versace.us>
src/mesa/drivers/dri/intel/intel_fbo.c
src/mesa/drivers/dri/intel/intel_fbo.h
src/mesa/drivers/dri/intel/intel_span.c
src/mesa/drivers/dri/intel/intel_span.h

index b7f07bb40ee6db52fec8db3e61302e2091f5981f..9df51d389a3e030df1e65ed7a6dc38513b089e5c 100644 (file)
@@ -84,6 +84,129 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
    free(irb);
 }
 
+static void
+intel_map_renderbuffer(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);
+   GLubyte *map;
+   int stride;
+
+   /* We sometimes get called with this by our intel_span.c usage. */
+   if (!irb->region) {
+      *out_map = NULL;
+      *out_stride = 0;
+      return;
+   }
+
+   irb->map_mode = mode;
+   irb->map_x = x;
+   irb->map_y = y;
+   irb->map_w = w;
+   irb->map_h = h;
+
+   stride = irb->region->pitch * irb->region->cpp;
+
+   if (rb->Format == MESA_FORMAT_S8) {
+      GLuint pix_x, pix_y;
+      uint8_t *tiled_s8_map, *untiled_s8_map;
+
+      /* Flip the Y axis for the default framebuffer. */
+      int y_flip = (rb->Name == 0) ? -1 : 1;
+      int y_bias = (rb->Name == 0) ? (2 * irb->region->height - 1) : 0;
+
+      /* Perform W-tile deswizzling for stencil buffers into a temporary. */
+      stride = w;
+      irb->map_buffer = malloc(stride * h);
+      untiled_s8_map = irb->map_buffer;
+
+      tiled_s8_map = intel_region_map(intel, irb->region, mode);
+
+      for (pix_y = 0; pix_y < h; pix_y++) {
+        for (pix_x = 0; pix_x < w; pix_x++) {
+           GLuint flipped_y = y_flip * (y + pix_y) + y_bias;
+           intptr_t offset = intel_offset_S8(irb->region->pitch,
+                                             x + pix_x,
+                                             flipped_y);
+
+           untiled_s8_map[pix_y * stride + pix_x] = tiled_s8_map[offset];
+        }
+      }
+      *out_map = untiled_s8_map;
+      *out_stride = stride;
+
+      DBG("%s: rb %d (%s) s8 detiled mapped: (%d, %d) (%dx%d) -> %p/%d\n",
+         __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format),
+         x, y, w, h, *out_map, *out_stride);
+
+      return;
+   }
+
+   map = intel_region_map(intel, irb->region, mode);
+   stride = irb->region->pitch * irb->region->cpp;
+
+   if (rb->Name == 0) {
+      map += stride * (irb->region->height - 1);
+      stride = -stride;
+   } else {
+      map += irb->draw_x * irb->region->cpp;
+      map += (int)irb->draw_y * stride;
+   }
+
+   map += x * irb->region->cpp;
+   map += (int)y * stride;
+
+   *out_map = map;
+   *out_stride = stride;
+}
+
+static void
+intel_unmap_renderbuffer(struct gl_context *ctx,
+                        struct gl_renderbuffer *rb)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+   DBG("%s: rb %d (%s)\n", __FUNCTION__,
+       rb->Name, _mesa_get_format_name(rb->Format));
+
+   if (irb->map_buffer) {
+      if (irb->map_mode & GL_MAP_WRITE_BIT) {
+        GLuint pix_x, pix_y;
+        uint8_t *tiled_s8_map = irb->map_buffer;
+        uint8_t *untiled_s8_map = irb->region->bo->virtual;
+
+        /* Flip the Y axis for the default framebuffer. */
+        int y_flip = (rb->Name == 0) ? -1 : 1;
+        int y_bias = (rb->Name == 0) ? (2 * irb->region->height - 1) : 0;
+
+        /* Perform W-tile swizzling back out of the temporary. */
+        for (pix_y = 0; pix_y < irb->map_h; pix_y++) {
+           for (pix_x = 0; pix_x < irb->map_w; pix_x++) {
+              GLuint flipped_y = y_flip * (pix_y + irb->map_y) + y_bias;
+              intptr_t offset = intel_offset_S8(irb->region->pitch,
+                                                pix_x + irb->map_x,
+                                                flipped_y);
+
+              tiled_s8_map[offset] =
+                 untiled_s8_map[pix_y * irb->map_w + pix_x];
+           }
+        }
+      }
+
+      intel_region_unmap(intel, irb->region);
+      free(irb->map_buffer);
+      irb->map_buffer = NULL;
+   } else {
+      if (irb->region)
+        intel_region_unmap(intel, irb->region);
+   }
+}
 
 /**
  * Return a pointer to a specific pixel in a renderbuffer.
@@ -938,6 +1061,8 @@ intel_fbo_init(struct intel_context *intel)
 {
    intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
    intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
+   intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
+   intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
    intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
    intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
    intel->ctx.Driver.RenderTexture = intel_render_texture;
index e12d0fdab9c7737ecdf3d785548b64381965d724..4bcbecdc9c7b7caf56e9e0e3f65e6b0ab086f584 100644 (file)
@@ -44,6 +44,9 @@ struct intel_renderbuffer
 {
    struct gl_renderbuffer Base;
    struct intel_region *region;
+   void *map_buffer;
+   GLuint map_x, map_y, map_w, map_h;
+   GLbitfield map_mode;
 
    /** Only used by depth renderbuffers for which HiZ is enabled. */
    struct intel_region *hiz_region;
index bdc4a0e158c55dc5a5877879f79fac6da280b71b..2819acb443ba9268fa32c45a5c27823ee458b035 100644 (file)
@@ -165,7 +165,7 @@ intel_set_span_functions(struct intel_context *intel,
  *    commit e8b1c6d6f55f5be3bef25084fdd8b6127517e137
  *    mesa: Fix return type of  _mesa_get_format_bytes() (#37351)
  */
-static inline intptr_t
+intptr_t
 intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y)
 {
    uint32_t tile_size = 4096;
index 5a4c4e8e52a5a26d3e233d808954869de405e548..d546ecd158558d19351af11ff0aea211b83aebff 100644 (file)
@@ -42,5 +42,6 @@ void intel_renderbuffer_unmap(struct intel_context *intel,
 void intel_map_vertex_shader_textures(struct gl_context *ctx);
 void intel_unmap_vertex_shader_textures(struct gl_context *ctx);
 bool intel_span_supports_format(gl_format format);
+intptr_t intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y);
 
 #endif