Dave Reveman's patch for GLX_MESA_copy_sub_buffer support
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 31 Mar 2006 15:48:04 +0000 (15:48 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 31 Mar 2006 15:48:04 +0000 (15:48 +0000)
23 files changed:
include/GL/internal/dri_interface.h
src/glx/x11/glxcmds.c
src/glx/x11/glxextensions.c
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/i915/intel_batchbuffer.c
src/mesa/drivers/dri/i915/intel_batchbuffer.h
src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/i915/intel_screen.c
src/mesa/drivers/dri/i915/intel_screen.h
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r200/r200_context.h
src/mesa/drivers/dri/r200/r200_ioctl.c
src/mesa/drivers/dri/r200/r200_ioctl.h
src/mesa/drivers/dri/r300/radeon_context.c
src/mesa/drivers/dri/r300/radeon_context.h
src/mesa/drivers/dri/r300/radeon_ioctl.c
src/mesa/drivers/dri/r300/radeon_ioctl.h
src/mesa/drivers/dri/radeon/radeon_context.c
src/mesa/drivers/dri/radeon/radeon_context.h
src/mesa/drivers/dri/radeon/radeon_ioctl.c
src/mesa/drivers/dri/radeon/radeon_ioctl.h
src/mesa/drivers/dri/radeon/radeon_screen.c

index 0f3555b576e7a20f591209be33c95ce5b0298dff..c204ecfe622f90662490415fd82b3b3e10dad76b 100644 (file)
@@ -472,6 +472,14 @@ struct __DRIdrawableRec {
      * \since Internal API version 20030317.
      */
     unsigned swap_interval;
+
+    /**
+     * Used by drivers that implement the GLX_MESA_copy_sub_buffer extension.
+     *
+     * \since Internal API version 20060314.
+     */
+    void (*copySubBuffer)(__DRInativeDisplay *dpy, void *drawablePrivate,
+                         int x, int y, int w, int h);
 };
 
 #endif
index d4f579d01acd35f9d04ca87f4464eb68e54c1682..16f7e96150af44c98156bb094a4e171a2b013281 100644 (file)
@@ -2570,18 +2570,69 @@ PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
    return 0;
 }
 
-
+#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
 PUBLIC void glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
                                 int x, int y, int width, int height)
 {
-   (void) dpy;
-   (void) drawable;
-   (void) x;
-   (void) y;
-   (void) width;
-   (void) height;
-}
+    xGLXVendorPrivateReq *req;
+    GLXContext gc;
+    GLXContextTag tag;
+    CARD32 *drawable_ptr;
+    INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
+    CARD8 opcode;
+
+#ifdef GLX_DIRECT_RENDERING
+    int screen;
+    __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen );
+    if ( pdraw != NULL ) {
+       __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
+       if ( __glXExtensionBitIsEnabled( psc, MESA_copy_sub_buffer_bit ) ) {
+           (*pdraw->copySubBuffer)(dpy, pdraw->private, x, y, width, height);
+       }
+
+       return;
+    }
+#endif
+
+    opcode = __glXSetupForCommand(dpy);
+    if (!opcode)
+       return;
 
