Assuming everyone likes this patch, I'll commit it tomorrow.
HOWEVER, the wincopy demo runs about as fast with this patch as with indirect, software rasterization. The software path for glCopyPixels is *death*. Could people who are working on drivers *please* implement screen-to-screen blits for at least the common, easy cases of glCopyPixels? I understand that glCopyPixels isn't a common performance critical path, but the a lot of the code used to accelerate that should be re-usable for accelerating glCopyTexImage and some other pbuffer related functionality when the time comes.
Index: lib/GL/mesa/src/drv/mga/mga_xmesa.c =================================================================== RCS file: /cvs/dri/xc/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v retrieving revision 1.62 diff -u -d -r1.62 mga_xmesa.c --- lib/GL/mesa/src/drv/mga/mga_xmesa.c 25 Oct 2003 16:11:46 -0000 1.62 +++ lib/GL/mesa/src/drv/mga/mga_xmesa.c 29 Oct 2003 18:40:09 -0000 @@ -129,6 +129,7 @@ (*glx_enable_extension)( psc, "GLX_MESA_swap_control" ); } + (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); } } @@ -377,7 +378,6 @@ mmesa->mgaScreen = mgaScreen; mmesa->driScreen = sPriv; mmesa->sarea = (void *)saPriv; - mmesa->glBuffer = NULL; /* Parse configuration files */ driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache, @@ -655,6 +655,8 @@ mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); } + mmesa->driReadable = driReadPriv; + _mesa_make_current2(mmesa->glCtx, (GLframebuffer *) driDrawPriv->driverPrivate, (GLframebuffer *) driReadPriv->driverPrivate); Index: lib/GL/mesa/src/drv/mga/mgacontext.h =================================================================== RCS file: /cvs/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgacontext.h,v retrieving revision 1.30 diff -u -d -r1.30 mgacontext.h --- lib/GL/mesa/src/drv/mga/mgacontext.h 25 Oct 2003 16:11:46 -0000 1.30 +++ lib/GL/mesa/src/drv/mga/mgacontext.h 29 Oct 2003 18:40:09 -0000 @@ -298,11 +298,19 @@ /* Mirrors of some DRI state. */ - GLframebuffer *glBuffer; drmContext hHWContext; drmLock *driHwLock; int driFd; __DRIdrawablePrivate *driDrawable; + __DRIdrawablePrivate *driReadable; + + /** + * Drawable used by Mesa for software fallbacks for reading and + * writing. It is set by Mesa's \c SetBuffer callback, and will always be + * either \c mga_context_t::driDrawable or \c mga_context_t::driReadable. + */ + __DRIdrawablePrivate *mesa_drawable; + __DRIscreenPrivate *driScreen; struct mga_screen_private_s *mgaScreen; MGASAREAPrivPtr sarea; Index: lib/GL/mesa/src/drv/mga/mgaspan.c =================================================================== RCS file: /cvs/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgaspan.c,v retrieving revision 1.31 diff -u -d -r1.31 mgaspan.c --- lib/GL/mesa/src/drv/mga/mgaspan.c 30 Apr 2003 01:50:42 -0000 1.31 +++ lib/GL/mesa/src/drv/mga/mgaspan.c 29 Oct 2003 18:40:09 -0000 @@ -37,7 +37,7 @@ #define LOCAL_VARS \ - __DRIdrawablePrivate *dPriv = mmesa->driDrawable; \ + __DRIdrawablePrivate *dPriv = mmesa->mesa_drawable; \ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; \ __DRIscreenPrivate *sPriv = mmesa->driScreen; \ GLuint pitch = mgaScreen->frontPitch; \ @@ -56,7 +56,7 @@ #define LOCAL_DEPTH_VARS \ - __DRIdrawablePrivate *dPriv = mmesa->driDrawable; \ + __DRIdrawablePrivate *dPriv = mmesa->mesa_drawable; \ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen; \ __DRIscreenPrivate *sPriv = mmesa->driScreen; \ GLuint pitch = mgaScreen->frontPitch; \ @@ -242,20 +242,22 @@ GLuint bufferBit) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); + unsigned int offset; - if (bufferBit == FRONT_LEFT_BIT) - { - mmesa->drawOffset = mmesa->mgaScreen->frontOffset; - mmesa->readOffset = mmesa->mgaScreen->frontOffset; - } - else if (bufferBit == BACK_LEFT_BIT) - { - mmesa->drawOffset = mmesa->mgaScreen->backOffset; - mmesa->readOffset = mmesa->mgaScreen->backOffset; - } - else { - assert(0); - } + assert( (bufferBit == FRONT_LEFT_BIT) || (bufferBit == BACK_LEFT_BIT) ); + + offset = (bufferBit == FRONT_LEFT_BIT) + ? mmesa->mgaScreen->frontOffset + : mmesa->mgaScreen->backOffset; + + mmesa->drawOffset = offset; + mmesa->readOffset = offset; + + assert( (buffer == mmesa->driDrawable->driverPrivate) + || (buffer == mmesa->driReadable->driverPrivate) ); + + mmesa->mesa_drawable = (buffer == mmesa->driDrawable->driverPrivate) + ? mmesa->driDrawable : mmesa->driReadable; } void mgaDDInitSpanFuncs( GLcontext *ctx )