From f2ad1b60c0da11283b399008f491792790cea294 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 31 Mar 2006 15:48:04 +0000 Subject: Dave Reveman's patch for GLX_MESA_copy_sub_buffer support --- include/GL/internal/dri_interface.h | 8 +++ src/glx/x11/glxcmds.c | 70 +++++++++++++++++++++++---- src/glx/x11/glxextensions.c | 2 +- src/mesa/drivers/dri/common/dri_util.c | 10 ++++ src/mesa/drivers/dri/common/dri_util.h | 2 + src/mesa/drivers/dri/i915/intel_batchbuffer.c | 53 ++++++++++++++------ src/mesa/drivers/dri/i915/intel_batchbuffer.h | 3 +- src/mesa/drivers/dri/i915/intel_context.c | 25 +++++++++- src/mesa/drivers/dri/i915/intel_screen.c | 4 +- src/mesa/drivers/dri/i915/intel_screen.h | 3 ++ src/mesa/drivers/dri/r200/r200_context.c | 26 +++++++++- src/mesa/drivers/dri/r200/r200_context.h | 2 + src/mesa/drivers/dri/r200/r200_ioctl.c | 56 +++++++++++++++------ src/mesa/drivers/dri/r200/r200_ioctl.h | 3 +- src/mesa/drivers/dri/r300/radeon_context.c | 27 ++++++++++- src/mesa/drivers/dri/r300/radeon_context.h | 2 + src/mesa/drivers/dri/r300/radeon_ioctl.c | 59 +++++++++++++++------- src/mesa/drivers/dri/r300/radeon_ioctl.h | 3 +- src/mesa/drivers/dri/radeon/radeon_context.c | 27 ++++++++++- src/mesa/drivers/dri/radeon/radeon_context.h | 2 + src/mesa/drivers/dri/radeon/radeon_ioctl.c | 54 +++++++++++++++------ src/mesa/drivers/dri/radeon/radeon_ioctl.h | 3 +- src/mesa/drivers/dri/radeon/radeon_screen.c | 8 ++- 23 files changed, 371 insertions(+), 81 deletions(-) diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 0f3555b576..c204ecfe62 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -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 diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index d4f579d01a..16f7e96150 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 0cee71f6c3..c3bc93009a 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 883a89c888..d68837b545 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 b9b38f39cd..14c24a0efa 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 508900de30..974a2497e1 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 dcc63b23c8..b0aed89af5 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 c79ce9661c..7dbc2c8739 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 9ee44ea086..c8649d8243 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 0cdcc14044..24cfd9bf8b 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 0d7df499c0..e4d9e264bf 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 eee72bdacb..faf1b96a2b 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 5a2f7e2ad6..ae0f35cb39 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 cf4188afe8..f53752739d 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 0a957816db..4e351dd66b 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 671c14df03..4eeb4edcfd 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 f562762878..798e83c010 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 4ddd776602..b53767510e 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 f546731ad4..791d1a37bc 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 09fa948ccb..9abd866730 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 fa22cbd6f9..53f6f57057 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 dd7ed19b84..335ed77c9a 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 a93cfb3821..5257e541e5 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 -- cgit v1.2.3