summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Bosveld <[email protected]>2009-05-10 18:26:40 +0200
committerJerome Glisse <[email protected]>2009-05-10 18:26:40 +0200
commit98bb5c610dc68d8e9a185216ce9d2dc6d278c114 (patch)
tree7aa9ae19f98b6cd58113a996e856bbba1c105a52
parent221b30d595ab2f97fd0518c761615dd28f3ef5ca (diff)
radeon: add support for new dri2 interfaces & fix single buffer rendering
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common.c39
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.c115
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_common_context.h16
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;