On Mon, 2006-03-13 at 10:45 -0800, Ian Romanick wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > David Reveman wrote: > > This patch adds direct and indirect rendering support for > > GLX_MESA_copy_sub_buffer. Intel, r200 and r300 drivers are the only > > drivers I've implemented support for so far. I've only tried the intel > > implementation and that seems to be working OK. I've attached a patch > > for CVS head and one for 6.4.2. > > I think the spec for this extension and the code implementing it needs a > slight update. The problem is that the extension assumes that > SwapBuffers is implemented by copying the back buffer to the front. > However, this is *not* always the case. The result is that this > extension does not produce the desired results with page flipping. > > However, it is possible for an application to detect / request the copy > behavior by using GLX_OML_swap_method. An fbconfig with copy semantics > can be requested by using "GLX_SWAP_METHOD_OML, GLX_SWAP_COPY_OML" in > the attribs list. If not particular method is requested, the current > method can be queried via glXGetFBConfigAttrib. > > The only rub is that most of our drivers only advertise a > GLX_SWAP_METHOD_OML of GLX_SWAP_UNDEFINED_OML. This is because, in the > drivers that support page-flipping, we switch between GLX_SWAP_COPY_OML > and GLX_SWAP_EXCHANGE_OML on the fly. We can easilly modify the drivers > to adverteise GLX_SWAP_COPY_OML fbconfigs and enforce that behavior. > > Currently none of the drivers actually advertise GLX_SWAP_EXCHANGE_OML > fbconfigs. > > http://oss.sgi.com/projects/ogl-sample/registry/OML/glx_swap_method.txt > > My opinion is that we should modify GLX_MESA_copy_sub_buffer to, at the > very least, note that the desired behavior is only guaranteed for the > GLX_SWAP_COPY_OML case. We may even want to say that, if > GLX_OML_swap_method is supported, it is an error to call > glXCopySubBufferMESA when GLX_SWAP_METHOD_OML is not GLX_SWAP_COPY_OML. > > Dunno. > > I have a few comments about the patches, but nothing too major... > > > --- include/GL/internal/dri_interface.h 29 Nov 2005 23:01:43 -0000 > > 1.17 > > +++ include/GL/internal/dri_interface.h 12 Mar 2006 15:58:04 -0000 > > @@ -472,6 +472,9 @@ > > * \since Internal API version 20030317. > > */ > > unsigned swap_interval; > > + > > + void (*copySubBuffer)(__DRInativeDisplay *dpy, void *drawablePrivate, > > + int x, int y, int w, int h); > > }; > > Please add a \since comment here and bump the internal version. You'll > also need to update __glXGetInternalVersion (glxcmds.c). > > > --- src/glx/x11/glxextensions.c 24 Feb 2006 15:36:24 -0000 1.13 > > +++ src/glx/x11/glxextensions.c 12 Mar 2006 15:58:41 -0000 > > @@ -79,7 +79,7 @@ > > { 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, Y, N, N }, /* > > Deprecated? */ > > This should be "Y, N, N, N". Setting direct_support here means that the > extension is enable without the driver explicitly enabling it. Since > not all drivers will set the copySubBuffer pointer, I assume that's not > what you want. :) > > I'll update the field comments in the extension_info structure today. > It's not very clear. Sorry. > > > { 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 */ > > --- src/mesa/drivers/dri/common/dri_util.c 29 Nov 2005 23:01:43 -0000 > > 1.29 > > +++ src/mesa/drivers/dri/common/dri_util.c 12 Mar 2006 15:58:46 -0000 > > @@ -547,6 +547,13 @@ > > 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. > > @@ -622,6 +629,7 @@ > > pdraw->swapBuffersMSC = driSwapBuffersMSC; > > pdraw->frameTracking = NULL; > > pdraw->queryFrameTracking = driQueryFrameTracking; > > + pdraw->copySubBuffer = driCopySubBuffer; > > After bumping the API version, this code will need to verify that > api_ver is new enough for this field to exist.
I've updated my patch. -David
--- include/GL/internal/dri_interface.h 29 Nov 2005 23:01:43 -0000 1.17 +++ include/GL/internal/dri_interface.h 14 Mar 2006 12:26:53 -0000 @@ -472,6 +472,14 @@ * \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 --- src/glx/x11/glxcmds.c 9 Mar 2006 16:25:46 -0000 1.13 +++ src/glx/x11/glxcmds.c 14 Mar 2006 12:27:49 -0000 @@ -2570,18 +2570,69 @@ 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 @@ * 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; } --- src/glx/x11/glxextensions.c 24 Feb 2006 15:36:24 -0000 1.13 +++ src/glx/x11/glxextensions.c 14 Mar 2006 12:27:50 -0000 @@ -79,7 +79,7 @@ { 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 */ --- src/mesa/drivers/dri/common/dri_util.c 29 Nov 2005 23:01:43 -0000 1.29 +++ src/mesa/drivers/dri/common/dri_util.c 14 Mar 2006 12:27:59 -0000 @@ -547,6 +547,13 @@ 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 @@ 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. --- src/mesa/drivers/dri/common/dri_util.h 29 Nov 2005 23:01:43 -0000 1.21 +++ src/mesa/drivers/dri/common/dri_util.h 14 Mar 2006 12:27:59 -0000 @@ -189,6 +189,8 @@ int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc, int64_t divisor, int64_t remainder ); /[EMAIL PROTECTED]/ + void (*CopySubBuffer)(__DRIdrawablePrivate *driDrawPriv, + int x, int y, int w, int h); }; --- src/mesa/drivers/dri/i915/intel_batchbuffer.c 6 Feb 2006 00:09:58 -0000 1.6 +++ src/mesa/drivers/dri/i915/intel_batchbuffer.c 14 Mar 2006 12:28:09 -0000 @@ -366,7 +366,8 @@ /* * 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 @@ 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 @@ 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 @@ 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; + } } --- src/mesa/drivers/dri/i915/intel_batchbuffer.h 23 Jan 2006 10:10:48 -0000 1.3 +++ src/mesa/drivers/dri/i915/intel_batchbuffer.h 14 Mar 2006 12:28:09 -0000 @@ -75,7 +75,8 @@ 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); --- src/mesa/drivers/dri/i915/intel_context.c 6 Feb 2006 00:09:58 -0000 1.22 +++ src/mesa/drivers/dri/i915/intel_context.c 14 Mar 2006 12:28:10 -0000 @@ -722,7 +722,7 @@ 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 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 ) { --- src/mesa/drivers/dri/i915/intel_screen.c 8 Feb 2006 22:05:42 -0000 1.35 +++ src/mesa/drivers/dri/i915/intel_screen.c 14 Mar 2006 12:28:10 -0000 @@ -341,6 +341,7 @@ (*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 @@ .GetMSC = driGetMSC32, .WaitForMSC = driWaitForMSC32, .WaitForSBC = NULL, - .SwapBuffersMSC = NULL + .SwapBuffersMSC = NULL, + .CopySubBuffer = intelCopySubBuffer }; --- src/mesa/drivers/dri/i915/intel_screen.h 23 Jan 2006 10:10:48 -0000 1.6 +++ src/mesa/drivers/dri/i915/intel_screen.h 14 Mar 2006 12:28:10 -0000 @@ -106,4 +106,7 @@ extern void intelSwapBuffers(__DRIdrawablePrivate *dPriv); +extern void +intelCopySubBuffer( __DRIdrawablePrivate *dPriv, int x, int y, int w, int h ); + #endif --- src/mesa/drivers/dri/r200/r200_context.c 3 Feb 2006 13:29:11 -0000 1.55 +++ src/mesa/drivers/dri/r200/r200_context.c 14 Mar 2006 12:28:14 -0000 @@ -637,7 +637,7 @@ r200PageFlip( dPriv ); } else { - r200CopyBuffer( dPriv ); + r200CopyBuffer( dPriv, NULL ); } } } @@ -647,6 +647,30 @@ } } +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'. --- src/mesa/drivers/dri/r200/r200_context.h 2 Nov 2005 01:15:08 -0000 1.37 +++ src/mesa/drivers/dri/r200/r200_context.h 14 Mar 2006 12:28:14 -0000 @@ -1002,6 +1002,8 @@ __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 ); --- src/mesa/drivers/dri/r200/r200_ioctl.c 2 Nov 2005 01:15:08 -0000 1.32 +++ src/mesa/drivers/dri/r200/r200_ioctl.c 14 Mar 2006 12:28:14 -0000 @@ -420,7 +420,8 @@ /* 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 @@ * 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 @@ 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 @@ } 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 ) --- src/mesa/drivers/dri/r200/r200_ioctl.h 11 Oct 2005 17:55:54 -0000 1.14 +++ src/mesa/drivers/dri/r200/r200_ioctl.h 14 Mar 2006 12:28:14 -0000 @@ -90,7 +90,8 @@ 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 ); --- src/mesa/drivers/dri/r300/radeon_context.c 17 Dec 2005 11:39:40 -0000 1.8 +++ src/mesa/drivers/dri/r300/radeon_context.c 14 Mar 2006 12:28:17 -0000 @@ -229,7 +229,7 @@ if (radeon->doPageFlip) { radeonPageFlip(dPriv); } else { - radeonCopyBuffer(dPriv); + radeonCopyBuffer(dPriv, NULL); } } } else { @@ -239,6 +239,31 @@ } } +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'. --- src/mesa/drivers/dri/r300/radeon_context.h 3 Sep 2005 16:40:44 -0000 1.7 +++ src/mesa/drivers/dri/r300/radeon_context.h 14 Mar 2006 12:28:17 -0000 @@ -203,6 +203,8 @@ #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, --- src/mesa/drivers/dri/r300/radeon_ioctl.c 2 Nov 2005 01:15:08 -0000 1.9 +++ src/mesa/drivers/dri/r300/radeon_ioctl.c 14 Mar 2006 12:28:17 -0000 @@ -145,7 +145,8 @@ /* 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; @@ -174,10 +175,13 @@ * 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 */ @@ -187,9 +191,28 @@ 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; @@ -204,22 +227,24 @@ } 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) --- src/mesa/drivers/dri/r300/radeon_ioctl.h 20 Jul 2005 21:35:27 -0000 1.2 +++ src/mesa/drivers/dri/r300/radeon_ioctl.h 14 Mar 2006 12:28:17 -0000 @@ -44,7 +44,8 @@ #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); --- src/mesa/drivers/dri/radeon/radeon_context.c 3 Feb 2006 13:29:11 -0000 1.48 +++ src/mesa/drivers/dri/radeon/radeon_context.c 14 Mar 2006 12:28:18 -0000 @@ -572,7 +572,7 @@ radeonPageFlip( dPriv ); } else { - radeonCopyBuffer( dPriv ); + radeonCopyBuffer( dPriv, NULL ); } } } @@ -582,6 +582,31 @@ } } +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. --- src/mesa/drivers/dri/radeon/radeon_context.h 15 Oct 2005 23:45:54 -0000 1.27 +++ src/mesa/drivers/dri/radeon/radeon_context.h 14 Mar 2006 12:28:18 -0000 @@ -846,6 +846,8 @@ __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 ); --- src/mesa/drivers/dri/radeon/radeon_ioctl.c 2 Nov 2005 01:15:07 -0000 1.30 +++ src/mesa/drivers/dri/radeon/radeon_ioctl.c 14 Mar 2006 12:28:18 -0000 @@ -875,7 +875,8 @@ /* 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 @@ * 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 @@ 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 @@ } 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 ) --- src/mesa/drivers/dri/radeon/radeon_ioctl.h 11 Oct 2005 17:55:54 -0000 1.7 +++ src/mesa/drivers/dri/radeon/radeon_ioctl.h 14 Mar 2006 12:28:18 -0000 @@ -87,7 +87,8 @@ 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 ); --- src/mesa/drivers/dri/radeon/radeon_screen.c 7 Mar 2006 05:31:36 -0000 1.54 +++ src/mesa/drivers/dri/radeon/radeon_screen.c 14 Mar 2006 12:28:18 -0000 @@ -708,6 +708,8 @@ (*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) @@ -915,7 +917,8 @@ .GetMSC = driGetMSC32, .WaitForMSC = driWaitForMSC32, .WaitForSBC = NULL, - .SwapBuffersMSC = NULL + .SwapBuffersMSC = NULL, + .CopySubBuffer = radeonCopySubBuffer, }; #else static const struct __DriverAPIRec r200API = { @@ -932,7 +935,8 @@ .GetMSC = driGetMSC32, .WaitForMSC = driWaitForMSC32, .WaitForSBC = NULL, - .SwapBuffersMSC = NULL + .SwapBuffersMSC = NULL, + .CopySubBuffer = r200CopySubBuffer }; #endif