diff -ur ../Mesa-6.4.2/include/GL/internal/dri_interface.h ./include/GL/internal/dri_interface.h --- ../Mesa-6.4.2/include/GL/internal/dri_interface.h 2005-11-30 00:01:57.000000000 +0100 +++ ./include/GL/internal/dri_interface.h 2006-03-12 17:11:43.000000000 +0100 @@ -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); }; #endif diff -ur ../Mesa-6.4.2/src/glx/x11/glxcmds.c ./src/glx/x11/glxcmds.c --- ../Mesa-6.4.2/src/glx/x11/glxcmds.c 2005-08-11 16:18:53.000000000 +0200 +++ ./src/glx/x11/glxcmds.c 2006-03-12 17:11:43.000000000 +0100 @@ -2569,18 +2569,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 ) { diff -ur ../Mesa-6.4.2/src/glx/x11/glxextensions.c ./src/glx/x11/glxextensions.c --- ../Mesa-6.4.2/src/glx/x11/glxextensions.c 2005-08-11 16:18:53.000000000 +0200 +++ ./src/glx/x11/glxextensions.c 2006-03-12 17:11:43.000000000 +0100 @@ -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? */ { 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 -ur ../Mesa-6.4.2/src/mesa/drivers/dri/common/dri_util.c ./src/mesa/drivers/dri/common/dri_util.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/common/dri_util.c 2005-11-30 00:01:57.000000000 +0100 +++ ./src/mesa/drivers/dri/common/dri_util.c 2006-03-12 17:11:43.000000000 +0100 @@ -545,6 +545,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. @@ -620,6 +627,7 @@ pdraw->swapBuffersMSC = driSwapBuffersMSC; pdraw->frameTracking = NULL; pdraw->queryFrameTracking = driQueryFrameTracking; + pdraw->copySubBuffer = driCopySubBuffer; /* This special default value is replaced with the configured * default value when the drawable is first bound to a direct diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/common/dri_util.h ./src/mesa/drivers/dri/common/dri_util.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/common/dri_util.h 2005-11-30 00:01:57.000000000 +0100 +++ ./src/mesa/drivers/dri/common/dri_util.h 2006-03-12 17:11:43.000000000 +0100 @@ -189,6 +189,8 @@ 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 -ur ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_batchbuffer.c ./src/mesa/drivers/dri/i915/intel_batchbuffer.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_batchbuffer.c 2005-05-04 22:11:37.000000000 +0200 +++ ./src/mesa/drivers/dri/i915/intel_batchbuffer.c 2006-03-12 17:17:26.000000000 +0100 @@ -318,7 +318,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; @@ -338,6 +339,7 @@ __DRIdrawablePrivate *dPriv = intel->driDrawable; int nbox = dPriv->numClipRects; drm_clip_rect_t *pbox = dPriv->pClipRects; + drm_clip_rect_t box; int pitch = intelScreen->frontPitch; int cpp = intelScreen->cpp; int i; @@ -370,19 +372,36 @@ pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) 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->frontOffset ); else OUT_BATCH( intelScreen->backOffset ); - 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) diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_batchbuffer.h ./src/mesa/drivers/dri/i915/intel_batchbuffer.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_batchbuffer.h 2004-06-18 12:54:48.000000000 +0200 +++ ./src/mesa/drivers/dri/i915/intel_batchbuffer.h 2006-03-12 17:11:43.000000000 +0100 @@ -74,7 +74,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); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_context.c ./src/mesa/drivers/dri/i915/intel_context.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_context.c 2005-09-10 18:44:26.000000000 +0200 +++ ./src/mesa/drivers/dri/i915/intel_context.c 2006-03-12 17:11:43.000000000 +0100 @@ -617,7 +617,7 @@ if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ intelPageFlip( dPriv ); } else { - intelCopyBuffer( dPriv ); + intelCopyBuffer( dPriv, NULL ); } } } else { @@ -626,6 +626,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 ) { diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_screen.c ./src/mesa/drivers/dri/i915/intel_screen.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_screen.c 2005-08-15 08:59:24.000000000 +0200 +++ ./src/mesa/drivers/dri/i915/intel_screen.c 2006-03-12 17:11:43.000000000 +0100 @@ -202,6 +202,7 @@ if (glx_enable_extension != NULL) { (*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; @@ -364,7 +365,8 @@ .GetMSC = NULL, .WaitForMSC = NULL, .WaitForSBC = NULL, - .SwapBuffersMSC = NULL + .SwapBuffersMSC = NULL, + .CopySubBuffer = intelCopySubBuffer }; diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_screen.h ./src/mesa/drivers/dri/i915/intel_screen.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/i915/intel_screen.h 2004-10-08 01:30:29.000000000 +0200 +++ ./src/mesa/drivers/dri/i915/intel_screen.h 2006-03-12 17:11:43.000000000 +0100 @@ -98,4 +98,7 @@ extern void intelSwapBuffers( __DRIdrawablePrivate *dPriv); +extern void +intelCopySubBuffer( __DRIdrawablePrivate *dPriv, int x, int y, int w, int h ); + #endif diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_context.c ./src/mesa/drivers/dri/r200/r200_context.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_context.c 2005-09-10 18:44:26.000000000 +0200 +++ ./src/mesa/drivers/dri/r200/r200_context.c 2006-03-12 17:11:43.000000000 +0100 @@ -625,7 +625,7 @@ r200PageFlip( dPriv ); } else { - r200CopyBuffer( dPriv ); + r200CopyBuffer( dPriv, NULL ); } } } @@ -635,6 +635,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'. diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_context.h ./src/mesa/drivers/dri/r200/r200_context.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_context.h 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/r200/r200_context.h 2006-03-12 17:11:43.000000000 +0100 @@ -960,6 +960,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 ); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_ioctl.c ./src/mesa/drivers/dri/r200/r200_ioctl.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_ioctl.c 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/r200/r200_ioctl.c 2006-03-12 17:11:43.000000000 +0100 @@ -429,7 +429,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; @@ -455,9 +456,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 */ @@ -468,8 +472,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; @@ -483,18 +506,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 ) diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_ioctl.h ./src/mesa/drivers/dri/r200/r200_ioctl.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/r200/r200_ioctl.h 2005-02-01 00:40:06.000000000 +0100 +++ ./src/mesa/drivers/dri/r200/r200_ioctl.h 2006-03-12 17:11:43.000000000 +0100 @@ -96,7 +96,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 ); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_context.c ./src/mesa/drivers/dri/r300/radeon_context.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_context.c 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/r300/radeon_context.c 2006-03-12 17:11:43.000000000 +0100 @@ -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'. diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_context.h ./src/mesa/drivers/dri/r300/radeon_context.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_context.h 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/r300/radeon_context.h 2006-03-12 17:11:43.000000000 +0100 @@ -208,6 +208,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, diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_ioctl.c ./src/mesa/drivers/dri/r300/radeon_ioctl.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_ioctl.c 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/r300/radeon_ioctl.c 2006-03-12 17:23:57.000000000 +0100 @@ -142,7 +142,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; @@ -171,10 +172,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 */ @@ -184,9 +188,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; @@ -202,21 +225,24 @@ UNLOCK_HARDWARE(radeon); - if (IS_FAMILY_R200(radeon)) + if (!rect) + { + if (IS_FAMILY_R200(radeon)) ((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 -ur ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_ioctl.h ./src/mesa/drivers/dri/r300/radeon_ioctl.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/r300/radeon_ioctl.h 2005-07-20 23:35:27.000000000 +0200 +++ ./src/mesa/drivers/dri/r300/radeon_ioctl.h 2006-03-12 17:11:43.000000000 +0100 @@ -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); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_context.c ./src/mesa/drivers/dri/radeon/radeon_context.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_context.c 2005-07-28 02:29:52.000000000 +0200 +++ ./src/mesa/drivers/dri/radeon/radeon_context.c 2006-03-12 17:11:43.000000000 +0100 @@ -565,7 +565,7 @@ radeonPageFlip( dPriv ); } else { - radeonCopyBuffer( dPriv ); + radeonCopyBuffer( dPriv, NULL ); } } } @@ -575,6 +575,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'. diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_context.h ./src/mesa/drivers/dri/radeon/radeon_context.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_context.h 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/radeon/radeon_context.h 2006-03-12 17:11:43.000000000 +0100 @@ -835,6 +835,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 ); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_ioctl.c ./src/mesa/drivers/dri/radeon/radeon_ioctl.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_ioctl.c 2005-07-26 04:44:02.000000000 +0200 +++ ./src/mesa/drivers/dri/radeon/radeon_ioctl.c 2006-03-12 17:11:43.000000000 +0100 @@ -882,7 +882,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; @@ -906,9 +907,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 */ @@ -919,8 +923,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; @@ -934,15 +957,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 ) diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_ioctl.h ./src/mesa/drivers/dri/radeon/radeon_ioctl.h --- ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_ioctl.h 2005-02-01 00:40:06.000000000 +0100 +++ ./src/mesa/drivers/dri/radeon/radeon_ioctl.h 2006-03-12 17:11:43.000000000 +0100 @@ -93,7 +93,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 ); diff -ur ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_screen.c ./src/mesa/drivers/dri/radeon/radeon_screen.c --- ../Mesa-6.4.2/src/mesa/drivers/dri/radeon/radeon_screen.c 2005-11-29 23:36:02.000000000 +0100 +++ ./src/mesa/drivers/dri/radeon/radeon_screen.c 2006-03-12 17:26:10.000000000 +0100 @@ -410,6 +410,7 @@ } (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); + (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" ); } screen->driScreen = sPriv; @@ -562,7 +563,8 @@ .GetMSC = driGetMSC32, .WaitForMSC = driWaitForMSC32, .WaitForSBC = NULL, - .SwapBuffersMSC = NULL + .SwapBuffersMSC = NULL, + .CopySubBuffer = radeonCopySubBuffer, };