+    /*
+    ** The calling thread may or may not have a current context.  If it
+    ** does, send the context tag so the server can do a flush.
+    */
+    gc = __glXGetCurrentContext();
+    if ((gc != NULL) && (dpy == gc->currentDpy) &&
+       ((drawable == gc->currentDrawable) ||
+        (drawable == gc->currentReadable)) ) {
+       tag = gc->currentContextTag;
+    } else {
+       tag = 0;
+    }
+
+    LockDisplay(dpy);
+    GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4,req);
+    req->reqType = opcode;
+    req->glxCode = X_GLXVendorPrivate;
+    req->vendorCode = X_GLXvop_CopySubBufferMESA;
+    req->contextTag = tag;
+
+    drawable_ptr = (CARD32 *) (req + 1);
+    x_ptr = (INT32 *) (drawable_ptr + 1);
+    y_ptr = (INT32 *) (drawable_ptr + 2);
+    w_ptr = (INT32 *) (drawable_ptr + 3);
+    h_ptr = (INT32 *) (drawable_ptr + 4);
+
+    *drawable_ptr = drawable;
+    *x_ptr = x;
+    *y_ptr = y;
+    *w_ptr = width;
+    *h_ptr = height;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
 
 PUBLIC Bool glXSet3DfxModeMESA( int mode )
 {
@@ -2973,8 +3024,9 @@ int __glXGetInternalVersion(void)
      *            months ago. :(
      * 20050727 - Gut all the old interfaces.  This breaks compatability with
      *            any DRI driver built to any previous version.
+     * 20060314 - Added support for GLX_MESA_copy_sub_buffer.
      */
-    return 20050727;
+    return 20060314;
 }
 
 
index 0cee71f6c3a6486fec19913aa0b872955c7aa859..c3bc93009aad08445f845b3b33af5718576e2f4c 100644 (file)
@@ -79,7 +79,7 @@ static const struct extension_info known_glx_extensions[] = {
    { GLX(EXT_visual_rating),           VER(0,0), Y, Y, N, N },
    { GLX(MESA_agp_offset),             VER(0,0), N, N, N, Y }, /* Deprecated */
    { GLX(MESA_allocate_memory),        VER(0,0), Y, N, N, Y },
-   { GLX(MESA_copy_sub_buffer),        VER(0,0), N, N, N, N }, /* Deprecated? */
+   { GLX(MESA_copy_sub_buffer),        VER(0,0), Y, N, N, N },
    { GLX(MESA_pixmap_colormap),        VER(0,0), N, N, N, N }, /* Deprecated */
    { GLX(MESA_release_buffers),        VER(0,0), N, N, N, N }, /* Deprecated */
    { GLX(MESA_set_3dfx_mode),          VER(0,0), N, N, N, N }, /* Deprecated */
index 883a89c8886e5671a23e9f19840698a55bb46905..d68837b545a2945f9642029f5f2fb42fbbfa5da1 100644 (file)
@@ -547,6 +547,13 @@ static int64_t driSwapBuffersMSC( __DRInativeDisplay * dpy, void *drawablePriv,
                                                            remainder );
 }
 
+static void driCopySubBuffer( __DRInativeDisplay *dpy, void *drawablePrivate,
+                             int x, int y, int w, int h)
+{
+    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
+    (void) dpy;
+}
 
 /**
  * This is called via __DRIscreenRec's createNewDrawable pointer.
@@ -623,6 +630,9 @@ static void *driCreateNewDrawable(__DRInativeDisplay *dpy,
     pdraw->frameTracking = NULL;
     pdraw->queryFrameTracking = driQueryFrameTracking;
 
+    if (driCompareGLXAPIVersion (20060314) >= 0)
+       pdraw->copySubBuffer = driCopySubBuffer;
+
     /* This special default value is replaced with the configured
      * default value when the drawable is first bound to a direct
      * rendering context. 
index b9b38f39cd676bd23a3534009116a81e630674d8..14c24a0efaab6eb4648f170febf13a83741aba92 100644 (file)
@@ -189,6 +189,8 @@ struct __DriverAPIRec {
     int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
                               int64_t divisor, int64_t remainder );
     /*@}*/
+    void (*CopySubBuffer)(__DRIdrawablePrivate *driDrawPriv,
+                         int x, int y, int w, int h);
 };
 
 
index 508900de3086455f6458c5d4688d87e69dfecf79..974a2497e1d622b38a32223a2f4d36e51b143cb5 100644 (file)
@@ -366,7 +366,8 @@ static void intelWaitForFrameCompletion( intelContextPtr intel )
 /*
  * Copy the back buffer to the front buffer. 
  */
