From 98bb5c610dc68d8e9a185216ce9d2dc6d278c114 Mon Sep 17 00:00:00 2001 From: Joel Bosveld Date: Sun, 10 May 2009 18:26:40 +0200 Subject: [PATCH] radeon: add support for new dri2 interfaces & fix single buffer rendering --- src/mesa/drivers/dri/radeon/radeon_common.c | 39 ++++++ .../dri/radeon/radeon_common_context.c | 115 +++++++++++++++--- .../dri/radeon/radeon_common_context.h | 16 +++ 3 files changed, 154 insertions(+), 16 deletions(-) diff --git a/src/mesa/drivers/dri/radeon/radeon_common.c b/src/mesa/drivers/dri/radeon/radeon_common.c index daf03a98566..decea4518e6 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common.c +++ b/src/mesa/drivers/dri/radeon/radeon_common.c @@ -678,6 +678,7 @@ void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb) if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); radeon->front_cliprects = GL_TRUE; + radeon->front_buffer_dirty = GL_TRUE; } else { rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); radeon->front_cliprects = GL_FALSE; @@ -793,6 +794,24 @@ void radeonDrawBuffer( GLcontext *ctx, GLenum mode ) if (RADEON_DEBUG & DEBUG_DRI) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr( mode )); + + if (ctx->DrawBuffer->Name == 0) { + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + + const GLboolean was_front_buffer_rendering = + radeon->is_front_buffer_rendering; + + radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || + (mode == GL_FRONT); + + /* If we weren't front-buffer rendering before but we are now, make sure + * that the front-buffer has actually been allocated. + */ + if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) { + radeon_update_renderbuffers(radeon->dri.context, + radeon->dri.context->driDrawablePriv); + } + } radeon_draw_buffer(ctx, ctx->DrawBuffer); } @@ -1046,6 +1065,26 @@ void radeonFlush(GLcontext *ctx) if (radeon->cmdbuf.cs->cdw) rcommonFlushCmdBuf(radeon, __FUNCTION__); + + if ((ctx->DrawBuffer->Name == 0) && radeon->front_buffer_dirty) { + __DRIscreen *const screen = radeon->radeonScreen->driScreen; + + if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2) + && (screen->dri2.loader->flushFrontBuffer != NULL)) { + (*screen->dri2.loader->flushFrontBuffer)(radeon->dri.drawable, + radeon->dri.drawable->loaderPrivate); + + /* Only clear the dirty bit if front-buffer rendering is no longer + * enabled. This is done so that the dirty bit can only be set in + * glDrawBuffer. Otherwise the dirty bit would have to be set at + * each of N places that do rendering. This has worse performances, + * but it is much easier to get correct. + */ + if (radeon->is_front_buffer_rendering) { + radeon->front_buffer_dirty = GL_FALSE; + } + } + } } /* Make sure all commands have been sent to the hardware and have diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c index 3e713628ecb..124b587bab1 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c @@ -406,6 +406,23 @@ radeon_make_renderbuffer_current(radeonContextPtr radeon, } } +static unsigned +radeon_bits_per_pixel(const struct radeon_renderbuffer *rb) +{ + switch (rb->base._ActualFormat) { + case GL_RGB5: + case GL_DEPTH_COMPONENT16: + return 16; + case GL_RGB8: + case GL_RGBA8: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH24_STENCIL8_EXT: + case GL_STENCIL_INDEX8_EXT: + return 32; + default: + return 0; + } +} void radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) @@ -426,22 +443,63 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) draw = drawable->driverPrivate; screen = context->driScreenPriv; radeon = (radeonContextPtr) context->driverPrivate; - i = 0; - if (draw->color_rb[0]) - attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - if (draw->color_rb[1]) - attachments[i++] = __DRI_BUFFER_BACK_LEFT; - if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH)) - attachments[i++] = __DRI_BUFFER_DEPTH; - if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL)) - attachments[i++] = __DRI_BUFFER_STENCIL; + + if ((screen->dri2.loader->base.version > 2) + && (screen->dri2.loader->getBuffersWithFormat != NULL)) { + struct radeon_renderbuffer *depth_rb; + struct radeon_renderbuffer *stencil_rb; + + i = 0; + if ((radeon->is_front_buffer_rendering || !draw->color_rb[1]) + && draw->color_rb[0]) { + attachments[i++] = __DRI_BUFFER_FRONT_LEFT; + attachments[i++] = radeon_bits_per_pixel(draw->color_rb[0]); + } + + if (draw->color_rb[1]) { + attachments[i++] = __DRI_BUFFER_BACK_LEFT; + attachments[i++] = radeon_bits_per_pixel(draw->color_rb[1]); + } + + depth_rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); + stencil_rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); + + if ((depth_rb != NULL) && (stencil_rb != NULL)) { + attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; + attachments[i++] = radeon_bits_per_pixel(depth_rb); + } else if (depth_rb != NULL) { + attachments[i++] = __DRI_BUFFER_DEPTH; + attachments[i++] = radeon_bits_per_pixel(depth_rb); + } else if (stencil_rb != NULL) { + attachments[i++] = __DRI_BUFFER_STENCIL; + attachments[i++] = radeon_bits_per_pixel(stencil_rb); + } + + buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable, + &drawable->w, + &drawable->h, + attachments, i / 2, + &count, + drawable->loaderPrivate); + } else { + i = 0; + if (draw->color_rb[0]) + attachments[i++] = __DRI_BUFFER_FRONT_LEFT; + if (draw->color_rb[1]) + attachments[i++] = __DRI_BUFFER_BACK_LEFT; + if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH)) + attachments[i++] = __DRI_BUFFER_DEPTH; + if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL)) + attachments[i++] = __DRI_BUFFER_STENCIL; - buffers = (*screen->dri2.loader->getBuffers)(drawable, - &drawable->w, - &drawable->h, - attachments, i, - &count, - drawable->loaderPrivate); + buffers = (*screen->dri2.loader->getBuffers)(drawable, + &drawable->w, + &drawable->h, + attachments, i, + &count, + drawable->loaderPrivate); + } + if (buffers == NULL) return; @@ -466,6 +524,10 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) rb = draw->color_rb[0]; regname = "dri2 front buffer"; break; + case __DRI_BUFFER_FAKE_FRONT_LEFT: + rb = draw->color_rb[0]; + regname = "dri2 fake front buffer"; + break; case __DRI_BUFFER_BACK_LEFT: rb = draw->color_rb[1]; regname = "dri2 back buffer"; @@ -474,6 +536,10 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); regname = "dri2 depth buffer"; break; + case __DRI_BUFFER_DEPTH_STENCIL: + rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); + regname = "dri2 depth / stencil buffer"; + break; case __DRI_BUFFER_STENCIL: rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); regname = "dri2 stencil buffer"; @@ -535,7 +601,24 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) radeon_renderbuffer_set_bo(rb, bo); radeon_bo_unref(bo); - + + if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) { + rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); + if (rb != NULL) { + struct radeon_bo *stencil_bo = NULL; + + if (rb->bo) { + uint32_t name = radeon_gem_name_bo(rb->bo); + if (name == buffers[i].name) + continue; + } + + stencil_bo = bo; + radeon_bo_ref(stencil_bo); + radeon_renderbuffer_set_bo(rb, stencil_bo); + radeon_bo_unref(stencil_bo); + } + } } driUpdateFramebufferSize(radeon->glCtx, drawable); diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h index 181688cbe46..446c2f6269b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_common_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h @@ -463,6 +463,22 @@ struct radeon_context { GLboolean constant_cliprect; /* use for FBO or DRI2 rendering */ GLboolean front_cliprects; + /** + * Set if rendering has occured to the drawable's front buffer. + * + * This is used in the DRI2 case to detect that glFlush should also copy + * the contents of the fake front buffer to the real front buffer. + */ + GLboolean front_buffer_dirty; + + /** + * Track whether front-buffer rendering is currently enabled + * + * A separate flag is used to track this in order to support MRT more + * easily. + */ + GLboolean is_front_buffer_rendering; + struct { struct gl_fragment_program *bitmap_fp; struct gl_vertex_program *passthrough_vp; -- 2.30.2