radeon: Add implementation of MapRenderbuffer.
authorEric Anholt <eric@anholt.net>
Mon, 17 Oct 2011 16:50:52 +0000 (09:50 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 1 Nov 2011 22:42:18 +0000 (15:42 -0700)
Unlike intel, we do a blit to/from GTT memory in order to
untile/retile the renderbuffer data, since we don't have fence
registers for accessing it.

(There is software tiling code in radeon_tile.c, but it's unused and
doesn't support macro tiling)

Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_fbo.c

index 17889b0a9a058d524f927d06cd9f344614a26c80..2cfaec8f7965f7649f49d9e6e319f6511aa0805e 100644 (file)
@@ -87,6 +87,10 @@ struct radeon_renderbuffer
        /* unsigned int offset; */
        unsigned int pitch;
 
+       struct radeon_bo *map_bo;
+       GLbitfield map_mode;
+       int map_x, map_y, map_w, map_h;
+
        uint32_t draw_offset; /* FBO */
        /* boo Xorg 6.8.2 compat */
        int has_surface;
index 4b64cacddad21de7ef5ff98166d2207d1dd805e3..cf89fe5b38fa811ab62c32413e73101727c4ec29 100644 (file)
@@ -70,6 +70,98 @@ radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
   free(rrb);
 }
 
+static void
+radeon_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 radeon_context *const rmesa = RADEON_CONTEXT(ctx);
+   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+   GLubyte *map;
+   GLboolean ok;
+   int stride, ret;
+
+   assert(rrb && rrb->bo);
+
+   /* Make a temporary buffer and blit the current contents of the renderbuffer
+    * out to it.  This gives us linear access to the buffer, instead of having
+    * to do detiling in software.
+    */
+   assert(!rrb->map_bo);
+   rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
+                               rrb->pitch * h, 4,
+                               RADEON_GEM_DOMAIN_GTT, 0);
+   rrb->map_mode = mode;
+   rrb->map_x = x;
+   rrb->map_y = y;
+   rrb->map_w = w;
+   rrb->map_h = h;
+
+   ok = rmesa->vtbl.check_blit(rb->Format);
+   assert(ok);
+
+   ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
+                        rb->Format, rrb->pitch / rrb->cpp,
+                        rb->Width, rb->Height,
+                        x, y,
+                        rrb->map_bo, 0,
+                        rb->Format, rrb->pitch / rrb->cpp,
+                        w, h,
+                        0, 0,
+                        w, h,
+                        GL_FALSE);
+   assert(ok);
+
+   radeon_bo_wait(rrb->map_bo);
+   ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
+   assert(!ret);
+
+   map = rrb->map_bo->ptr;
+   stride = rrb->pitch;
+
+   if (rb->Name == 0) {
+      map += stride * (rb->Height - 1);
+      stride = -stride;
+   }
+
+   map += x * _mesa_get_format_bytes(rb->Format);
+   map += (int)y * stride;
+
+   *out_map = map;
+   *out_stride = stride;
+}
+
+static void
+radeon_unmap_renderbuffer(struct gl_context *ctx,
+                         struct gl_renderbuffer *rb)
+{
+   struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
+   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
+   GLboolean ok;
+
+   radeon_bo_unmap(rrb->map_bo);
+
+   if (rrb->map_mode & GL_MAP_WRITE_BIT) {
+      ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
+                           rb->Format, rrb->pitch / rrb->cpp,
+                           rrb->map_w, rrb->map_h,
+                           0, 0,
+                           rrb->bo, rrb->draw_offset,
+                           rb->Format, rrb->pitch / rrb->cpp,
+                           rb->Width, rb->Height,
+                           rrb->map_x, rrb->map_y,
+                           rrb->map_w, rrb->map_h,
+                           GL_FALSE);
+      assert(ok);
+   }
+
+   radeon_bo_unref(rrb->map_bo);
+   rrb->map_bo = NULL;
+}
+
 static void *
 radeon_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb,
                   GLint x, GLint y)
@@ -639,6 +731,8 @@ void radeon_fbo_init(struct radeon_context *radeon)
 #if FEATURE_EXT_framebuffer_object
   radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
   radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
+  radeon->glCtx->Driver.MapRenderbuffer = radeon_map_renderbuffer;
+  radeon->glCtx->Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
   radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
   radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
   radeon->glCtx->Driver.RenderTexture = radeon_render_texture;