-void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) 
+void intelCopyBuffer( const __DRIdrawablePrivate *dPriv,
+                     const drm_clip_rect_t      *rect)
 {
    intelContextPtr intel;
    GLboolean   missed_target;
@@ -385,15 +386,19 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
    
    LOCK_HARDWARE( intel );
    intelWaitForFrameCompletion( intel );
-   UNLOCK_HARDWARE( intel );
-   driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
 
-   LOCK_HARDWARE( intel );
+   if (!rect)
+   {
+       UNLOCK_HARDWARE( intel );
+       driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
+       LOCK_HARDWARE( intel );
+   }
    {
       const intelScreenPrivate *intelScreen = intel->intelScreen;
       const __DRIdrawablePrivate *dPriv = intel->driDrawable;
       const int nbox = dPriv->numClipRects;
       const drm_clip_rect_t *pbox = dPriv->pClipRects;
+      drm_clip_rect_t box;
       const int cpp = intelScreen->cpp;
       const int pitch = intelScreen->front.pitch; /* in bytes */
       int i;
@@ -429,18 +434,35 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
            continue;
          }
 
+        box = *pbox;
+
+        if (rect)
+        {
+            if (rect->x1 > box.x1)
+                box.x1 = rect->x1;
+            if (rect->y1 > box.y1)
+                box.y1 = rect->y1;
+            if (rect->x2 < box.x2)
+                box.x2 = rect->x2;
+            if (rect->y2 < box.y2)
+                box.y2 = rect->y2;
+
+            if (box.x1 > box.x2 || box.y1 > box.y2)
+                continue;
+        }
+
         BEGIN_BATCH( 8);
         OUT_BATCH( CMD );
         OUT_BATCH( BR13 );
-        OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
-        OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
+        OUT_BATCH( (box.y1 << 16) | box.x1 );
+        OUT_BATCH( (box.y2 << 16) | box.x2 );
 
         if (intel->sarea->pf_current_page == 0) 
            OUT_BATCH( intelScreen->front.offset );
         else
            OUT_BATCH( intelScreen->back.offset );                      
 
-        OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
+        OUT_BATCH( (box.y1 << 16) | box.x1 );
         OUT_BATCH( BR13 & 0xffff );
 
         if (intel->sarea->pf_current_page == 0) 
@@ -454,14 +476,17 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
    UNLOCK_HARDWARE( intel );
 
-   intel->swap_count++;
-   (*dri_interface->getUST)(&ust);
-   if (missed_target) {
-     intel->swap_missed_count++;
-     intel->swap_missed_ust = ust -  intel->swap_ust;
-   }
+   if (!rect)
+   {
+       intel->swap_count++;
+       (*dri_interface->getUST)(&ust);
+       if (missed_target) {
+          intel->swap_missed_count++;
+          intel->swap_missed_ust = ust -  intel->swap_ust;
+       }
    
-   intel->swap_ust = ust;
+       intel->swap_ust = ust;
+   }
 }
 
 
index dcc63b23c8d1f65dc8e0196a8bafe3f69c1d9a69..b0aed89af556124faaf334bcd14db9ed7fd23f11 100644 (file)
@@ -75,7 +75,8 @@ extern void intelRestartInlinePrimitive( intelContextPtr intel );
 extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, 
                                              int primitive, int dwords,
                                              int vertex_size);
-extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
+extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv,
+                            const drm_clip_rect_t      *rect);
 extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
                             GLint cx1, GLint cy1, GLint cw, GLint ch);
 
index c79ce9661c1bcad66dee9a22a541ae38342f228f..7dbc2c8739b85d5d01544d93a65b7e5f1eb469ba 100644 (file)
@@ -722,7 +722,7 @@ void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
         if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
            intelPageFlip( dPriv );
         } else {
-           intelCopyBuffer( dPriv );
+            intelCopyBuffer( dPriv, NULL );
         }
          if (screen->current_rotation != 0) {
             intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
@@ -734,6 +734,29 @@ void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
    }
 }
 
