OSDN Git Service

Merge branch 'master' of git+ssh://keithw@git.freedesktop.org/git/mesa/mesa into...
authorKeith Whitwell <keith@tungstengraphics.com>
Tue, 16 Jan 2007 11:22:57 +0000 (11:22 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Tue, 16 Jan 2007 11:22:57 +0000 (11:22 +0000)
Conflicts:

src/mesa/array_cache/sources
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_fallback.c
src/mesa/drivers/dri/i965/brw_vs_emit.c
src/mesa/drivers/dri/i965/brw_vs_tnl.c
src/mesa/drivers/dri/mach64/mach64_context.c
src/mesa/main/extensions.c
src/mesa/main/getstring.c
src/mesa/tnl/sources
src/mesa/tnl/t_save_api.c
src/mesa/tnl/t_save_playback.c
src/mesa/tnl/t_vtx_api.c
src/mesa/tnl/t_vtx_exec.c
src/mesa/vbo/vbo_attrib.h
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_save_api.c
src/mesa/vbo/vbo_save_draw.c

44 files changed:
1  2 
src/mesa/Makefile
src/mesa/drivers/directfb/idirectfbgl_mesa.c
src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/i915tex/i915_context.c
src/mesa/drivers/dri/i915tex/intel_context.c
src/mesa/drivers/dri/i965/Makefile
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_metaops.c
src/mesa/drivers/dri/i965/brw_vs_tnl.c
src/mesa/drivers/dri/i965/brw_vtbl.c
src/mesa/drivers/dri/i965/intel_context.c
src/mesa/drivers/dri/mach64/mach64_context.c
src/mesa/drivers/dri/mga/mgastate.c
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/nouveau/nouveau_state.c
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r200/r200_state.c
src/mesa/drivers/dri/r200/r200_tcl.c
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/radeon_state.c
src/mesa/drivers/dri/radeon/radeon_context.c
src/mesa/drivers/dri/savage/savage_xmesa.c
src/mesa/drivers/dri/savage/savagestate.c
src/mesa/drivers/dri/tdfx/tdfx_context.c
src/mesa/drivers/dri/trident/trident_context.c
src/mesa/drivers/dri/unichrome/via_context.c
src/mesa/drivers/dri/unichrome/via_state.c
src/mesa/main/context.c
src/mesa/main/enable.c
src/mesa/main/extensions.c
src/mesa/main/get.c
src/mesa/main/get_gen.py
src/mesa/main/mtypes.h
src/mesa/main/state.c
src/mesa/main/stencil.c
src/mesa/tnl/sources
src/mesa/tnl/t_context.c
src/mesa/vbo/vbo_attrib.h
src/mesa/vbo/vbo_save_api.c
src/mesa/vbo/vbo_save_draw.c
src/mesa/vbo/vbo_split_copy.c

Simple merge
@@@ -36,7 -36,7 +36,6 @@@
  #include "swrast/swrast.h"
  #include "swrast_setup/swrast_setup.h"
  #include "tnl/tnl.h"
--#include "array_cache/acache.h"
  
  #include "utils.h"
  #include "i915_reg.h"
@@@ -67,7 -67,7 +66,7 @@@ i915InvalidateState(GLcontext * ctx, GL
  {
     _swrast_InvalidateState(ctx, new_state);
     _swsetup_InvalidateState(ctx, new_state);
--   _ac_InvalidateState(ctx, new_state);
++   _vbo_InvalidateState(ctx, new_state);
     _tnl_InvalidateState(ctx, new_state);
     _tnl_invalidate_vertex_state(ctx, new_state);
     intel_context(ctx)->NewGLState |= new_state;
@@@ -37,7 -37,7 +37,6 @@@
  #include "swrast/swrast.h"
  #include "swrast_setup/swrast_setup.h"
  #include "tnl/tnl.h"
--#include "array_cache/acache.h"
  
  #include "tnl/t_pipeline.h"
  #include "tnl/t_vertex.h"
@@@ -241,7 -241,7 +240,7 @@@ intelInvalidateState(GLcontext * ctx, G
  {
     _swrast_InvalidateState(ctx, new_state);
     _swsetup_InvalidateState(ctx, new_state);
--   _ac_InvalidateState(ctx, new_state);
++   _vbo_InvalidateState(ctx, new_state);
     _tnl_InvalidateState(ctx, new_state);
     _tnl_invalidate_vertex_state(ctx, new_state);
     intel_context(ctx)->NewGLState |= new_state;
@@@ -390,7 -390,7 +389,7 @@@ intelInitContext(struct intel_context *
  
     /* Initialize the software rasterizer and helper modules. */
     _swrast_CreateContext(ctx);
--   _ac_CreateContext(ctx);
++   _vbo_CreateContext(ctx);
     _tnl_CreateContext(ctx);
     _swsetup_CreateContext(ctx);
  
@@@ -500,7 -500,7 +499,7 @@@ intelDestroyContext(__DRIcontextPrivat
        release_texture_heaps = (intel->ctx.Shared->RefCount == 1);
        _swsetup_DestroyContext(&intel->ctx);
        _tnl_DestroyContext(&intel->ctx);
--      _ac_DestroyContext(&intel->ctx);
++      _vbo_DestroyContext(&intel->ctx);
  
        _swrast_DestroyContext(&intel->ctx);
        intel->Fallback = 0;      /* don't call _swrast_Flush later */
Simple merge
@@@ -154,7 -156,14 +154,8 @@@ GLboolean brwCreateContext( const __GLc
  
     brw_ProgramCacheInit( ctx );
  
+    brw_FrameBufferTexInit( brw );
  
 -   /* Hook our functions into exec and compile dispatch tables.  Only
 -    * fallback on out-of-memory situations.
 -    */
 -   brw_exec_init( ctx );
 -   brw_save_init( ctx );
 -
     {
        const char *filename = getenv("INTEL_REPLAY");
        if (filename) {
@@@ -411,10 -414,10 +411,10 @@@ GLboolean brw_upload_vertices( struct b
      */
     
     while (tmp) {
-       GLuint i = ffs(tmp)-1;
+       GLuint i = ffsll(tmp)-1;
        struct brw_vertex_element *input = &brw->vb.inputs[i];
  
 -      tmp &= ~((GLuint64EXT)1<<i);
 +      tmp &= ~(1<<i);
        enabled[nr_enabled++] = input;
  
        input->index = i;
@@@ -66,7 -68,11 +66,8 @@@ static void brw_destroy_context( struc
     brw_destroy_state(brw);
     brw_draw_destroy( brw );
  
 -   brw_exec_destroy( ctx );
 -   brw_save_destroy( ctx );
 -
     brw_ProgramCacheDestroy( ctx );
+    brw_FrameBufferTexDestroy( brw );
  }
  
  /* called from intelDrawBuffer()
@@@ -320,9 -355,14 +355,14 @@@ GLboolean intelInitContext( struct inte
     ctx->Const.MaxPointSizeAA = 3.0;
     ctx->Const.PointSizeGranularity = 1.0;
  
+    /* reinitialize the context point state.
+     * It depend on constants in __GLcontextRec::Const
+     */
+    _mesa_init_point(ctx);
     /* Initialize the software rasterizer and helper modules. */
     _swrast_CreateContext( ctx );
 -   _ac_CreateContext( ctx );
 +   _vbo_CreateContext( ctx );
     _tnl_CreateContext( ctx );
     _swsetup_CreateContext( ctx );
  
@@@ -250,7 -272,16 +272,16 @@@ void mach64DestroyContext( __DRIcontext
  
     assert(mmesa);  /* should never be null */
     if ( mmesa ) {
-       if (mmesa->glCtx->Shared->RefCount == 1) {
+       GLboolean   release_texture_heaps;
+       release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
+       _swsetup_DestroyContext( mmesa->glCtx );
+       _tnl_DestroyContext( mmesa->glCtx );
 -      _ac_DestroyContext( mmesa->glCtx );
++      _vbo_DestroyContext( mmesa->glCtx );
+       _swrast_DestroyContext( mmesa->glCtx );
+       if (release_texture_heaps) {
           /* This share group is about to go away, free our private
            * texture object data.
            */
Simple merge
index 0000000,79da46f..c86ff60
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,367 +1,366 @@@
 -#include "array_cache/acache.h"
+ /**************************************************************************
+ Copyright 2006 Stephane Marchesin
+ All Rights Reserved.
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ on the rights to use, copy, modify, merge, publish, distribute, sub
+ license, and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************/
+ #include "glheader.h"
+ #include "context.h"
+ #include "simple_list.h"
+ #include "imports.h"
+ #include "matrix.h"
+ #include "swrast/swrast.h"
+ #include "swrast_setup/swrast_setup.h"
 -      _ac_CreateContext( ctx );
+ #include "framebuffer.h"
+ #include "tnl/tnl.h"
+ #include "tnl/t_pipeline.h"
+ #include "tnl/t_vp_build.h"
+ #include "drivers/common/driverfuncs.h"
+ #include "nouveau_context.h"
+ #include "nouveau_driver.h"
+ //#include "nouveau_state.h"
+ #include "nouveau_span.h"
+ #include "nouveau_object.h"
+ #include "nouveau_fifo.h"
+ #include "nouveau_tex.h"
+ #include "nouveau_msg.h"
+ #include "nouveau_reg.h"
+ #include "nouveau_lock.h"
+ #include "nv10_swtcl.h"
+ #include "vblank.h"
+ #include "utils.h"
+ #include "texmem.h"
+ #include "xmlpool.h" /* for symbolic values of enum-type options */
+ #ifndef NOUVEAU_DEBUG
+ int NOUVEAU_DEBUG = 0;
+ #endif
+ static const struct dri_debug_control debug_control[] =
+ {
+       { "shaders"   , DEBUG_SHADERS    },
+       { "mem"       , DEBUG_MEM        },
+       { "bufferobj" , DEBUG_BUFFEROBJ  },
+       { NULL        , 0                }
+ };
+ #define need_GL_ARB_vertex_program
+ #include "extension_helper.h"
+ const struct dri_extension common_extensions[] =
+ {
+       { NULL,    0 }
+ };
+ const struct dri_extension nv10_extensions[] =
+ {
+       { NULL,    0 }
+ };
+ const struct dri_extension nv20_extensions[] =
+ {
+       { NULL,    0 }
+ };
+ const struct dri_extension nv30_extensions[] =
+ {
+       { "GL_ARB_fragment_program",    NULL                            },
+       { NULL,    0 }
+ };
+ const struct dri_extension nv40_extensions[] =
+ {
+    /* ARB_vp can be moved to nv20/30 once the shader backend has been
+     * written for those cards.
+     */
+       { "GL_ARB_vertex_program",      GL_ARB_vertex_program_functions },
+       { NULL, 0 }
+ };
+ const struct dri_extension nv50_extensions[] =
+ {
+       { NULL,    0 }
+ };
+ /* Create the device specific context.
+  */
+ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual,
+               __DRIcontextPrivate *driContextPriv,
+               void *sharedContextPrivate )
+ {
+       GLcontext *ctx, *shareCtx;
+       __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+       struct dd_function_table functions;
+       nouveauContextPtr nmesa;
+       nouveauScreenPtr screen;
+       /* Allocate the context */
+       nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) );
+       if ( !nmesa )
+               return GL_FALSE;
+       nmesa->driContext = driContextPriv;
+       nmesa->driScreen = sPriv;
+       nmesa->driDrawable = NULL;
+       nmesa->hHWContext = driContextPriv->hHWContext;
+       nmesa->driHwLock = &sPriv->pSAREA->lock;
+       nmesa->driFd = sPriv->fd;
+       nmesa->screen = (nouveauScreenPtr)(sPriv->private);
+       screen=nmesa->screen;
+       /* Create the hardware context */
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL,
+                               &nmesa->vram_phys))
+          return GL_FALSE;
+       if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL,
+                               &nmesa->agp_phys))
+          return GL_FALSE;
+       if (!nouveauFifoInit(nmesa))
+          return GL_FALSE;
+       nouveauObjectInit(nmesa);
+       /* Init default driver functions then plug in our nouveau-specific functions
+        * (the texture functions are especially important)
+        */
+       _mesa_init_driver_functions( &functions );
+       nouveauDriverInitFunctions( &functions );
+       nouveauTexInitFunctions( &functions );
+       /* Allocate the Mesa context */
+       if (sharedContextPrivate)
+               shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx;
+       else 
+               shareCtx = NULL;
+       nmesa->glCtx = _mesa_create_context(glVisual, shareCtx,
+                       &functions, (void *) nmesa);
+       if (!nmesa->glCtx) {
+               FREE(nmesa);
+               return GL_FALSE;
+       }
+       driContextPriv->driverPrivate = nmesa;
+       ctx = nmesa->glCtx;
+       /* Parse configuration files */
+       driParseConfigFiles (&nmesa->optionCache, &screen->optionCache,
+                       screen->driScreen->myNum, "nouveau");
+       nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA +
+                       screen->sarea_priv_offset);
+       /* Enable any supported extensions */
+       driInitExtensions(ctx, common_extensions, GL_TRUE);
+       if (nmesa->screen->card->type >= NV_10)
+               driInitExtensions(ctx, nv10_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_20)
+               driInitExtensions(ctx, nv20_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_30)
+               driInitExtensions(ctx, nv30_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_40)
+               driInitExtensions(ctx, nv40_extensions, GL_FALSE);
+       if (nmesa->screen->card->type >= NV_50)
+               driInitExtensions(ctx, nv50_extensions, GL_FALSE);
+       nmesa->current_primitive = -1;
+       nouveauShaderInitFuncs(ctx);
+       /* Install Mesa's fixed-function texenv shader support */
+       if (nmesa->screen->card->type >= NV_40)
+               ctx->_MaintainTexEnvProgram = GL_TRUE;
+       /* Initialize the swrast */
+       _swrast_CreateContext( ctx );
++      _vbo_CreateContext( ctx );
+       _tnl_CreateContext( ctx );
+       _swsetup_CreateContext( ctx );
+       _math_matrix_ctr(&nmesa->viewport);
+       nouveauDDInitStateFuncs( ctx );
+       nouveauSpanInitFunctions( ctx );
+       nouveauDDInitState( nmesa );
+       switch(nmesa->screen->card->type)
+       {
+               case NV_03:
+                       //nv03TriInitFunctions( ctx );
+                       break;
+               case NV_04:
+               case NV_05:
+                       //nv04TriInitFunctions( ctx );
+                       break;
+               case NV_10:
+               case NV_20:
+               case NV_30:
+               case NV_40:
+               case NV_44:
+               case NV_50:
+               default:
+                       nv10TriInitFunctions( ctx );
+                       break;
+       }
+       nouveauInitBufferObjects(ctx);
+       if (!nouveauSyncInitFuncs(ctx))
+          return GL_FALSE;
+       nmesa->hw_func.InitCard(nmesa);
+         nouveauInitState(ctx);
+       driContextPriv->driverPrivate = (void *)nmesa;
+       NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ),
+                       debug_control );
+       if (driQueryOptionb(&nmesa->optionCache, "no_rast")) {
+               fprintf(stderr, "disabling 3D acceleration\n");
+               FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1);
+       }
+       return GL_TRUE;
+ }
+ /* Destroy the device specific context. */
+ void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv  )
+ {
+       nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+       assert(nmesa);
+       if ( nmesa ) {
+               /* free the option cache */
+               driDestroyOptionCache (&nmesa->optionCache);
+               FREE( nmesa );
+       }
+ }
+ /* Force the context `c' to be the current context and associate with it
+  * buffer `b'.
+  */
+ GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
+               __DRIdrawablePrivate *driDrawPriv,
+               __DRIdrawablePrivate *driReadPriv )
+ {
+       if ( driContextPriv ) {
+               nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate;
+               struct gl_framebuffer *draw_fb =
+                       (struct gl_framebuffer*)driDrawPriv->driverPrivate;
+               struct gl_framebuffer *read_fb =
+                       (struct gl_framebuffer*)driReadPriv->driverPrivate;
+               driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
+               nmesa->driDrawable = driDrawPriv;
+               _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                        driDrawPriv->w, driDrawPriv->h);
+               if (draw_fb != read_fb) {
+                       _mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
+                                                driReadPriv->w,
+                                                driReadPriv->h);
+               }
+               _mesa_make_current(nmesa->glCtx, draw_fb, read_fb);
+               nouveau_build_framebuffer(nmesa->glCtx,
+                                         driDrawPriv->driverPrivate);
+       } else {
+               _mesa_make_current( NULL, NULL, NULL );
+       }
+       return GL_TRUE;
+ }
+ /* Force the context `c' to be unbound from its buffer.
+  */
+ GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv )
+ {
+       return GL_TRUE;
+ }
+ static void nouveauDoSwapBuffers(nouveauContextPtr nmesa,
+                                __DRIdrawablePrivate *dPriv)
+ {
+       struct gl_framebuffer *fb;
+       nouveau_renderbuffer *src, *dst;
+       drm_clip_rect_t *box;
+       int nbox, i;
+       fb = (struct gl_framebuffer *)dPriv->driverPrivate;
+       dst = (nouveau_renderbuffer*)
+               fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+       src = (nouveau_renderbuffer*)
+               fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ #ifdef ALLOW_MULTI_SUBCHANNEL
+       LOCK_HARDWARE(nmesa);
+       nbox = dPriv->numClipRects;
+       box  = dPriv->pClipRects;
+       if (nbox) {
+               BEGIN_RING_SIZE(NvSubCtxSurf2D,
+                               NV10_CONTEXT_SURFACES_2D_FORMAT, 4);
+               if (src->mesa._ActualFormat == GL_RGBA8)
+                       OUT_RING       (6); /* X8R8G8B8 */
+               else
+                       OUT_RING       (4); /* R5G6B5 */
+               OUT_RING       ((dst->pitch << 16) | src->pitch);
+               OUT_RING       (src->offset);
+               OUT_RING       (dst->offset);
+       }
+       for (i=0; i<nbox; i++, box++) {
+               BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3);
+               OUT_RING       (((box->y1 - dPriv->y) << 16) |
+                               (box->x1 - dPriv->x));
+               OUT_RING       ((box->y1 << 16) | box->x1);
+               OUT_RING       (((box->y2 - box->y1) << 16) |
+                               (box->x2 - box->x1));
+       }
+       UNLOCK_HARDWARE(nmesa);
+ #endif
+ }
+ void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv)
+ {
+       if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+               nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate;
+               if (nmesa->glCtx->Visual.doubleBufferMode) {
+                       _mesa_notifySwapBuffers(nmesa->glCtx);
+                       nouveauDoSwapBuffers(nmesa, dPriv);
+               }
+       }
+ }
+ void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv,
+                         int x, int y, int w, int h)
+ {
+ }
index 0000000,1ff881f..8d3c018
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,342 +1,341 @@@
 -#include "array_cache/acache.h"
