radeon: add support for new dri2 interfaces & fix single buffer rendering
authorJoel Bosveld <joel.bosveld@gmail.com>
Sun, 10 May 2009 16:26:40 +0000 (18:26 +0200)
committerJerome Glisse <glisse@freedesktop.org>
Sun, 10 May 2009 16:26:40 +0000 (18:26 +0200)
src/mesa/drivers/dri/radeon/radeon_common.c
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.h

index daf03a98566a50c034e0e81e2625f99f7437f73d..decea4518e6c50f5b3f6facefc40215d899e831c 100644 (file)
@@ -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
index 3e713628ecb73c49c6266adf84f7713e403cfe1b..124b587bab15f6b1834e071ca953d252effd337b 100644 (file)
@@ -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);
index 181688cbe46c23cf9a2bb086c07b3ddece5d59c5..446c2f6269b75a96587ac9ad063fb833651e50dd 100644 (file)
@@ -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;