+void intelCopySubBuffer( __DRIdrawablePrivate *dPriv,
+                        int x, int y, int w, int h )
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      intelContextPtr intel;
+      GLcontext *ctx;
+      intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = &intel->ctx;
+      if (ctx->Visual.doubleBufferMode) {
+         intelScreenPrivate *screen = intel->intelScreen;
+        drm_clip_rect_t rect;
+        rect.x1 = x + dPriv->x;
+        rect.y1 = (dPriv->h - y - h) + dPriv->y;
+        rect.x2 = rect.x1 + w;
+        rect.y2 = rect.y1 + h;
+        _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+        intelCopyBuffer( dPriv, &rect );
+      }
+   } else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+   }
+}
 
 void intelInitState( GLcontext *ctx )
 {
index 9ee44ea086070a0f4a178662fa3a6cfeb43899bd..c8649d8243a91ce20648154852927bf9f3b94b8b 100644 (file)
@@ -341,6 +341,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
       (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
       (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
+      (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" );
    }
    
    sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
@@ -534,7 +535,8 @@ static const struct __DriverAPIRec intelAPI = {
    .GetMSC          = driGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
-   .SwapBuffersMSC  = NULL
+   .SwapBuffersMSC  = NULL,
+   .CopySubBuffer   = intelCopySubBuffer
 };
 
 
index 0cdcc140445aca99da51a8f107068e8cf738b641..24cfd9bf8b2c2a82d2dcd9fb9511d6d87f77ff10 100644 (file)
@@ -106,4 +106,7 @@ intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
 extern void
 intelSwapBuffers(__DRIdrawablePrivate *dPriv);
 
+extern void
+intelCopySubBuffer( __DRIdrawablePrivate *dPriv, int x, int y, int w, int h );
+
 #endif
index 0d7df499c096aae9a44665e491a60adf563a0e66..e4d9e264bf9bacc0daf6a84488e035091a1415e6 100644 (file)
@@ -637,7 +637,7 @@ r200SwapBuffers( __DRIdrawablePrivate *dPriv )
             r200PageFlip( dPriv );
          }
          else {
-            r200CopyBuffer( dPriv );
+            r200CopyBuffer( dPriv, NULL );
          }
       }
    }
@@ -647,6 +647,30 @@ r200SwapBuffers( __DRIdrawablePrivate *dPriv )
    }
 }
 
+void
+r200CopySubBuffer( __DRIdrawablePrivate *dPriv,
+                  int x, int y, int w, int h )
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      r200ContextPtr rmesa;
+      GLcontext *ctx;
+      rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = rmesa->glCtx;
+      if (ctx->Visual.doubleBufferMode) {
+        drm_clip_rect_t rect;
+        rect.x1 = x + dPriv->x;
+        rect.y1 = (dPriv->h - y - h) + dPriv->y;
+        rect.x2 = rect.x1 + w;
+        rect.y2 = rect.y1 + h;
+         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+        r200CopyBuffer( dPriv, &rect );
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
+   }
+}
 
 /* Force the context `c' to be the current context and associate with it
  * buffer `b'.
index eee72bdacbb0f4c340643af6dc45db1f5a86efbf..faf1b96a2b808d8fbb7c129e8f293f5aa1624649 100644 (file)
@@ -1006,6 +1006,8 @@ extern GLboolean r200CreateContext( const __GLcontextModes *glVisual,
                                    __DRIcontextPrivate *driContextPriv,
                                    void *sharedContextPrivate);
 extern void r200SwapBuffers( __DRIdrawablePrivate *dPriv );
+extern void r200CopySubBuffer( __DRIdrawablePrivate * dPriv,
+                              int x, int y, int w, int h );
 extern GLboolean r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
                                  __DRIdrawablePrivate *driDrawPriv,
                                  __DRIdrawablePrivate *driReadPriv );
index 5a2f7e2ad619211f5d7789bba0c3e4c299458bc2..ae0f35cb398619304fddc2741f1b04a99e6602c6 100644 (file)
@@ -420,7 +420,8 @@ static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
 
 /* Copy the back color buffer to the front color buffer.
  */