+ /**************************************************************************
+ Copyright 2006 Jeremy Kolb
+ All Rights Reserved.
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ on the rights to use, copy, modify, merge, publish, distribute, sub
+ license, and/or sell copies of the Software, and to permit persons to whom
+ the Software is furnished to do so, subject to the following conditions:
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
+ **************************************************************************/
+ #include "nouveau_context.h"
+ #include "nouveau_state.h"
+ #include "nouveau_swtcl.h"
+ #include "nouveau_fifo.h"
+ #include "swrast/swrast.h"
 -    _ac_InvalidateState( ctx, new_state );
+ #include "tnl/tnl.h"
+ #include "swrast_setup/swrast_setup.h"
+ #include "tnl/t_pipeline.h"
+ #include "mtypes.h"
+ #include "colormac.h"
+ static __inline__ GLuint nouveauPackColor(GLuint format,
+                                      GLubyte r, GLubyte g,
+                                      GLubyte b, GLubyte a)
+ {
+    switch (format) {
+    case 2:
+       return PACK_COLOR_565( r, g, b );
+    case 4:
+       return PACK_COLOR_8888( r, g, b, a);
+    default:
+       fprintf(stderr, "unknown format %d\n", (int)format);
+       return 0;
+    }
+ }
+ static void nouveauCalcViewport(GLcontext *ctx)
+ {
+     /* Calculate the Viewport Matrix */
+     
+     nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+     const GLfloat *v = ctx->Viewport._WindowMap.m;
+     GLfloat *m = nmesa->viewport.m;
+     GLfloat xoffset = nmesa->drawX, yoffset = nmesa->drawY;
+   
+     nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
+     m[MAT_SX] =   v[MAT_SX];
+     m[MAT_TX] =   v[MAT_TX] + xoffset + SUBPIXEL_X;
+     m[MAT_SY] = - v[MAT_SY];
+     m[MAT_TY] =   v[MAT_TY] + yoffset + SUBPIXEL_Y;
+     m[MAT_SZ] =   v[MAT_SZ] * nmesa->depth_scale;
+     m[MAT_TZ] =   v[MAT_TZ] * nmesa->depth_scale;
+     nmesa->hw_func.WindowMoved(nmesa);
+ }
+ static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+ {
+     /* 
+      * Need to send (at least on an nv35 the following:
+      * cons = 4 (this may be bytes per pixel)
+      *
+      * The viewport:
+      * 445   0x0000bee0   {size: 0x0   channel: 0x1   cmd: 0x00009ee0} <-- VIEWPORT_SETUP/HEADER ?
+      * 446   0x00000000   {size: 0x0   channel: 0x0   cmd: 0x00000000} <-- x * cons
+      * 447   0x00000c80   {size: 0x0   channel: 0x0   cmd: 0x00000c80} <-- (height + x) * cons
+      * 448   0x00000000   {size: 0x0   channel: 0x0   cmd: 0x00000000} <-- y * cons
+      * 449   0x00000960   {size: 0x0   channel: 0x0   cmd: 0x00000960} <-- (width + y) * cons
+      * 44a   0x00082a00   {size: 0x2   channel: 0x1   cmd: 0x00000a00} <-- VIEWPORT_DIMS
+      * 44b   0x04000000  <-- (Width_from_glViewport << 16) | x
+      * 44c   0x03000000  <-- (Height_from_glViewport << 16) | (win_height - height - y)
+      *
+      */
+     
+     nouveauCalcViewport(ctx);
+ }
+ static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far)
+ {
+     nouveauCalcViewport(ctx);
+ }
+ static void nouveauDDUpdateHWState(GLcontext *ctx)
+ {
+     nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+     int new_state = nmesa->new_state;
+     if ( new_state || nmesa->new_render_state & _NEW_TEXTURE )
+     {
+         nmesa->new_state = 0;
+         /* Update the various parts of the context's state.
+         */
+         /*
+         if ( new_state & NOUVEAU_NEW_ALPHA )
+             nouveauUpdateAlphaMode( ctx );
+         if ( new_state & NOUVEAU_NEW_DEPTH )
+             nouveauUpdateZMode( ctx );
+         if ( new_state & NOUVEAU_NEW_FOG )
+             nouveauUpdateFogAttrib( ctx );
+         if ( new_state & NOUVEAU_NEW_CLIP )
+             nouveauUpdateClipping( ctx );
+         if ( new_state & NOUVEAU_NEW_CULL )
+             nouveauUpdateCull( ctx );
+         if ( new_state & NOUVEAU_NEW_MASKS )
+             nouveauUpdateMasks( ctx );
+         if ( new_state & NOUVEAU_NEW_WINDOW )
+             nouveauUpdateWindow( ctx );
+         if ( nmesa->new_render_state & _NEW_TEXTURE ) {
+             nouveauUpdateTextureState( ctx );
+         }*/
+     }
+ }
+ static void nouveauDDInvalidateState(GLcontext *ctx, GLuint new_state)
+ {
+     _swrast_InvalidateState( ctx, new_state );
+     _swsetup_InvalidateState( ctx, new_state );
++    _vbo_InvalidateState( ctx, new_state );
+     _tnl_InvalidateState( ctx, new_state );
+     NOUVEAU_CONTEXT(ctx)->new_render_state |= new_state;
+ }
+ /* Initialize the context's hardware state. */
+ void nouveauDDInitState(nouveauContextPtr nmesa)
+ {
+     uint32_t type = nmesa->screen->card->type;
+     switch(type)
+     {
+         case NV_03:
+         case NV_04:
+         case NV_05:
+             /* No TCL engines for these ones */
+             break;
+         case NV_10:
+             nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+             break;
+         case NV_20:
+             nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+             break;
+         case NV_30:
+         case NV_40:
+         case NV_44:
+         case NV_50:
+             nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver);
+             break;
+         default:
+             break;
+     }
+     nouveau_state_cache_init(nmesa);
+ }
+ /* Initialize the driver's state functions */
+ void nouveauDDInitStateFuncs(GLcontext *ctx)
+ {
+    ctx->Driver.UpdateState            = nouveauDDInvalidateState;
+    ctx->Driver.ClearIndex             = NULL;
+    ctx->Driver.ClearColor             = NULL; //nouveauDDClearColor;
+    ctx->Driver.ClearStencil           = NULL; //nouveauDDClearStencil;
+    ctx->Driver.DrawBuffer             = NULL; //nouveauDDDrawBuffer;
+    ctx->Driver.ReadBuffer             = NULL; //nouveauDDReadBuffer;
+    ctx->Driver.IndexMask              = NULL;
+    ctx->Driver.ColorMask              = NULL; //nouveauDDColorMask;
+    ctx->Driver.AlphaFunc              = NULL; //nouveauDDAlphaFunc;
+    ctx->Driver.BlendEquationSeparate  = NULL; //nouveauDDBlendEquationSeparate;
+    ctx->Driver.BlendFuncSeparate      = NULL; //nouveauDDBlendFuncSeparate;
+    ctx->Driver.ClearDepth             = NULL; //nouveauDDClearDepth;
+    ctx->Driver.CullFace                       = NULL; //nouveauDDCullFace;
+    ctx->Driver.FrontFace              = NULL; //nouveauDDFrontFace;
+    ctx->Driver.DepthFunc              = NULL; //nouveauDDDepthFunc;
+    ctx->Driver.DepthMask              = NULL; //nouveauDDDepthMask;
+    ctx->Driver.Enable                 = NULL; //nouveauDDEnable;
+    ctx->Driver.Fogfv                  = NULL; //nouveauDDFogfv;
+    ctx->Driver.Hint                   = NULL;
+    ctx->Driver.Lightfv                        = NULL;
+    ctx->Driver.LightModelfv           = NULL; //nouveauDDLightModelfv;
+    ctx->Driver.LogicOpcode            = NULL; //nouveauDDLogicOpCode;
+    ctx->Driver.PolygonMode            = NULL;
+    ctx->Driver.PolygonStipple         = NULL; //nouveauDDPolygonStipple;
+    ctx->Driver.RenderMode             = NULL; //nouveauDDRenderMode;
+    ctx->Driver.Scissor                        = NULL; //nouveauDDScissor;
+    ctx->Driver.ShadeModel             = NULL; //nouveauDDShadeModel;
+    ctx->Driver.StencilFuncSeparate    = NULL; //nouveauDDStencilFuncSeparate;
+    ctx->Driver.StencilMaskSeparate    = NULL; //nouveauDDStencilMaskSeparate;
+    ctx->Driver.StencilOpSeparate      = NULL; //nouveauDDStencilOpSeparate;
+    ctx->Driver.DepthRange               = nouveauDepthRange;
+    ctx->Driver.Viewport                 = nouveauViewport;
+    /* Pixel path fallbacks.
+     */
+    ctx->Driver.Accum = _swrast_Accum;
+    ctx->Driver.Bitmap = _swrast_Bitmap;
+    ctx->Driver.CopyPixels = _swrast_CopyPixels;
+    ctx->Driver.DrawPixels = _swrast_DrawPixels;
+    ctx->Driver.ReadPixels = _swrast_ReadPixels;
+    /* Swrast hooks for imaging extensions:
+     */
+    ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+    ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+    ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+    ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+ }
+ #define STATE_INIT(a) if (ctx->Driver.a) ctx->Driver.a
+ void nouveauInitState(GLcontext *ctx)
+ {
+     /*
+      * Mesa should do this for us:
+      */
+     STATE_INIT(AlphaFunc)( ctx, 
+             ctx->Color.AlphaFunc,
+             ctx->Color.AlphaRef);
+     STATE_INIT(BlendColor)( ctx,
+             ctx->Color.BlendColor );
+     STATE_INIT(BlendEquationSeparate)( ctx, 
+             ctx->Color.BlendEquationRGB,
+             ctx->Color.BlendEquationA);
+     STATE_INIT(BlendFuncSeparate)( ctx,
+             ctx->Color.BlendSrcRGB,
+             ctx->Color.BlendDstRGB,
+             ctx->Color.BlendSrcA,
+             ctx->Color.BlendDstA);
+     STATE_INIT(ClearColor)( ctx, ctx->Color.ClearColor);
+     STATE_INIT(ClearDepth)( ctx, ctx->Depth.Clear);
+     STATE_INIT(ClearStencil)( ctx, ctx->Stencil.Clear);
+     STATE_INIT(ColorMask)( ctx, 
+             ctx->Color.ColorMask[RCOMP],
+             ctx->Color.ColorMask[GCOMP],
+             ctx->Color.ColorMask[BCOMP],
+             ctx->Color.ColorMask[ACOMP]);
+     STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode );
+     STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func );
+     STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask );
+     STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
+     STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled );
+     STATE_INIT(Enable)( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
+     STATE_INIT(Enable)( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
+     STATE_INIT(Enable)( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
+     STATE_INIT(Enable)( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
+     STATE_INIT(Enable)( ctx, GL_DITHER, ctx->Color.DitherFlag );
+     STATE_INIT(Enable)( ctx, GL_FOG, ctx->Fog.Enabled );
+     STATE_INIT(Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled );
+     STATE_INIT(Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
+     STATE_INIT(Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag );
+     STATE_INIT(Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag );
+     STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill);
+     STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine);
+     STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint);
+     STATE_INIT(Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag );
+     STATE_INIT(Enable)( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
+     STATE_INIT(Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
+     STATE_INIT(Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
+     STATE_INIT(Enable)( ctx, GL_TEXTURE_1D, GL_FALSE );
+     STATE_INIT(Enable)( ctx, GL_TEXTURE_2D, GL_FALSE );
+     STATE_INIT(Enable)( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
+     STATE_INIT(Enable)( ctx, GL_TEXTURE_3D, GL_FALSE );
+     STATE_INIT(Enable)( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
+     STATE_INIT(Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+     STATE_INIT(Fogfv)( ctx, GL_FOG_MODE, 0 );
+     STATE_INIT(Fogfv)( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+     STATE_INIT(Fogfv)( ctx, GL_FOG_START, &ctx->Fog.Start );
+     STATE_INIT(Fogfv)( ctx, GL_FOG_END, &ctx->Fog.End );
+     STATE_INIT(FrontFace)( ctx, ctx->Polygon.FrontFace );
+     {
+         GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
+         STATE_INIT(LightModelfv)( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
+     }
+     STATE_INIT(LineStipple)( ctx, ctx->Line.StippleFactor, ctx->Line.StipplePattern );
+     STATE_INIT(LineWidth)( ctx, ctx->Line.Width );
+     STATE_INIT(LogicOpcode)( ctx, ctx->Color.LogicOp );
+     STATE_INIT(PointSize)( ctx, ctx->Point.Size );
+     STATE_INIT(PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode );
+     STATE_INIT(PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode );
+     STATE_INIT(PolygonOffset)( ctx,
+           ctx->Polygon.OffsetFactor,
+           ctx->Polygon.OffsetUnits );
+     STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple );
+     STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel );
+     STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT,
+             ctx->Stencil.Function[0],
+             ctx->Stencil.Ref[0],
+             ctx->Stencil.ValueMask[0] );
+     STATE_INIT(StencilFuncSeparate)( ctx, GL_BACK,
+             ctx->Stencil.Function[1],
+             ctx->Stencil.Ref[1],
+             ctx->Stencil.ValueMask[1] );
+     STATE_INIT(StencilMaskSeparate)( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
+     STATE_INIT(StencilMaskSeparate)( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
+     STATE_INIT(StencilOpSeparate)( ctx, GL_FRONT,
+             ctx->Stencil.FailFunc[0],
+             ctx->Stencil.ZFailFunc[0],
+             ctx->Stencil.ZPassFunc[0]);
+     STATE_INIT(StencilOpSeparate)( ctx, GL_BACK,
+             ctx->Stencil.FailFunc[1],
+             ctx->Stencil.ZFailFunc[1],
+             ctx->Stencil.ZPassFunc[1]);
+ }
@@@ -40,9 -40,10 +40,10 @@@ WITH THE SOFTWARE OR THE USE OR OTHER D
  #include "enums.h"
  #include "colormac.h"
  #include "light.h"
+ #include "framebuffer.h"
  
  #include "swrast/swrast.h"
 -#include "array_cache/acache.h"
 +#include "vbo/vbo.h"
  #include "tnl/tnl.h"
  #include "tnl/t_pipeline.h"
  #include "swrast_setup/swrast_setup.h"
Simple merge
Simple merge
     }
  
  
+ /**
+  * Helper to enable/disable client-side state.
+  */
  static void
- client_state( GLcontext *ctx, GLenum cap, GLboolean state )
+ client_state(GLcontext *ctx, GLenum cap, GLboolean state)
  {
     GLuint flag;
 -   GLuint *var;
 +   GLboolean *var;
  
     switch (cap) {
        case GL_VERTEX_ARRAY:
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1,7 -1,12 +1,7 @@@
- # List of ource files in this directory used for X.org xserver build
+ # List of source files in this directory used for X.org xserver build
  MESA_TNL_SOURCES = \
 -t_array_api.c \
 -t_array_import.c \
  t_context.c \
  t_pipeline.c \
 -t_save_api.c \
 -t_save_loopback.c \
 -t_save_playback.c \
  t_vb_arbprogram.c \
  t_vb_arbprogram_sse.c \
  t_vb_arbshader.c \
@@@ -18,4 -23,24 +18,17 @@@ t_vb_vertex.c 
  t_vertex.c \
  t_vertex_generic.c \
  t_vertex_sse.c \
 -t_vp_build.c \
 -t_vtx_api.c \
 -t_vtx_eval.c \
 -t_vtx_exec.c \
 -t_vtx_generic.c \
 -t_vtx_x86.c
 +t_vp_build.c 
+ MESA_TNL_HEADERS = \
+ t_array_api.h \
+ t_array_import.h \
+ t_context.h \
+ t_pipeline.h \
 -t_save_api.h \
+ t_vb_arbprogram.h \
+ t_vb_cliptmp.h \
+ t_vb_lighttmp.h \
+ t_vb_rendertmp.h \
+ t_vertex.h \
+ t_vp_build.h \
 -t_vtx_api.h \
+ tnl.h
Simple merge
   * program instruction formats and register layouts.
   */
  enum {
 -      BRW_ATTRIB_POS = 0,
 -      BRW_ATTRIB_WEIGHT = 1,
 -      BRW_ATTRIB_NORMAL = 2,
 -      BRW_ATTRIB_COLOR0 = 3,
 -      BRW_ATTRIB_COLOR1 = 4,
 -      BRW_ATTRIB_FOG = 5,
 -      BRW_ATTRIB_INDEX = 6,        
 -      BRW_ATTRIB_EDGEFLAG = 7,     
 -      BRW_ATTRIB_TEX0 = 8,
 -      BRW_ATTRIB_TEX1 = 9,
 -      BRW_ATTRIB_TEX2 = 10,
 -      BRW_ATTRIB_TEX3 = 11,
 -      BRW_ATTRIB_TEX4 = 12,
 -      BRW_ATTRIB_TEX5 = 13,
 -      BRW_ATTRIB_TEX6 = 14,
 -      BRW_ATTRIB_TEX7 = 15,
 +      VBO_ATTRIB_POS = 0,
 +      VBO_ATTRIB_WEIGHT = 1,
 +      VBO_ATTRIB_NORMAL = 2,
 +      VBO_ATTRIB_COLOR0 = 3,
 +      VBO_ATTRIB_COLOR1 = 4,
 +      VBO_ATTRIB_FOG = 5,
 +      VBO_ATTRIB_INDEX = 6,        
 +      VBO_ATTRIB_EDGEFLAG = 7,     
 +      VBO_ATTRIB_TEX0 = 8,
 +      VBO_ATTRIB_TEX1 = 9,
 +      VBO_ATTRIB_TEX2 = 10,
 +      VBO_ATTRIB_TEX3 = 11,
 +      VBO_ATTRIB_TEX4 = 12,
 +      VBO_ATTRIB_TEX5 = 13,
 +      VBO_ATTRIB_TEX6 = 14,
 +      VBO_ATTRIB_TEX7 = 15,
  
 -      BRW_ATTRIB_GENERIC0 = 16, /* Not used? */
 -      BRW_ATTRIB_GENERIC1 = 17,
 -      BRW_ATTRIB_GENERIC2 = 18,
 -      BRW_ATTRIB_GENERIC3 = 19,
 -      BRW_ATTRIB_GENERIC4 = 20,
 -      BRW_ATTRIB_GENERIC5 = 21,
 -      BRW_ATTRIB_GENERIC6 = 22,
 -      BRW_ATTRIB_GENERIC7 = 23,
 -      BRW_ATTRIB_GENERIC8 = 24,
 -      BRW_ATTRIB_GENERIC9 = 25,
 -      BRW_ATTRIB_GENERIC10 = 26,
 -      BRW_ATTRIB_GENERIC11 = 27,
 -      BRW_ATTRIB_GENERIC12 = 28,
 -      BRW_ATTRIB_GENERIC13 = 29,
 -      BRW_ATTRIB_GENERIC14 = 30,
 -      BRW_ATTRIB_GENERIC15 = 31,
 +      VBO_ATTRIB_GENERIC0 = 16, /* Not used? */
 +      VBO_ATTRIB_GENERIC1 = 17,
 +      VBO_ATTRIB_GENERIC2 = 18,
 +      VBO_ATTRIB_GENERIC3 = 19,
 +      VBO_ATTRIB_GENERIC4 = 20,
 +      VBO_ATTRIB_GENERIC5 = 21,
 +      VBO_ATTRIB_GENERIC6 = 22,
 +      VBO_ATTRIB_GENERIC7 = 23,
 +      VBO_ATTRIB_GENERIC8 = 24,
 +      VBO_ATTRIB_GENERIC9 = 25,
 +      VBO_ATTRIB_GENERIC10 = 26,
 +      VBO_ATTRIB_GENERIC11 = 27,
 +      VBO_ATTRIB_GENERIC12 = 28,
 +      VBO_ATTRIB_GENERIC13 = 29,
 +      VBO_ATTRIB_GENERIC14 = 30,
 +      VBO_ATTRIB_GENERIC15 = 31,
  
 -      BRW_ATTRIB_MAT_FRONT_AMBIENT = 32, 
 -      BRW_ATTRIB_MAT_BACK_AMBIENT = 33,
 -      BRW_ATTRIB_MAT_FRONT_DIFFUSE = 34,
 -      BRW_ATTRIB_MAT_BACK_DIFFUSE = 35,
 -      BRW_ATTRIB_MAT_FRONT_SPECULAR = 36,
 -      BRW_ATTRIB_MAT_BACK_SPECULAR = 37,
 -      BRW_ATTRIB_MAT_FRONT_EMISSION = 38,
 -      BRW_ATTRIB_MAT_BACK_EMISSION = 39,
 -      BRW_ATTRIB_MAT_FRONT_SHININESS = 40,
 -      BRW_ATTRIB_MAT_BACK_SHININESS = 41,
 -      BRW_ATTRIB_MAT_FRONT_INDEXES = 42,
 -      BRW_ATTRIB_MAT_BACK_INDEXES = 43, 
 +      /* XXX: in the vertex program InputsRead flag, we alias
 +       * materials and generics and use knowledge about the program
 +       * (whether it is a fixed-function emulation) to
 +       * differentiate.  Here we must keep them apart instead.
 +       */
 +      VBO_ATTRIB_MAT_FRONT_AMBIENT = 32, 
 +      VBO_ATTRIB_MAT_BACK_AMBIENT = 33,
 +      VBO_ATTRIB_MAT_FRONT_DIFFUSE = 34,
 +      VBO_ATTRIB_MAT_BACK_DIFFUSE = 35,
 +      VBO_ATTRIB_MAT_FRONT_SPECULAR = 36,
 +      VBO_ATTRIB_MAT_BACK_SPECULAR = 37,
 +      VBO_ATTRIB_MAT_FRONT_EMISSION = 38,
 +      VBO_ATTRIB_MAT_BACK_EMISSION = 39,
 +      VBO_ATTRIB_MAT_FRONT_SHININESS = 40,
 +      VBO_ATTRIB_MAT_BACK_SHININESS = 41,
 +      VBO_ATTRIB_MAT_FRONT_INDEXES = 42,
 +      VBO_ATTRIB_MAT_BACK_INDEXES = 43, 
  
 -      BRW_ATTRIB_MAX = 44
 -} ;
 +      VBO_ATTRIB_MAX = 44
 +};
  
 -#define BRW_ATTRIB_FIRST_MATERIAL BRW_ATTRIB_MAT_FRONT_AMBIENT
 -#define BRW_ATTRIB_LAST_MATERIAL BRW_ATTRIB_MAT_BACK_INDEXES
 -
 -#define BRW_MAX_COPIED_VERTS 3
 -
 -
 -static inline GLuint64EXT brw_translate_inputs( GLboolean vp_enabled,
 -                                              GLuint mesa_inputs )
 -{
 -   GLuint64EXT inputs = mesa_inputs;
 -   if (vp_enabled)
 -      return inputs;
 -   else 
 -      return (inputs & 0xffff) | ((inputs & 0xffff0000) << 16);
 -}
 +#define VBO_ATTRIB_FIRST_MATERIAL VBO_ATTRIB_MAT_FRONT_AMBIENT
++#define VBO_ATTRIB_LAST_MATERIAL VBO_ATTRIB_MAT_BACK_INDEXES
  
 +#define VBO_MAX_COPIED_VERTS 3
  
  #endif
@@@ -835,7 -855,9 +835,10 @@@ static void GLAPIENTRY _save_OBE_DrawAr
     if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
        return;
  
 -   brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
+    _ae_map_vbos( ctx );
 +   vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
++
     for (i = 0; i < count; i++)
         CALL_ArrayElement(GET_DISPATCH(), (start + i));
     CALL_End(GET_DISPATCH(), ());
@@@ -853,7 -877,9 +858,9 @@@ static void GLAPIENTRY _save_OBE_DrawEl
     if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
        return;
  
 -   brw_save_NotifyBegin( ctx, mode | BRW_SAVE_PRIM_WEAK );
+    _ae_map_vbos( ctx );
 +   vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
  
     switch (type) {
     case GL_UNSIGNED_BYTE:
@@@ -1085,18 -1113,16 +1094,18 @@@ static void vbo_print_vertex_list( GLco
  
  static void _save_current_init( GLcontext *ctx ) 
  {
 -   struct brw_save_context *save = IMM_CONTEXT(ctx)->save;
 +   struct vbo_save_context *save = &vbo_context(ctx)->save;
     GLint i;
  
 -   for (i = 0; i < BRW_ATTRIB_FIRST_MATERIAL; i++) {
 -      save->currentsz[i] = &ctx->ListState.ActiveAttribSize[i];
 -      save->current[i] = ctx->ListState.CurrentAttrib[i];
 +   for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
 +      const GLuint j = i - VBO_ATTRIB_POS;
 +      ASSERT(j < VERT_ATTRIB_MAX);
 +      save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
 +      save->current[i] = ctx->ListState.CurrentAttrib[j];
     }
  
-    for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_MAT_FRONT_AMBIENT; i++) {
 -   for (i = BRW_ATTRIB_FIRST_MATERIAL; i <= BRW_ATTRIB_LAST_MATERIAL; i++) {
 -      const GLuint j = i - BRW_ATTRIB_FIRST_MATERIAL;
++   for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
 +      const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
        ASSERT(j < MAT_ATTRIB_MAX);
        save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
        save->current[i] = ctx->ListState.CurrentMaterial[j];
  #include "light.h"
  #include "state.h"
  
 -#include "brw_save.h"
 -#include "brw_draw.h"
 -#include "brw_fallback.h"
 +#include "vbo_context.h"
 +
  
+ /*
+  * After playback, copy everything but the position from the
+  * last vertex to the saved state
+  */
  static void _playback_copy_to_current( GLcontext *ctx,
 -                                     const struct brw_save_vertex_list *node )
 +                                     const struct vbo_save_vertex_list *node )
  {
 -   struct brw_save_context *save = IMM_CONTEXT(ctx)->save; 
 -   GLfloat vertex[BRW_ATTRIB_MAX * 4], *data = vertex;
 +   struct vbo_context *vbo = vbo_context(ctx);
 +   GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex;
     GLuint i, offset;
  
     if (node->count)
     else
        offset = node->buffer_offset;
  
-    ctx->Driver.GetBufferSubData( ctx, 0, offset, node->vertex_size, 
+    ctx->Driver.GetBufferSubData( ctx, 0, offset, 
+                                node->vertex_size * sizeof(GLfloat), 
                                 data, node->vertex_store->bufferobj );
  
-    for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; i++) {
 -   for (i = 0 ; i < BRW_ATTRIB_MAX ; i++) {
++   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
        if (node->attrsz[i]) {
 -       if (i != BRW_ATTRIB_POS)
 -          COPY_CLEAN_4V(save->current[i], node->attrsz[i], data);
 +       GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
  
 -       if (i >= BRW_ATTRIB_MAT_FRONT_AMBIENT &&
 -           i <= BRW_ATTRIB_MAT_BACK_INDEXES)
 -          ctx->NewState |= _NEW_LIGHT;
 +       COPY_CLEAN_4V(current, 
 +                     node->attrsz[i], 
 +                     data);
  
 -       /* Edgeflag requires special treatment:
 -        */
 -       if (i == BRW_ATTRIB_EDGEFLAG)
 -          ctx->Current.EdgeFlag = (data[0] == 1.0);
 +       vbo->currval[i].Size = node->attrsz[i];
  
 -       data += node->attrsz[i] * sizeof(GLfloat);
 -      }
 -   }
 +       data += node->attrsz[i];
  
-        if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
-            i <= VBO_ATTRIB_MAT_BACK_INDEXES)
 -   /* Edgeflag requires special treatment:
 -    */
 -   if (node->attrsz[BRW_ATTRIB_EDGEFLAG]) {
 -      ctx->Current.EdgeFlag = (data[0] == 1.0);
++       if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
++           i <= VBO_ATTRIB_LAST_MATERIAL)
 +          ctx->NewState |= _NEW_LIGHT;
 +      }
     }
  
 -
 -#if 1
     /* Colormaterial -- this kindof sucks.
      */
     if (ctx->Light.ColorMaterialEnabled) {
index 0adad71,0000000..08eae2d
mode 100644,000000..100644
--- /dev/null
@@@ -1,549 -1,0 +1,550 @@@
-    _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag);
 +
 +/*
 + * Mesa 3-D graphics library
 + * Version:  6.5
 + *
 + * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the "Software"),
 + * to deal in the Software without restriction, including without limitation
 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 + * and/or sell copies of the Software, and to permit persons to whom the
 + * Software is furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included
 + * in all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 + *
 + * Authors:
 + *    Keith Whitwell <keith@tungstengraphics.com>
 + */
 +
 +/* Split indexed primitives with per-vertex copying.
 + */
 +
 +#include "glheader.h"
 +#include "imports.h"
 +#include "macros.h"
 +#include "enums.h"
 +#include "mtypes.h"
 +
 +#include "vbo_split.h"
 +#include "vbo.h"
 +
 +
 +#define ELT_TABLE_SIZE 16
 +
 +/* Used for vertex-level splitting of indexed buffers.  Note that
 + * non-indexed primitives may be converted to indexed in some cases
 + * (eg loops, fans) in order to use this splitting path.
 + */
 +struct copy_context {
 +
 +   GLcontext *ctx;
 +   const struct gl_client_array **array;
 +   const struct _mesa_prim *prim;
 +   GLuint nr_prims;
 +   const struct _mesa_index_buffer *ib;
 +   vbo_draw_func draw;
 +
 +   const struct split_limits *limits;
 +
 +   struct {
 +      GLuint attr;
 +      GLuint size;
 +      const struct gl_client_array *array;
 +      const GLubyte *src_ptr;
 +
 +      struct gl_client_array dstarray;
 +
 +   } varying[VERT_ATTRIB_MAX];
 +   GLuint nr_varying;
 +
 +   const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
 +   struct _mesa_index_buffer dstib;
 +
 +   GLuint *translated_elt_buf;
 +   const GLuint *srcelt;
 +
 +   /* A baby hash table to avoid re-emitting (some) duplicate
 +    * vertices when splitting indexed primitives.
 +    */
 +   struct { 
 +      GLuint in;
 +      GLuint out;
 +   } vert_cache[ELT_TABLE_SIZE];
 +      
 +
 +   GLuint vertex_size;
 +   GLubyte *dstbuf;
 +   GLubyte *dstptr;           /* dstptr == dstbuf + dstelt_max * vertsize */
 +   GLuint dstbuf_size;        /* in vertices */
 +   GLuint dstbuf_nr;          /* count of emitted vertices, also the
 +                               * largest value in dstelt.  Our
 +                               * MaxIndex.
 +                               */
 +
 +   GLuint *dstelt;
 +   GLuint dstelt_nr;
 +   GLuint dstelt_size;
 +
 +#define MAX_PRIM 32
 +   struct _mesa_prim dstprim[MAX_PRIM];
 +   GLuint dstprim_nr;
 +
 +};
 +
 +
 +static GLuint type_size( GLenum type )
 +{
 +   switch(type) {
 +   case GL_BYTE: return sizeof(GLbyte);
 +   case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
 +   case GL_SHORT: return sizeof(GLshort);
 +   case GL_UNSIGNED_SHORT: return sizeof(GLushort);
 +   case GL_INT: return sizeof(GLint);
 +   case GL_UNSIGNED_INT: return sizeof(GLuint);
 +   case GL_FLOAT: return sizeof(GLfloat);
 +   case GL_DOUBLE: return sizeof(GLdouble);
 +   default: return 0;
 +   }
 +}
 +
 +static GLuint attr_size( const struct gl_client_array *array )
 +{
 +   return array->Size * type_size(array->Type);
 +}
 +
 +
 +/* Starts returning true slightly before the buffer fills, to ensure
 + * that there is sufficient room for any remaining vertices to finish
 + * off the prim:
 + */
 +static GLboolean check_flush( struct copy_context *copy )
 +{
 +   if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
 +      return GL_TRUE;
 +
 +   if (copy->dstelt_nr + 4 > copy->dstelt_size)
 +      return GL_TRUE;
 +
 +   return GL_FALSE;
 +}
 +
 +static void flush( struct copy_context *copy )
 +{
 +   GLuint i;
 +
 +   /* Set some counters: 
 +    */
 +   copy->dstib.count = copy->dstelt_nr;
 +
 +   copy->draw( copy->ctx,
 +             copy->dstarray_ptr,
 +             copy->dstprim,
 +             copy->dstprim_nr,
 +             &copy->dstib,
 +             0,
 +             copy->dstbuf_nr );
 +
 +   /* Reset all pointers: 
 +    */
 +   copy->dstprim_nr = 0;
 +   copy->dstelt_nr = 0;
 +   copy->dstbuf_nr = 0;
 +   copy->dstptr = copy->dstbuf;
 +
 +   /* Clear the vertex cache:
 +    */
 +   for (i = 0; i < ELT_TABLE_SIZE; i++)
 +      copy->vert_cache[i].in = ~0;
 +}
 +
 +
 +
 +static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
 +{
 +   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
 +
-    _mesa_printf("elt %d\n", elt);
++/*    _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); */
 +              
 +   prim->mode = mode;
 +   prim->begin = begin_flag;
 +}
 +
 +
 +/* Use a hashtable to attempt to identify recently-emitted vertices
 + * and avoid re-emitting them.
 + */
 +static GLuint elt(struct copy_context *copy, GLuint elt_idx)
 +{
 +   GLuint elt = copy->srcelt[elt_idx];
 +   GLuint slot = elt & (ELT_TABLE_SIZE-1);
 +
-       _mesa_printf("  --> emit to dstelt %d\n", copy->dstbuf_nr);
++/*    _mesa_printf("elt %d\n", elt); */
 +
 +   /* Look up the incoming element in the vertex cache.  Re-emit if
 +    * necessary.   
 +    */
 +   if (copy->vert_cache[slot].in != elt) {
 +      GLubyte *csr = copy->dstptr;
 +      GLuint i;
 +
-    else
-       _mesa_printf("  --> reuse vertex\n");
++/*       _mesa_printf("  --> emit to dstelt %d\n", copy->dstbuf_nr); */
 +
 +      for (i = 0; i < copy->nr_varying; i++) {
 +       const struct gl_client_array *srcarray = copy->varying[i].array;
 +       const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
 +
 +       memcpy(csr, srcptr, copy->varying[i].size);
 +       csr += copy->varying[i].size;
 +
++       if (0) 
 +       {
 +          const GLuint *f = (const GLuint *)srcptr;
 +          GLuint j;
 +          _mesa_printf("  varying %d: ", i);
 +          for(j = 0; j < copy->varying[i].size / 4; j++)
 +             _mesa_printf("%x ", f[j]);
 +          _mesa_printf("\n");
 +       }
 +             
 +      }
 +
 +      copy->vert_cache[slot].in = elt;
 +      copy->vert_cache[slot].out = copy->dstbuf_nr++;
 +      copy->dstptr += copy->vertex_size;
 +
 +      assert(csr == copy->dstptr);
 +      assert(copy->dstptr == (copy->dstbuf + 
 +                                  copy->dstbuf_nr * 
 +                                  copy->vertex_size));
 +   }
-    _mesa_printf("  --> emit %d\n", copy->vert_cache[slot].out);
++/*    else */
++/*       _mesa_printf("  --> reuse vertex\n"); */
 +   
-    _mesa_printf("end (%d)\n", end_flag);
++/*    _mesa_printf("  --> emit %d\n", copy->vert_cache[slot].out); */
 +   copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
 +   return check_flush(copy);
 +}
 +
 +static void end( struct copy_context *copy, GLboolean end_flag )
 +{
 +   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
 +
++/*    _mesa_printf("end (%d)\n", end_flag); */
 +
 +   prim->end = end_flag;
 +   prim->count = copy->dstelt_nr - prim->start;
 +
 +   if (++copy->dstprim_nr == MAX_PRIM ||
 +       check_flush(copy)) 
 +      flush(copy);
 +}
 +
 +
 +
 +static void replay_elts( struct copy_context *copy )
 +{
 +   GLuint i, j, k;
 +   GLboolean split;
 +
 +   for (i = 0; i < copy->nr_prims; i++) {
 +      const struct _mesa_prim *prim = &copy->prim[i];
 +      const GLuint start = prim->start;
 +      GLuint first, incr;
 +
 +      switch (prim->mode) {
 +       
 +      case GL_LINE_LOOP:
 +       /* Convert to linestrip and emit the final vertex explicitly,
 +        * but only in the resultant strip that requires it.
 +        */
 +       j = 0;
 +       while (j != prim->count) {
 +          begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
 +
 +          for (split = GL_FALSE; j != prim->count && !split; j++)
 +             split = elt(copy, start + j);
 +
 +          if (j == prim->count) {
 +             /* Done, emit final line.  Split doesn't matter as
 +              * it is always raised a bit early so we can emit
 +              * the last verts if necessary!
 +              */
 +             if (prim->end) 
 +                (void)elt(copy, start + 0);
 +
 +             end(copy, prim->end);
 +          }
 +          else {
 +             /* Wrap
 +              */
 +             assert(split);
 +             end(copy, 0);
 +             j--;
 +          }
 +       }
 +       break;
 +
 +      case GL_TRIANGLE_FAN:
 +      case GL_POLYGON:
 +       j = 2;
 +       while (j != prim->count) {
 +          begin(copy, prim->mode, prim->begin && j == 0);
 +
 +          split = elt(copy, start+0); 
 +          assert(!split);
 +
 +          split = elt(copy, start+j-1); 
 +          assert(!split);
 +
 +          for (; j != prim->count && !split; j++)
 +             split = elt(copy, start+j);
 +
 +          end(copy, prim->end && j == prim->count);
 +
 +          if (j != prim->count) {
 +             /* Wrapped the primitive, need to repeat some vertices:
 +              */
 +             j -= 1;
 +          }
 +       }
 +       break;
 +
 +      default:
 +       (void)split_prim_inplace(prim->mode, &first, &incr);
 +       
 +       j = 0;
 +       while (j != prim->count) {
 +
 +          begin(copy, prim->mode, prim->begin && j == 0);
 +
 +          split = 0;
 +          for (k = 0; k < first; k++, j++)
 +             split |= elt(copy, start+j);
 +
 +          assert(!split);
 +
 +          for (; j != prim->count && !split; )
 +             for (k = 0; k < incr; k++, j++)
 +                split |= elt(copy, start+j);
 +
 +          end(copy, prim->end && j == prim->count);
 +
 +          if (j != prim->count) {
 +             /* Wrapped the primitive, need to repeat some vertices:
 +              */
 +             assert(j > first - incr);
 +             j -= (first - incr);
 +          }
 +       }
 +       break;
 +      }
 +   }
 +
 +   if (copy->dstprim_nr)
 +      flush(copy);
 +}
 +
 +
 +static void replay_init( struct copy_context *copy )
 +{
 +   GLcontext *ctx = copy->ctx;
 +   GLuint i;
 +   GLuint offset;
 +
 +   /* Make a list of varying attributes and their vbo's.  Also
 +    * calculate vertex size.
 +    */
 +   copy->vertex_size = 0;
 +   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
 +      struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
 +
 +      if (copy->array[i]->StrideB == 0) {
 +       copy->dstarray_ptr[i] = copy->array[i];
 +      }
 +      else {
 +       GLuint j = copy->nr_varying++;
 +       
 +       copy->varying[j].attr = i;
 +       copy->varying[j].array = copy->array[i];
 +       copy->varying[j].size = attr_size(copy->array[i]);
 +       copy->vertex_size += attr_size(copy->array[i]);
 +      
 +       if (vbo->Name && !vbo->Pointer) 
 +          ctx->Driver.MapBuffer(ctx,
 +                                GL_ARRAY_BUFFER_ARB, 
 +                                GL_DYNAMIC_DRAW_ARB, /* XXX */
 +                                vbo);
 +
 +       copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
 +                                               copy->array[i]->Ptr);
 +
 +       copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
 +      }
 +   }
 +
 +   /* There must always be an index buffer.  Currently require the
 +    * caller convert non-indexed prims to indexed.  Could alternately
 +    * do it internally.
 +    */
 +   if (copy->ib->obj->Name && !copy->ib->obj->Pointer) 
 +      ctx->Driver.MapBuffer(ctx, 
 +                          GL_ARRAY_BUFFER_ARB, /* XXX */
 +                          GL_DYNAMIC_DRAW_ARB, /* XXX */
 +                          copy->ib->obj);
 +
 +   switch (copy->ib->type) {
 +   case GL_UNSIGNED_BYTE:
 +      copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count);
 +      copy->srcelt = copy->translated_elt_buf;
 +      
 +      for (i = 0; i < copy->ib->count; i++)
 +       copy->translated_elt_buf[i] = ((const GLubyte *)copy->ib->ptr)[i];
 +      break;
 +
 +   case GL_UNSIGNED_SHORT:
 +      copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count);
 +      copy->srcelt = copy->translated_elt_buf;
 +
 +      for (i = 0; i < copy->ib->count; i++)
 +       copy->translated_elt_buf[i] = ((const GLushort *)copy->ib->ptr)[i];
 +      break;
 +
 +   case GL_UNSIGNED_INT:
 +      copy->translated_elt_buf = NULL;
 +      copy->srcelt = (const GLuint *)ADD_POINTERS(copy->ib->obj->Pointer, 
 +                                                copy->ib->ptr);
 +      break;
 +   }
 +   
 +
 +   /* Figure out the maximum allowed vertex buffer size:
 +    */
 +   if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
 +      copy->dstbuf_size = copy->limits->max_verts;
 +   }
 +   else {
 +      copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
 +   }
 +
 +   /* Allocate an output vertex buffer:
 +    *
 +    * XXX:  This should be a VBO!
 +    */
 +   copy->dstbuf = _mesa_malloc(copy->dstbuf_size * 
 +                             copy->vertex_size);   
 +   copy->dstptr = copy->dstbuf;
 +
 +   /* Setup new vertex arrays to point into the output buffer: 
 +    */
 +   for (offset = 0, i = 0; i < copy->nr_varying; i++) {
 +      const struct gl_client_array *src = copy->varying[i].array;
 +      struct gl_client_array *dst = &copy->varying[i].dstarray;
 +
 +      dst->Size = src->Size;
 +      dst->Type = src->Type;
 +      dst->Stride = copy->vertex_size;
 +      dst->StrideB = copy->vertex_size;
 +      dst->Ptr = copy->dstbuf + offset;
 +      dst->Enabled = GL_TRUE;
 +      dst->Normalized = GL_TRUE;
 +      dst->BufferObj = ctx->Array.NullBufferObj;
 +      dst->_MaxElement = copy->dstbuf_size; /* may be less! */
 +
 +      offset += copy->varying[i].size;
 +   }
 +
 +   /* Allocate an output element list:
 +    */
 +   copy->dstelt_size = MIN2(65536,
 +                          copy->ib->count * 2);
 +   copy->dstelt_size = MIN2(copy->dstelt_size,
 +                          copy->limits->max_indices);
 +   copy->dstelt = _mesa_malloc(copy->dstelt_size);
 +   copy->dstelt_nr = 0;
 +
 +   /* Setup the new index buffer to point to the allocated element
 +    * list:
 +    */
 +   copy->dstib.count = 0;     /* duplicates dstelt_nr */
 +   copy->dstib.type = GL_UNSIGNED_INT;
 +   copy->dstib.obj = ctx->Array.NullBufferObj;
 +   copy->dstib.ptr = copy->dstelt;
 +   copy->dstib.rebase = 0;    
 +}
 +
 +
 +static void replay_finish( struct copy_context *copy )
 +{
 +   GLcontext *ctx = copy->ctx;
 +   GLuint i;
 +
 +   /* Free our vertex and index buffers: 
 +    */
 +   _mesa_free(copy->translated_elt_buf);
 +   _mesa_free(copy->dstbuf);
 +   _mesa_free(copy->dstelt);
 +   
 +   /* Unmap VBO's 
 +    */
 +   for (i = 0; i < copy->nr_varying; i++) {
 +      struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
 +
 +      if (vbo->Name && vbo->Pointer) 
 +       ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vbo);
 +   }
 +
 +   /* Unmap index buffer:
 +    */
 +   if (copy->ib->obj->Name && copy->ib->obj->Pointer) {
 +      ctx->Driver.UnmapBuffer(ctx, 
 +                            GL_ARRAY_BUFFER_ARB, /* XXX */
 +                            copy->ib->obj);
 +   }
 +}
 +
 +void vbo_split_copy( GLcontext *ctx,
 +                   const struct gl_client_array *arrays[],
 +                   const struct _mesa_prim *prim,
 +                   GLuint nr_prims,
 +                   const struct _mesa_index_buffer *ib,
 +                   vbo_draw_func draw,
 +                   const struct split_limits *limits )
 +{
 +   struct copy_context copy;
 +   GLuint i;
 +
 +   memset(&copy, 0, sizeof(copy));
 +
 +   /* Require indexed primitives:
 +    */
 +   assert(ib);
 +   
 +   copy.ctx = ctx;
 +   copy.array = arrays;
 +   copy.prim = prim;
 +   copy.nr_prims = nr_prims;
 +   copy.ib = ib;
 +   copy.draw = draw;
 +   copy.limits = limits;
 +
 +
 +   /* Clear the vertex cache:
 +    */
 +   for (i = 0; i < ELT_TABLE_SIZE; i++)
 +      copy.vert_cache[i].in = ~0;
 +
 +
 +   replay_init(&copy);
 +   replay_elts(&copy);
 +   replay_finish(&copy);
 +}