diff options
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_common_context.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_fbo.c | 94 |
2 files changed, 98 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index 17889b0a9a0..2cfaec8f796 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -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; diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c index 4b64cacddad..cf89fe5b38f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_fbo.c +++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c @@ -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; |