-void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
+void r200CopyBuffer( const __DRIdrawablePrivate *dPriv,
+                     const drm_clip_rect_t      *rect)
 {
    r200ContextPtr rmesa;
    GLint nbox, i, ret;
@@ -446,9 +447,12 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
     * request at a time.
     */
    r200WaitForFrameCompletion( rmesa );
-   UNLOCK_HARDWARE( rmesa );
-   driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
-   LOCK_HARDWARE( rmesa );
+   if (!rect)
+   {
+       UNLOCK_HARDWARE( rmesa );
+       driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+       LOCK_HARDWARE( rmesa );
+   }
 
    nbox = dPriv->numClipRects; /* must be in locked region */
 
@@ -459,8 +463,27 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
       GLint n = 0;
 
       for ( ; i < nr ; i++ ) {
-        *b++ = box[i];
-        n++;
+
+         *b = box[i];
+
+         if (rect)
+         {
+            if (rect->x1 > b->x1)
+                b->x1 = rect->x1;
+            if (rect->y1 > b->y1)
+                b->y1 = rect->y1;
+            if (rect->x2 < b->x2)
+                b->x2 = rect->x2;
+            if (rect->y2 < b->y2)
+                b->y2 = rect->y2;
+
+            if (b->x1 < b->x2 && b->y1 < b->y2)
+                b++;
+         }
+         else
+             b++;
+
+         n++;
       }
       rmesa->sarea->nbox = n;
 
@@ -474,18 +497,21 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
    }
 
    UNLOCK_HARDWARE( rmesa );
-   rmesa->hw.all_dirty = GL_TRUE;
+   if (!rect)
+   {
+       rmesa->hw.all_dirty = GL_TRUE;
 
-   rmesa->swap_count++;
-   (*dri_interface->getUST)( & ust );
-   if ( missed_target ) {
-      rmesa->swap_missed_count++;
-      rmesa->swap_missed_ust = ust - rmesa->swap_ust;
-   }
+       rmesa->swap_count++;
+       (*dri_interface->getUST)( & ust );
+       if ( missed_target ) {
+          rmesa->swap_missed_count++;
+          rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+       }
 
-   rmesa->swap_ust = ust;
+       rmesa->swap_ust = ust;
 
-   sched_yield();
+       sched_yield();
+   }
 }
 
 void r200PageFlip( const __DRIdrawablePrivate *dPriv )
index cf4188afe895e1829e287b369506fc9df3b37feb..f53752739d217eb9de5f982a80c034f64b452ca5 100644 (file)
@@ -90,7 +90,8 @@ extern void r200ReleaseDmaRegion( r200ContextPtr rmesa,
                                    struct r200_dma_region *region,
                                    const char *caller );
 
-extern void r200CopyBuffer( const __DRIdrawablePrivate *drawable );
+extern void r200CopyBuffer( const __DRIdrawablePrivate *drawable,
+                           const drm_clip_rect_t      *rect);
 extern void r200PageFlip( const __DRIdrawablePrivate *drawable );
 extern void r200Flush( GLcontext *ctx );
 extern void r200Finish( GLcontext *ctx );
index 0a957816dbf7f08938a9d1b7348a397527567672..4e351dd66b093898251179473bf12780913f78ce 100644 (file)
@@ -231,7 +231,7 @@ void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
                        if (radeon->doPageFlip) {
                                radeonPageFlip(dPriv);
                        } else {
-                               radeonCopyBuffer(dPriv);
+                           radeonCopyBuffer(dPriv, NULL);
                        }
                }
        } else {
@@ -241,6 +241,31 @@ void radeonSwapBuffers(__DRIdrawablePrivate * dPriv)
        }
 }
 
