summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2006-03-31 15:48:04 +0000
committerBrian Paul <[email protected]>2006-03-31 15:48:04 +0000
commitf2ad1b60c0da11283b399008f491792790cea294 (patch)
treeed81cb738dd06f961713fb9e34827a3b57832cca /src
parentdf3d4e0bb9ce40b3380734cf4f209a7363d5dcfd (diff)
Dave Reveman's patch for GLX_MESA_copy_sub_buffer support
Diffstat (limited to 'src')
-rw-r--r--src/glx/x11/glxcmds.c70
-rw-r--r--src/glx/x11/glxextensions.c2
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c10
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h2
-rw-r--r--src/mesa/drivers/dri/i915/intel_batchbuffer.c53
-rw-r--r--src/mesa/drivers/dri/i915/intel_batchbuffer.h3
-rw-r--r--src/mesa/drivers/dri/i915/intel_context.c25
-rw-r--r--src/mesa/drivers/dri/i915/intel_screen.c4
-rw-r--r--src/mesa/drivers/dri/i915/intel_screen.h3
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.c26
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.h2
-rw-r--r--src/mesa/drivers/dri/r200/r200_ioctl.c56
-rw-r--r--src/mesa/drivers/dri/r200/r200_ioctl.h3
-rw-r--r--src/mesa/drivers/dri/r300/radeon_context.c27
-rw-r--r--src/mesa/drivers/dri/r300/radeon_context.h2
-rw-r--r--src/mesa/drivers/dri/r300/radeon_ioctl.c59
-rw-r--r--src/mesa/drivers/dri/r300/radeon_ioctl.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.c27
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.c54
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_ioctl.h3
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c8
22 files changed, 363 insertions, 81 deletions
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index d4f579d01ac..16f7e96150a 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -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;
}
diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c
index 0cee71f6c3a..c3bc93009aa 100644
--- a/src/glx/x11/glxextensions.c
+++ b/src/glx/x11/glxextensions.c
@@ -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 */
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 883a89c8886..d68837b545a 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -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.
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index b9b38f39cd6..14c24a0efaa 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -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);
};
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c
index 508900de308..974a2497e1d 100644
--- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c
@@ -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;
+ }
}
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.h b/src/mesa/drivers/dri/i915/intel_batchbuffer.h
index dcc63b23c8d..b0aed89af55 100644
--- a/src/mesa/drivers/dri/i915/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.h
@@ -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);
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index c79ce9661c1..7dbc2c8739b 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -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 )
{
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 9ee44ea0860..c8649d8243a 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -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
};
diff --git a/src/mesa/drivers/dri/i915/intel_screen.h b/src/mesa/drivers/dri/i915/intel_screen.h
index 0cdcc140445..24cfd9bf8b2 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.h
+++ b/src/mesa/drivers/dri/i915/intel_screen.h
@@ -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
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index 0d7df499c09..e4d9e264bf9 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -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'.
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index eee72bdacbb..faf1b96a2b8 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -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 );
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.c b/src/mesa/drivers/dri/r200/r200_ioctl.c
index 5a2f7e2ad61..ae0f35cb398 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.c
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.c
@@ -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 )
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.h b/src/mesa/drivers/dri/r200/r200_ioctl.h
index cf4188afe89..f53752739d2 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.h
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.h
@@ -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 );
diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c
index 0a957816dbf..4e351dd66b0 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.c
+++ b/src/mesa/drivers/dri/r300/radeon_context.c
@@ -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'.
diff --git a/src/mesa/drivers/dri/r300/radeon_context.h b/src/mesa/drivers/dri/r300/radeon_context.h
index 671c14df030..4eeb4edcfd4 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.h
+++ b/src/mesa/drivers/dri/r300/radeon_context.h
@@ -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,
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.c b/src/mesa/drivers/dri/r300/radeon_ioctl.c
index f5627628783..798e83c0107 100644
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.c
+++ b/src/mesa/drivers/dri/r300/radeon_ioctl.c
@@ -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)
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.h b/src/mesa/drivers/dri/r300/radeon_ioctl.h
index 4ddd776602d..b53767510e8 100644
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.h
+++ b/src/mesa/drivers/dri/r300/radeon_ioctl.h
@@ -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);
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index f546731ad44..791d1a37bc0 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -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.
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
index 09fa948ccba..9abd8667308 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -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 );
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
index fa22cbd6f92..53f6f57057b 100644
--- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
@@ -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 )
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.h b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
index dd7ed19b847..335ed77c9ad 100644
--- a/src/mesa/drivers/dri/radeon/radeon_ioctl.h
+++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
@@ -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 );
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index a93cfb3821c..5257e541e5f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -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