+void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+                        int x, int y, int w, int h )
+{
+    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+       radeonContextPtr radeon;
+       GLcontext *ctx;
+
+       radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+       ctx = radeon->glCtx;
+
+       if (ctx->Visual.doubleBufferMode) {
+           drm_clip_rect_t rect;
+           rect.x1 = x + dPriv->x;
+           rect.y1 = (dPriv->h - y - h) + dPriv->y;
+           rect.x2 = rect.x1 + w;
+           rect.y2 = rect.y1 + h;
+           _mesa_notifySwapBuffers(ctx);       /* flush pending rendering comands */
+           radeonCopyBuffer(dPriv, &rect);
+       }
+    } else {
+       /* XXX this shouldn't be an error but we can't handle it for now */
+       _mesa_problem(NULL, "%s: drawable has no context!",
+                     __FUNCTION__);
+    }
+}
 
 /* Force the context `c' to be the current context and associate with it
  * buffer `b'.
index 671c14df0307779a293ecd1b53e54ad923473309..4eeb4edcfd4ffd68f6566f1d66404b78649f9d88 100644 (file)
@@ -203,6 +203,8 @@ struct radeon_context {
 #define RADEON_CONTEXT(glctx) ((radeonContextPtr)(ctx->DriverCtx))
 
 extern void radeonSwapBuffers(__DRIdrawablePrivate * dPriv);
+extern void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+                               int x, int y, int w, int h);
 extern GLboolean radeonInitContext(radeonContextPtr radeon,
                                   struct dd_function_table* functions,
                                   const __GLcontextModes * glVisual,
index f562762878356049b32a76b7793eecb1b889fb6f..798e83c0107c8ff5e0166cb326848952ab5714f2 100644 (file)
@@ -164,7 +164,8 @@ static void radeonWaitForFrameCompletion(radeonContextPtr radeon)
 
 /* Copy the back color buffer to the front color buffer.
  */
-void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv)
+void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv,
+                     const drm_clip_rect_t      * rect)
 {
        radeonContextPtr radeon;
        GLint nbox, i, ret;
@@ -193,10 +194,13 @@ void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv)
         * request at a time.
         */
        radeonWaitForFrameCompletion(radeon);
-       UNLOCK_HARDWARE(radeon);
-       driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags,
-                        &missed_target);
-       LOCK_HARDWARE(radeon);
+       if (!rect)
+       {
+           UNLOCK_HARDWARE(radeon);
+           driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags,
+                            &missed_target);
+           LOCK_HARDWARE(radeon);
+       }
 
        nbox = dPriv->numClipRects;     /* must be in locked region */
 
@@ -206,9 +210,28 @@ void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv)
                drm_clip_rect_t *b = radeon->sarea->boxes;
                GLint n = 0;
 
-               for (; i < nr; i++) {
-                       *b++ = box[i];
-                       n++;
+               for ( ; i < nr ; i++ ) {
+
+                   *b = box[i];
+
+                   if (rect)
+                   {
+                       if (rect->x1 > b->x1)
+                           b->x1 = rect->x1;
+                       if (rect->y1 > b->y1)
+                           b->y1 = rect->y1;
+                       if (rect->x2 < b->x2)
+                           b->x2 = rect->x2;
+                       if (rect->y2 < b->y2)
+                           b->y2 = rect->y2;
+
+                       if (b->x1 < b->x2 && b->y1 < b->y2)
+                           b++;
+                   }
+                   else
+                       b++;
+
+                   n++;
                }
                radeon->sarea->nbox = n;
 
@@ -223,22 +246,24 @@ void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv)
        }
 
        UNLOCK_HARDWARE(radeon);
-
-       if (IS_R200_CLASS(radeon->radeonScreen))
+       if (!rect)
+       {
+           if (IS_R200_CLASS(radeon->radeonScreen))
                ((r200ContextPtr)radeon)->hw.all_dirty = GL_TRUE;
-       else
+           else
                ((r300ContextPtr)radeon)->hw.all_dirty = GL_TRUE;
 
-       radeon->swap_count++;
-       (*dri_interface->getUST) (&ust);
-       if (missed_target) {
+           radeon->swap_count++;
+           (*dri_interface->getUST) (&ust);
+           if (missed_target) {
                radeon->swap_missed_count++;
                radeon->swap_missed_ust = ust - radeon->swap_ust;
-       }
+           }
 
-       radeon->swap_ust = ust;
+           radeon->swap_ust = ust;
 
-       sched_yield();
+           sched_yield();
+       }
 }
 
 void radeonPageFlip(const __DRIdrawablePrivate * dPriv)
index 4ddd776602d5cb4492d8e70eafb76b9fc7776a3f..b53767510e84cc08062e82a181c5e2507ba119fd 100644 (file)
@@ -44,7 +44,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r200_context.h"
 #include "radeon_drm.h"
 
-extern void radeonCopyBuffer(const __DRIdrawablePrivate * drawable);
+extern void radeonCopyBuffer(const __DRIdrawablePrivate * drawable,
+                            const drm_clip_rect_t      * rect);
 extern void radeonPageFlip(const __DRIdrawablePrivate * drawable);
 extern void radeonFlush(GLcontext * ctx);
 extern void radeonFinish(GLcontext * ctx);
index f546731ad448f020a6ca901f8863f1f13a9d5e6d..791d1a37bc01533f05cc329bd1d2937464bc29fc 100644 (file)
@@ -572,7 +572,7 @@ radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
             radeonPageFlip( dPriv );
          }
          else {
-            radeonCopyBuffer( dPriv );
+            radeonCopyBuffer( dPriv, NULL );
          }
       }
    }
@@ -582,6 +582,31 @@ radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
    }
 }
 
+void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+                        int x, int y, int w, int h )
+{
+    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+       radeonContextPtr radeon;
+       GLcontext *ctx;
+
+       radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+       ctx = radeon->glCtx;
+
+       if (ctx->Visual.doubleBufferMode) {
+           drm_clip_rect_t rect;
+           rect.x1 = x + dPriv->x;
+           rect.y1 = (dPriv->h - y - h) + dPriv->y;
+           rect.x2 = rect.x1 + w;
+           rect.y2 = rect.y1 + h;
+           _mesa_notifySwapBuffers(ctx);       /* flush pending rendering comands */
+           radeonCopyBuffer(dPriv, &rect);
+       }
+    } else {
+       /* XXX this shouldn't be an error but we can't handle it for now */
+       _mesa_problem(NULL, "%s: drawable has no context!",
+                     __FUNCTION__);
+    }
+}
 
 /* Make context `c' the current context and bind it to the given
  * drawing and reading surfaces.
index 09fa948ccba2e922062224122e1f1de050cf5823..9abd8667308fea01fed4e0ad7e5981bd6787a8ab 100644 (file)
@@ -850,6 +850,8 @@ extern GLboolean radeonCreateContext(const __GLcontextModes *glVisual,
                                     __DRIcontextPrivate *driContextPriv,
                                     void *sharedContextPrivate);
 extern void radeonSwapBuffers( __DRIdrawablePrivate *dPriv );
+extern void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv,
+                               int x, int y, int w, int h);
 extern GLboolean radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
                                    __DRIdrawablePrivate *driDrawPriv,
                                    __DRIdrawablePrivate *driReadPriv );
index fa22cbd6f9298fd0732bc4a7b7026706df22cc71..53f6f57057bb22a0ddb4c2fe96e67bf54d82b5a2 100644 (file)
@@ -875,7 +875,8 @@ static void radeonWaitForFrameCompletion( radeonContextPtr rmesa )
 
 /* Copy the back color buffer to the front color buffer.
  */
-void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
+void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv,
+                      const drm_clip_rect_t      *rect)
 {
    radeonContextPtr rmesa;
    GLint nbox, i, ret;
@@ -899,9 +900,12 @@ void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
     * request at a time.
     */
    radeonWaitForFrameCompletion( rmesa );
-   UNLOCK_HARDWARE( rmesa );
-   driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
-   LOCK_HARDWARE( rmesa );
+   if (!rect)
+   {
+       UNLOCK_HARDWARE( rmesa );
+       driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+       LOCK_HARDWARE( rmesa );
+   }
 
    nbox = dPriv->numClipRects; /* must be in locked region */
 
@@ -912,8 +916,27 @@ void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
       GLint n = 0;
 
       for ( ; i < nr ; i++ ) {
-        *b++ = box[i];
-        n++;
+
+         *b = box[i];
+
+         if (rect)
+         {
+             if (rect->x1 > b->x1)
+                 b->x1 = rect->x1;
+             if (rect->y1 > b->y1)
+                 b->y1 = rect->y1;
+             if (rect->x2 < b->x2)
+                 b->x2 = rect->x2;
+             if (rect->y2 < b->y2)
+                 b->y2 = rect->y2;
+
+             if (b->x1 < b->x2 && b->y1 < b->y2)
+                 b++;
+         }
+         else
+             b++;
+
+         n++;
       }
       rmesa->sarea->nbox = n;
 
@@ -927,15 +950,18 @@ void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
    }
 
    UNLOCK_HARDWARE( rmesa );
-   rmesa->swap_count++;
-   (*dri_interface->getUST)( & ust );
-   if ( missed_target ) {
-      rmesa->swap_missed_count++;
-      rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+   if (!rect)
+   {
+       rmesa->swap_count++;
+       (*dri_interface->getUST)( & ust );
+       if ( missed_target ) {
+          rmesa->swap_missed_count++;
+          rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+       }
+
+       rmesa->swap_ust = ust;
+       rmesa->hw.all_dirty = GL_TRUE;
    }
-
-   rmesa->swap_ust = ust;
-   rmesa->hw.all_dirty = GL_TRUE;
 }
 
 void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
index dd7ed19b8471d355980e27b190688a0e2348a580..335ed77c9ad9b9b1e6d979da559216d1b8687fba 100644 (file)
@@ -87,7 +87,8 @@ extern void radeonReleaseDmaRegion( radeonContextPtr rmesa,
                                    struct radeon_dma_region *region,
                                    const char *caller );
 
-extern void radeonCopyBuffer( const __DRIdrawablePrivate *drawable );
+extern void radeonCopyBuffer( const __DRIdrawablePrivate *drawable,
+                             const drm_clip_rect_t      *rect);
 extern void radeonPageFlip( const __DRIdrawablePrivate *drawable );
 extern void radeonFlush( GLcontext *ctx );
 extern void radeonFinish( GLcontext *ctx );
index a93cfb3821c9cb67b6de8b0a74bee7833189e678..5257e541e5f4e0e7c5450a9a7ef2668673d1611e 100644 (file)
@@ -716,6 +716,8 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
       (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
       if (IS_R200_CLASS(screen))
         (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
+
+      (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" );
    }
 
 #if RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
@@ -923,7 +925,8 @@ static struct __DriverAPIRec radeonAPI = {
    .GetMSC          = driGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
-   .SwapBuffersMSC  = NULL
+   .SwapBuffersMSC  = NULL,
+   .CopySubBuffer   = radeonCopySubBuffer,
 };
 #else
 static const struct __DriverAPIRec r200API = {
@@ -940,7 +943,8 @@ static const struct __DriverAPIRec r200API = {
    .GetMSC          = driGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
-   .SwapBuffersMSC  = NULL
+   .SwapBuffersMSC  = NULL,
+   .CopySubBuffer   = r200CopySubBuffer
 };
 #endif