mesa: merge gallium-0.2 into gallium-master-merge
authorBrian Paul <brianp@vmware.com>
Mon, 9 Feb 2009 16:22:22 +0000 (09:22 -0700)
committerBrian Paul <brianp@vmware.com>
Mon, 9 Feb 2009 16:22:22 +0000 (09:22 -0700)
Merge commit 'origin/gallium-0.2' into gallium-master-merge

Conflicts:

Makefile
docs/relnotes-7.4.html
docs/relnotes.html
src/mesa/drivers/dri/i965/brw_wm.h
src/mesa/main/imports.c
src/mesa/main/mtypes.h
src/mesa/main/texcompress.c
src/mesa/main/texenvprogram.c
src/mesa/main/version.h
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_save_draw.c

34 files changed:
1  2 
Makefile
configs/autoconf.in
configure.ac
progs/demos/engine.c
src/glx/x11/glxclient.h
src/mesa/drivers/dri/common/utils.c
src/mesa/drivers/dri/common/utils.h
src/mesa/main/buffers.c
src/mesa/main/context.c
src/mesa/main/enable.c
src/mesa/main/extensions.c
src/mesa/main/fbobject.c
src/mesa/main/imports.c
src/mesa/main/imports.h
src/mesa/main/mtypes.h
src/mesa/main/renderbuffer.c
src/mesa/main/texcompress.c
src/mesa/main/texenvprogram.c
src/mesa/main/texformat.c
src/mesa/main/teximage.c
src/mesa/main/version.h
src/mesa/shader/arbprogparse.c
src/mesa/shader/prog_print.c
src/mesa/shader/prog_print.h
src/mesa/shader/prog_statevars.c
src/mesa/shader/shader_api.c
src/mesa/shader/slang/slang_link.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_draw.c
src/mesa/tnl/t_context.c
src/mesa/vbo/vbo_context.c
src/mesa/vbo/vbo_exec_api.c
src/mesa/vbo/vbo_exec_draw.c
src/mesa/vbo/vbo_save_draw.c

diff --cc Makefile
Simple merge
Simple merge
diff --cc configure.ac
Simple merge
Simple merge
index bdc6287a452a02f75825a6ef719c5559836967c2,467b0ebb7f9a7899bbb46ba32b7b31c88335878f..9332eb64d3b738cc9bec9ce99896359b30b5c3b6
@@@ -602,9 -602,10 +602,11 @@@ extern void __glXSendLargeCommand(__GLX
                                  const GLvoid *, GLint);
  
  /* Initialize the GLX extension for dpy */
 +extern __GLXdisplayPrivate * __glXGetPrivateFromDisplay(Display *dpy);
  extern __GLXdisplayPrivate *__glXInitialize(Display*);
  
+ extern void __glXPreferEGL(int state);
  /************************************************************************/
  
  extern int __glXDebug;
Simple merge
index b0908e530a57d10a3d2244b4c6b317dc6c978bf9,4e27bd21a1f1cacf94edf72103e9dc58359441a9..a4ef5092478ab6f067db748a0acaf16ad4a0bf97
@@@ -131,10 -131,10 +131,11 @@@ extern __DRIconfig *
  driCreateConfigs(GLenum fb_format, GLenum fb_type,
                 const uint8_t * depth_bits, const uint8_t * stencil_bits,
                 unsigned num_depth_stencil_bits,
-                const GLenum * db_modes, unsigned num_db_modes);
+                const GLenum * db_modes, unsigned num_db_modes,
+                const uint8_t * msaa_samples, unsigned num_msaa_modes);
  
 -const __DRIconfig **driConcatConfigs(__DRIconfig **a, __DRIconfig **b);
 +const __DRIconfig **driConcatConfigs(const __DRIconfig **a,
 +                                   const __DRIconfig **b);
  
  int
  driGetConfigAttrib(const __DRIconfig *config,
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0c2c894eef024518f69ac0acdd72570a638e2ecf,69d55923c37b78ebbe9472c317873c9d31b5be3c..cb04594c1fd83687c948b5e10e8c6fc42a65e403
@@@ -950,27 -946,12 +946,25 @@@ _mesa_snprintf( char *str, size_t size
  void
  _mesa_printf( const char *fmtString, ... )
  {
-    char s[MAXSTRING];
     va_list args;
     va_start( args, fmtString );  
-    vsnprintf(s, MAXSTRING, fmtString, args);
+    vfprintf(stderr, fmtString, args);
     va_end( args );
-    fprintf(stderr, "%s", s);
  }
  
 +/** Wrapper around fprintf(), using vsprintf() for the formatting. */
 +void
 +_mesa_fprintf( FILE *f, const char *fmtString, ... )
 +{
 +   char s[MAXSTRING];
 +   va_list args;
 +   va_start( args, fmtString );  
 +   vsnprintf(s, MAXSTRING, fmtString, args);
 +   va_end( args );
 +   fprintf(f, "%s", s);
 +}
 +
 +
  /** Wrapper around vsprintf() */
  int
  _mesa_vsprintf( char *str, const char *fmt, va_list args )
Simple merge
Simple merge
Simple merge
Simple merge
index 066f3bd0bec1df855bbbebbd676d0e2cd0a6e977,48abf51d89057f0b0eccdfb000ec2003c2c2d920..10edfc8fb80ef71b06c392eb0c17adaeb83ff79b
@@@ -232,17 -206,17 +232,19 @@@ static GLuint translate_mode( GLenum en
  #define TEXTURE_UNKNOWN_INDEX 7
  static GLuint translate_tex_src_bit( GLbitfield bit )
  {
+    /* make sure number of switch cases is correct */
+    assert(NUM_TEXTURE_TARGETS == 7);
     switch (bit) {
 -   case TEXTURE_1D_BIT:         return TEXTURE_1D_INDEX;
 -   case TEXTURE_2D_BIT:         return TEXTURE_2D_INDEX;
 -   case TEXTURE_3D_BIT:         return TEXTURE_3D_INDEX;
 -   case TEXTURE_CUBE_BIT:       return TEXTURE_CUBE_INDEX;
 -   case TEXTURE_RECT_BIT:       return TEXTURE_RECT_INDEX;
 -   case TEXTURE_1D_ARRAY_BIT:   return TEXTURE_1D_ARRAY_INDEX;
 -   case TEXTURE_2D_ARRAY_BIT:   return TEXTURE_2D_ARRAY_INDEX;
 -   default:                     return TEXTURE_UNKNOWN_INDEX;
 +   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
 +   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
 +   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
 +   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
 +   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
 +   case TEXTURE_1D_ARRAY_BIT: return TEXTURE_1D_ARRAY_INDEX;
 +   case TEXTURE_2D_ARRAY_BIT: return TEXTURE_2D_ARRAY_INDEX;
 +   default:
 +      assert(0);
 +      return TEXTURE_UNKNOWN_INDEX;
     }
  }
  
Simple merge
Simple merge
index f5bf6e2c855e72ffd8be0f34265b943e7fb2c56a,84dcb263c6d6b2056b54095ad9f0c436729169fc..9287e8515cc2d3e79d7020a510c3904966619cf8
@@@ -1,6 -1,6 +1,10 @@@
  /*
   * Mesa 3-D graphics library
++<<<<<<< HEAD:src/mesa/main/version.h
 + * Version:  7.5
++=======
+  * Version:  7.4
++>>>>>>> origin/gallium-0.2:src/mesa/main/version.h
   *
   * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
   *
Simple merge
Simple merge
Simple merge
Simple merge
index fb2a7e54fe6de28fdd813ae8bd4a9eb177141e4b,122688826cd437fb397c32be4f21a1c06232bb65..a5cf1ca1d440a7830a93e067c19ca8c0d7f30f84
@@@ -406,9 -381,8 +406,9 @@@ _mesa_init_shader_state(GLcontext * ctx
      * are generated by the GLSL compiler.
      */
     ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
-    ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
+    ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */
     ctx->Shader.EmitComments = GL_FALSE;
 +   ctx->Shader.Flags = get_shader_flags();
  }
  
  
Simple merge
index 0000000000000000000000000000000000000000,963ac902d2c695f04f6f6e27dd99cfd32e11b6d8..9af648b8d0fda6a04fc81576fe0b5ad4e08d182b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,458 +1,458 @@@
 -   template.nr_samples = rb->Samples;
+ /**************************************************************************
+  * 
+  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+  * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+  * 
+  **************************************************************************/
+ /**
+  * Framebuffer/renderbuffer functions.
+  *
+  * \author Brian Paul
+  */
+ #include "main/imports.h"
+ #include "main/context.h"
+ #include "main/fbobject.h"
+ #include "main/framebuffer.h"
+ #include "main/renderbuffer.h"
+ #include "pipe/p_context.h"
+ #include "pipe/p_defines.h"
+ #include "pipe/p_inlines.h"
+ #include "pipe/p_screen.h"
+ #include "st_context.h"
+ #include "st_cb_fbo.h"
+ #include "st_cb_texture.h"
+ #include "st_format.h"
+ #include "st_public.h"
+ #include "st_texture.h"
+ /**
+  * Compute the renderbuffer's Red/Green/EtcBit fields from the pipe format.
+  */
+ static int
+ init_renderbuffer_bits(struct st_renderbuffer *strb,
+                        enum pipe_format pipeFormat)
+ {
+    struct pipe_format_info info;
+    if (!st_get_format_info( pipeFormat, &info )) {
+       assert( 0 );
+    }
+    strb->Base._ActualFormat = info.base_format;
+    strb->Base.RedBits = info.red_bits;
+    strb->Base.GreenBits = info.green_bits;
+    strb->Base.BlueBits = info.blue_bits;
+    strb->Base.AlphaBits = info.alpha_bits;
+    strb->Base.DepthBits = info.depth_bits;
+    strb->Base.StencilBits = info.stencil_bits;
+    strb->Base.DataType = st_format_datatype(pipeFormat);
+    return info.size;
+ }
+ /**
+  * gl_renderbuffer::AllocStorage()
+  * This is called to allocate the original drawing surface, and
+  * during window resize.
+  */
+ static GLboolean
+ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+                               GLenum internalFormat,
+                               GLuint width, GLuint height)
+ {
+    struct pipe_context *pipe = ctx->st->pipe;
+    struct st_renderbuffer *strb = st_renderbuffer(rb);
+    struct pipe_texture template;
+    unsigned surface_usage;
+    /* Free the old surface and texture
+     */
+    pipe_surface_reference( &strb->surface, NULL );
+    pipe_texture_reference( &strb->texture, NULL );
+    memset(&template, 0, sizeof(template));
+    if (strb->format != PIPE_FORMAT_NONE) {
+       template.format = strb->format;
+    }
+    else {
+       template.format = st_choose_renderbuffer_format(pipe, internalFormat);
+    }
+    strb->Base.Width  = width;
+    strb->Base.Height = height;
+    init_renderbuffer_bits(strb, template.format);
+    template.target = PIPE_TEXTURE_2D;
+    template.compressed = 0;
+    pf_get_block(template.format, &template.block);
+    template.width[0] = width;
+    template.height[0] = height;
+    template.depth[0] = 1;
+    template.last_level = 0;
 -   strb->Base.Samples = samples;
++   template.nr_samples = rb->NumSamples;
+    if (pf_is_depth_stencil(template.format)) {
+       template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+    }
+    else {
+       template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                             PIPE_TEXTURE_USAGE_RENDER_TARGET);
+    }
+    /* Probably need dedicated flags for surface usage too: 
+     */
+    surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
+                     PIPE_BUFFER_USAGE_GPU_WRITE);
+ #if 0
+                     PIPE_BUFFER_USAGE_CPU_READ |
+                     PIPE_BUFFER_USAGE_CPU_WRITE);
+ #endif
+    strb->texture = pipe->screen->texture_create( pipe->screen,
+                                                  &template );
+    /* Special path for accum buffers.  
+     *
+     * Try a different surface format.  Since accum buffers are s/w
+     * only for now, the surface pixel format doesn't really matter,
+     * only that the buffer is large enough.
+     */
+    if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT) 
+    {
+       /* Actually, just setting this usage value should be sufficient
+        * to tell the driver to go ahead and allocate the buffer, even
+        * if HW doesn't support the format.
+        */
+       template.tex_usage = 0;
+       surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
+                        PIPE_BUFFER_USAGE_CPU_WRITE);
+       strb->texture = pipe->screen->texture_create( pipe->screen,
+                                                     &template );
+    }
+    if (!strb->texture) 
+       return FALSE;
+    strb->surface = pipe->screen->get_tex_surface( pipe->screen,
+                                                   strb->texture,
+                                                   0, 0, 0,
+                                                   surface_usage );
+    assert(strb->surface->texture);
+    assert(strb->surface->format);
+    assert(strb->surface->block.size);
+    assert(strb->surface->block.width);
+    assert(strb->surface->block.height);
+    assert(strb->surface->width == width);
+    assert(strb->surface->height == height);
+    assert(strb->surface->stride);
+    return strb->surface != NULL;
+ }
+ /**
+  * gl_renderbuffer::Delete()
+  */
+ static void
+ st_renderbuffer_delete(struct gl_renderbuffer *rb)
+ {
+    struct st_renderbuffer *strb = st_renderbuffer(rb);
+    ASSERT(strb);
+    pipe_surface_reference(&strb->surface, NULL);
+    pipe_texture_reference(&strb->texture, NULL);
+    free(strb);
+ }
+ /**
+  * gl_renderbuffer::GetPointer()
+  */
+ static void *
+ null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
+                  GLint x, GLint y)
+ {
+    /* By returning NULL we force all software rendering to go through
+     * the span routines.
+     */
+ #if 0
+    assert(0);  /* Should never get called with softpipe */
+ #endif
+    return NULL;
+ }
+ /**
+  * Called via ctx->Driver.NewFramebuffer()
+  */
+ static struct gl_framebuffer *
+ st_new_framebuffer(GLcontext *ctx, GLuint name)
+ {
+    /* XXX not sure we need to subclass gl_framebuffer for pipe */
+    return _mesa_new_framebuffer(ctx, name);
+ }
+ /**
+  * Called via ctx->Driver.NewRenderbuffer()
+  */
+ static struct gl_renderbuffer *
+ st_new_renderbuffer(GLcontext *ctx, GLuint name)
+ {
+    struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
+    if (strb) {
+       _mesa_init_renderbuffer(&strb->Base, name);
+       strb->Base.Delete = st_renderbuffer_delete;
+       strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+       strb->Base.GetPointer = null_get_pointer;
+       strb->format = PIPE_FORMAT_NONE;
+       return &strb->Base;
+    }
+    return NULL;
+ }
+ /**
+  * Allocate a renderbuffer for a an on-screen window (not a user-created
+  * renderbuffer).  The window system code determines the format.
+  */
+ struct gl_renderbuffer *
+ st_new_renderbuffer_fb(enum pipe_format format, int samples)
+ {
+    struct st_renderbuffer *strb;
+    strb = CALLOC_STRUCT(st_renderbuffer);
+    if (!strb) {
+       _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
+       return NULL;
+    }
+    _mesa_init_renderbuffer(&strb->Base, 0);
+    strb->Base.ClassID = 0x4242; /* just a unique value */
++   strb->Base.NumSamples = samples;
+    strb->format = format;
+    switch (format) {
+    case PIPE_FORMAT_A8R8G8B8_UNORM:
+    case PIPE_FORMAT_B8G8R8A8_UNORM:
+    case PIPE_FORMAT_X8R8G8B8_UNORM:
+    case PIPE_FORMAT_B8G8R8X8_UNORM:
+    case PIPE_FORMAT_A1R5G5B5_UNORM:
+    case PIPE_FORMAT_A4R4G4B4_UNORM:
+    case PIPE_FORMAT_R5G6B5_UNORM:
+       strb->Base.InternalFormat = GL_RGBA;
+       strb->Base._BaseFormat = GL_RGBA;
+       break;
+    case PIPE_FORMAT_Z16_UNORM:
+       strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
+       strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+       break;
+    case PIPE_FORMAT_Z32_UNORM:
+       strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
+       strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+       break;
+    case PIPE_FORMAT_S8Z24_UNORM:
+    case PIPE_FORMAT_Z24S8_UNORM:
+    case PIPE_FORMAT_X8Z24_UNORM:
+    case PIPE_FORMAT_Z24X8_UNORM:
+       strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+       strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+       break;
+    case PIPE_FORMAT_S8_UNORM:
+       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
+       strb->Base._BaseFormat = GL_STENCIL_INDEX;
+       break;
+    case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/
+       strb->Base.InternalFormat = GL_RGBA16;
+       strb->Base._BaseFormat = GL_RGBA;
+       break;
+    default:
+       _mesa_problem(NULL,
+                   "Unexpected format in st_new_renderbuffer_fb");
+       return NULL;
+    }
+    /* st-specific methods */
+    strb->Base.Delete = st_renderbuffer_delete;
+    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
+    strb->Base.GetPointer = null_get_pointer;
+    /* surface is allocated in st_renderbuffer_alloc_storage() */
+    strb->surface = NULL;
+    return &strb->Base;
+ }
+ /**
+  * Called via ctx->Driver.BindFramebufferEXT().
+  */
+ static void
+ st_bind_framebuffer(GLcontext *ctx, GLenum target,
+                     struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
+ {
+ }
+ /**
+  * Called by ctx->Driver.FramebufferRenderbuffer
+  */
+ static void
+ st_framebuffer_renderbuffer(GLcontext *ctx, 
+                             struct gl_framebuffer *fb,
+                             GLenum attachment,
+                             struct gl_renderbuffer *rb)
+ {
+    /* XXX no need for derivation? */
+    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+ }
+ /**
+  * Called by ctx->Driver.RenderTexture
+  */
+ static void
+ st_render_texture(GLcontext *ctx,
+                   struct gl_framebuffer *fb,
+                   struct gl_renderbuffer_attachment *att)
+ {
+    struct st_renderbuffer *strb;
+    struct gl_renderbuffer *rb;
+    struct pipe_texture *pt = st_get_texobj_texture(att->Texture);
+    struct st_texture_object *stObj;
+    const struct gl_texture_image *texImage =
+       att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+    if (!pt) 
+       return;
+    assert(!att->Renderbuffer);
+    /* create new renderbuffer which wraps the texture image */
+    rb = st_new_renderbuffer(ctx, 0);
+    if (!rb) {
+       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
+       return;
+    }
+    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+    assert(rb->RefCount == 1);
+    rb->AllocStorage = NULL; /* should not get called */
+    strb = st_renderbuffer(rb);
+    /* get the texture for the texture object */
+    stObj = st_texture_object(att->Texture);
+    /* point renderbuffer at texobject */
+    strb->rtt = stObj;
+    strb->rtt_level = att->TextureLevel;
+    strb->rtt_face = att->CubeMapFace;
+    strb->rtt_slice = att->Zoffset;
+    rb->Width = texImage->Width2;
+    rb->Height = texImage->Height2;
+    /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
+    /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/
+    pipe_texture_reference( &strb->texture, pt );
+    pipe_surface_reference(&strb->surface, NULL);
+    /* the new surface will be created during framebuffer validation */
+    init_renderbuffer_bits(strb, pt->format);
+    /*
+    printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
+           att->Texture, pt, strb->surface, rb->Width, rb->Height);
+    */
+    /* Invalidate buffer state so that the pipe's framebuffer state
+     * gets updated.
+     * That's where the new renderbuffer (which we just created) gets
+     * passed to the pipe as a (color/depth) render target.
+     */
+    st_invalidate_state(ctx, _NEW_BUFFERS);
+ }
+ /**
+  * Called via ctx->Driver.FinishRenderTexture.
+  */
+ static void
+ st_finish_render_texture(GLcontext *ctx,
+                          struct gl_renderbuffer_attachment *att)
+ {
+    struct pipe_screen *screen = ctx->st->pipe->screen;
+    struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
+    if (!strb)
+       return;
+    st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
+    if (strb->surface)
+       screen->tex_surface_release( screen, &strb->surface );
+    strb->rtt = NULL;
+    /*
+    printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
+    */
+    _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+    /* restore previous framebuffer state */
+    st_invalidate_state(ctx, _NEW_BUFFERS);
+ }
+ void st_init_fbo_functions(struct dd_function_table *functions)
+ {
+    functions->NewFramebuffer = st_new_framebuffer;
+    functions->NewRenderbuffer = st_new_renderbuffer;
+    functions->BindFramebuffer = st_bind_framebuffer;
+    functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
+    functions->RenderTexture = st_render_texture;
+    functions->FinishRenderTexture = st_finish_render_texture;
+    /* no longer needed by core Mesa, drivers handle resizes...
+    functions->ResizeBuffers = st_resize_buffers;
+    */
+ }
index 0000000000000000000000000000000000000000,942f913ea21e7f49c7508c4affc4c639f47fcbae..ae71d586c2fabac8e684c697b87686098005e27b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,697 +1,699 @@@
+ /**************************************************************************
+  * 
+  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+  * 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, 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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>
+   */
+ #include "main/imports.h"
+ #include "main/image.h"
+ #include "main/macros.h"
+ #include "shader/prog_uniform.h"
+ #include "vbo/vbo.h"
+ #include "st_context.h"
+ #include "st_atom.h"
+ #include "st_cb_bufferobjects.h"
+ #include "st_draw.h"
+ #include "st_program.h"
+ #include "pipe/p_context.h"
+ #include "pipe/p_defines.h"
+ #include "pipe/p_inlines.h"
+ static GLuint double_types[4] = {
+    PIPE_FORMAT_R64_FLOAT,
+    PIPE_FORMAT_R64G64_FLOAT,
+    PIPE_FORMAT_R64G64B64_FLOAT,
+    PIPE_FORMAT_R64G64B64A64_FLOAT
+ };
+ static GLuint float_types[4] = {
+    PIPE_FORMAT_R32_FLOAT,
+    PIPE_FORMAT_R32G32_FLOAT,
+    PIPE_FORMAT_R32G32B32_FLOAT,
+    PIPE_FORMAT_R32G32B32A32_FLOAT
+ };
+ static GLuint uint_types_norm[4] = {
+    PIPE_FORMAT_R32_UNORM,
+    PIPE_FORMAT_R32G32_UNORM,
+    PIPE_FORMAT_R32G32B32_UNORM,
+    PIPE_FORMAT_R32G32B32A32_UNORM
+ };
+ static GLuint uint_types_scale[4] = {
+    PIPE_FORMAT_R32_USCALED,
+    PIPE_FORMAT_R32G32_USCALED,
+    PIPE_FORMAT_R32G32B32_USCALED,
+    PIPE_FORMAT_R32G32B32A32_USCALED
+ };
+ static GLuint int_types_norm[4] = {
+    PIPE_FORMAT_R32_SNORM,
+    PIPE_FORMAT_R32G32_SNORM,
+    PIPE_FORMAT_R32G32B32_SNORM,
+    PIPE_FORMAT_R32G32B32A32_SNORM
+ };
+ static GLuint int_types_scale[4] = {
+    PIPE_FORMAT_R32_SSCALED,
+    PIPE_FORMAT_R32G32_SSCALED,
+    PIPE_FORMAT_R32G32B32_SSCALED,
+    PIPE_FORMAT_R32G32B32A32_SSCALED
+ };
+ static GLuint ushort_types_norm[4] = {
+    PIPE_FORMAT_R16_UNORM,
+    PIPE_FORMAT_R16G16_UNORM,
+    PIPE_FORMAT_R16G16B16_UNORM,
+    PIPE_FORMAT_R16G16B16A16_UNORM
+ };
+ static GLuint ushort_types_scale[4] = {
+    PIPE_FORMAT_R16_USCALED,
+    PIPE_FORMAT_R16G16_USCALED,
+    PIPE_FORMAT_R16G16B16_USCALED,
+    PIPE_FORMAT_R16G16B16A16_USCALED
+ };
+ static GLuint short_types_norm[4] = {
+    PIPE_FORMAT_R16_SNORM,
+    PIPE_FORMAT_R16G16_SNORM,
+    PIPE_FORMAT_R16G16B16_SNORM,
+    PIPE_FORMAT_R16G16B16A16_SNORM
+ };
+ static GLuint short_types_scale[4] = {
+    PIPE_FORMAT_R16_SSCALED,
+    PIPE_FORMAT_R16G16_SSCALED,
+    PIPE_FORMAT_R16G16B16_SSCALED,
+    PIPE_FORMAT_R16G16B16A16_SSCALED
+ };
+ static GLuint ubyte_types_norm[4] = {
+    PIPE_FORMAT_R8_UNORM,
+    PIPE_FORMAT_R8G8_UNORM,
+    PIPE_FORMAT_R8G8B8_UNORM,
+    PIPE_FORMAT_R8G8B8A8_UNORM
+ };
+ static GLuint ubyte_types_scale[4] = {
+    PIPE_FORMAT_R8_USCALED,
+    PIPE_FORMAT_R8G8_USCALED,
+    PIPE_FORMAT_R8G8B8_USCALED,
+    PIPE_FORMAT_R8G8B8A8_USCALED
+ };
+ static GLuint byte_types_norm[4] = {
+    PIPE_FORMAT_R8_SNORM,
+    PIPE_FORMAT_R8G8_SNORM,
+    PIPE_FORMAT_R8G8B8_SNORM,
+    PIPE_FORMAT_R8G8B8A8_SNORM
+ };
+ static GLuint byte_types_scale[4] = {
+    PIPE_FORMAT_R8_SSCALED,
+    PIPE_FORMAT_R8G8_SSCALED,
+    PIPE_FORMAT_R8G8B8_SSCALED,
+    PIPE_FORMAT_R8G8B8A8_SSCALED
+ };
+ static GLuint fixed_types[4] = {
+    PIPE_FORMAT_R32_FIXED,
+    PIPE_FORMAT_R32G32_FIXED,
+    PIPE_FORMAT_R32G32B32_FIXED,
+    PIPE_FORMAT_R32G32B32A32_FIXED
+ };
+ /**
+  * Return a PIPE_FORMAT_x for the given GL datatype and size.
+  */
+ GLuint
+ st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized)
+ {
+    assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
+           type == GL_FIXED);
+    assert(size >= 1);
+    assert(size <= 4);
+    if (normalized) {
+       switch (type) {
+       case GL_DOUBLE: return double_types[size-1];
+       case GL_FLOAT: return float_types[size-1];
+       case GL_INT: return int_types_norm[size-1];
+       case GL_SHORT: return short_types_norm[size-1];
+       case GL_BYTE: return byte_types_norm[size-1];
+       case GL_UNSIGNED_INT: return uint_types_norm[size-1];
+       case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
+       case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
+       case GL_FIXED: return fixed_types[size-1];
+       default: assert(0); return 0;
+       }      
+    }
+    else {
+       switch (type) {
+       case GL_DOUBLE: return double_types[size-1];
+       case GL_FLOAT: return float_types[size-1];
+       case GL_INT: return int_types_scale[size-1];
+       case GL_SHORT: return short_types_scale[size-1];
+       case GL_BYTE: return byte_types_scale[size-1];
+       case GL_UNSIGNED_INT: return uint_types_scale[size-1];
+       case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
+       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
+       case GL_FIXED: return fixed_types[size-1];
+       default: assert(0); return 0;
+       }      
+    }
+    return 0; /* silence compiler warning */
+ }
+ /*
+  * If edge flags are needed, setup an bitvector of flags and call
+  * pipe->set_edgeflags().
+  * XXX memleak: need to free the returned pointer at some point
+  */
+ static void *
+ setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
+                 const struct gl_client_array *array)
+ {
+    struct pipe_context *pipe = ctx->st->pipe;
+    if ((primMode == GL_TRIANGLES ||
+         primMode == GL_QUADS ||
+         primMode == GL_POLYGON) &&
+        (ctx->Polygon.FrontMode != GL_FILL ||
+         ctx->Polygon.BackMode != GL_FILL)) {
+       /* need edge flags */
+       GLint i;
+       unsigned *vec;
+       struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
+       ubyte *map;
+       if (!stobj)
+          return NULL;
+       vec = (unsigned *) calloc(sizeof(unsigned), (count + 31) / 32);
+       if (!vec)
+          return NULL;
+       map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+       map = ADD_POINTERS(map, array->Ptr);
+       for (i = 0; i < count; i++) {
+          if (*((float *) map))
+             vec[i/32] |= 1 << (i % 32);
+          map += array->StrideB;
+       }
+       pipe_buffer_unmap(pipe->screen, stobj->buffer);
+       pipe->set_edgeflags(pipe, vec);
+       return vec;
+    }
+    else {
+       /* edge flags not needed */
+       pipe->set_edgeflags(pipe, NULL);
+       return NULL;
+    }
+ }
+ /**
+  * Examine the active arrays to determine if we have interleaved
+  * vertex arrays all living in one VBO, or all living in user space.
+  * \param userSpace  returns whether the arrays are in user space.
+  */
+ static GLboolean
+ is_interleaved_arrays(const struct st_vertex_program *vp,
+                       const struct gl_client_array **arrays,
+                       GLboolean *userSpace)
+ {
+    GLuint attr;
+    const struct gl_buffer_object *firstBufObj = NULL;
+    GLint firstStride = -1;
+    GLuint num_client_arrays = 0;
+    const GLubyte *client_addr = NULL;
+    for (attr = 0; attr < vp->num_inputs; attr++) {
+       const GLuint mesaAttr = vp->index_to_input[attr];
+       const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
+       const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
+       if (firstStride < 0) {
+          firstStride = stride;
+       }
+       else if (firstStride != stride) {
+          return GL_FALSE;
+       }
+          
+       if (!bufObj || !bufObj->Name) {
+          num_client_arrays++;
+          /* Try to detect if the client-space arrays are
+           * "close" to each other.
+           */
+          if (!client_addr) {
+             client_addr = arrays[mesaAttr]->Ptr;
+          }
+          else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
+             /* arrays start too far apart */
+             return GL_FALSE;
+          }
+       }
+       else if (!firstBufObj) {
+          firstBufObj = bufObj;
+       }
+       else if (bufObj != firstBufObj) {
+          return GL_FALSE;
+       }
+    }
+    *userSpace = (num_client_arrays == vp->num_inputs);
+    /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */
+    return GL_TRUE;
+ }
+ /**
+  * Compute the memory range occupied by the arrays.
+  */
+ static void
+ get_arrays_bounds(const struct st_vertex_program *vp,
+                        const struct gl_client_array **arrays,
+                        GLuint max_index,
+                        const GLubyte **low, const GLubyte **high)
+ {
+    const GLubyte *low_addr = NULL;
+    GLuint attr;
+    GLint stride;
+    for (attr = 0; attr < vp->num_inputs; attr++) {
+       const GLuint mesaAttr = vp->index_to_input[attr];
+       const GLubyte *start = arrays[mesaAttr]->Ptr;
+       stride = arrays[mesaAttr]->StrideB;
+       if (attr == 0) {
+          low_addr = start;
+       }
+       else {
+          low_addr = MIN2(low_addr, start);
+       }
+    }
+    *low = low_addr;
+    *high = low_addr + (max_index + 1) * stride;
+ }
+ /**
+  * Set up for drawing interleaved arrays that all live in one VBO
+  * or all live in user space.
+  * \param vbuffer  returns vertex buffer info
+  * \param velements  returns vertex element info
+  */
+ static void
+ setup_interleaved_attribs(GLcontext *ctx,
+                           const struct st_vertex_program *vp,
+                           const struct gl_client_array **arrays,
+                           GLuint max_index,
+                           GLboolean userSpace,
+                           struct pipe_vertex_buffer *vbuffer,
+                           struct pipe_vertex_element velements[])
+ {
+    struct pipe_context *pipe = ctx->st->pipe;
+    GLuint attr;
+    const GLubyte *offset0;
+    for (attr = 0; attr < vp->num_inputs; attr++) {
+       const GLuint mesaAttr = vp->index_to_input[attr];
+       struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+       struct st_buffer_object *stobj = st_buffer_object(bufobj);
+       GLsizei stride = arrays[mesaAttr]->StrideB;
+       /*printf("stobj %u = %p\n", attr, (void*)stobj);*/
+       if (attr == 0) {
+          const GLubyte *low, *high;
+          get_arrays_bounds(vp, arrays, max_index, &low, &high);
+          /*printf("buffer range: %p %p  %d\n", low, high, high-low);*/
+          offset0 = low;
+          if (userSpace) {
+             vbuffer->buffer =
+                pipe_user_buffer_create(pipe->screen, (void *) low, high - low);
+             vbuffer->buffer_offset = 0;
+          }
+          else {
+             vbuffer->buffer = NULL;
+             pipe_buffer_reference(pipe->screen, &vbuffer->buffer, stobj->buffer);
+             vbuffer->buffer_offset = (unsigned) low;
+          }
+          vbuffer->stride = stride; /* in bytes */
+          vbuffer->max_index = max_index;
+       }
+       velements[attr].src_offset =
+          (unsigned) (arrays[mesaAttr]->Ptr - offset0);
+       velements[attr].vertex_buffer_index = 0;
+       velements[attr].nr_components = arrays[mesaAttr]->Size;
+       velements[attr].src_format =
+          st_pipe_vertex_format(arrays[mesaAttr]->Type,
+                                arrays[mesaAttr]->Size,
+                                arrays[mesaAttr]->Normalized);
+       assert(velements[attr].src_format);
+    }
+ }
+ /**
+  * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
+  * vertex attribute.
+  * \param vbuffer  returns vertex buffer info
+  * \param velements  returns vertex element info
+  */
+ static void
+ setup_non_interleaved_attribs(GLcontext *ctx,
+                               const struct st_vertex_program *vp,
+                               const struct gl_client_array **arrays,
+                               GLuint max_index,
+                               GLboolean *userSpace,
+                               struct pipe_vertex_buffer vbuffer[],
+                               struct pipe_vertex_element velements[])
+ {
+    struct pipe_context *pipe = ctx->st->pipe;
+    GLuint attr;
+    for (attr = 0; attr < vp->num_inputs; attr++) {
+       const GLuint mesaAttr = vp->index_to_input[attr];
+       struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
+       GLsizei stride = arrays[mesaAttr]->StrideB;
+       *userSpace = GL_FALSE;
+       if (bufobj && bufobj->Name) {
+          /* Attribute data is in a VBO.
+           * Recall that for VBOs, the gl_client_array->Ptr field is
+           * really an offset from the start of the VBO, not a pointer.
+           */
+          struct st_buffer_object *stobj = st_buffer_object(bufobj);
+          assert(stobj->buffer);
+          /*printf("stobj %u = %p\n", attr, (void*) stobj);*/
+          vbuffer[attr].buffer = NULL;
+          pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, stobj->buffer);
+          vbuffer[attr].buffer_offset = (unsigned) arrays[mesaAttr]->Ptr;
+          velements[attr].src_offset = 0;
+       }
+       else {
+          /* attribute data is in user-space memory, not a VBO */
+          uint bytes;
+          /*printf("user-space array %d stride %d\n", attr, stride);*/
+       
+          *userSpace = GL_TRUE;
+          /* wrap user data */
+          if (arrays[mesaAttr]->Ptr) {
+             /* user's vertex array */
+             if (arrays[mesaAttr]->StrideB) {
+                bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
+             }
+             else {
+                bytes = arrays[mesaAttr]->Size
+                   * _mesa_sizeof_type(arrays[mesaAttr]->Type);
+             }
+             vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
+                            (void *) arrays[mesaAttr]->Ptr, bytes);
+          }
+          else {
+             /* no array, use ctx->Current.Attrib[] value */
+             bytes = sizeof(ctx->Current.Attrib[0]);
+             vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
+                            (void *) ctx->Current.Attrib[mesaAttr], bytes);
+             stride = 0;
+          }
+          vbuffer[attr].buffer_offset = 0;
+          velements[attr].src_offset = 0;
+       }
+       assert(velements[attr].src_offset <= 2048); /* 11-bit field */
+       /* common-case setup */
+       vbuffer[attr].stride = stride; /* in bytes */
+       vbuffer[attr].max_index = max_index;
+       velements[attr].vertex_buffer_index = attr;
+       velements[attr].nr_components = arrays[mesaAttr]->Size;
+       velements[attr].src_format
+          = st_pipe_vertex_format(arrays[mesaAttr]->Type,
+                                  arrays[mesaAttr]->Size,
+                                  arrays[mesaAttr]->Normalized);
+       assert(velements[attr].src_format);
+    }
+ }
+ /**
+  * Prior to drawing, check that any uniforms referenced by the
+  * current shader have been set.  If a uniform has not been set,
+  * issue a warning.
+  */
+ static void
+ check_uniforms(GLcontext *ctx)
+ {
+    const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+    if (shProg && shProg->LinkStatus) {
+       GLuint i;
+       for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
+          const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
+          if (!u->Initialized) {
+             _mesa_warning(ctx,
+                           "Using shader with uninitialized uniform: %s",
+                           u->Name);
+          }
+       }
+    }
+ }
+ /**
+  * This function gets plugged into the VBO module and is called when
+  * we have something to render.
+  * Basically, translate the information into the format expected by gallium.
+  */
+ void
+ st_draw_vbo(GLcontext *ctx,
+             const struct gl_client_array **arrays,
+             const struct _mesa_prim *prims,
+             GLuint nr_prims,
+             const struct _mesa_index_buffer *ib,
+             GLuint min_index,
+             GLuint max_index)
+ {
+    struct pipe_context *pipe = ctx->st->pipe;
+    const struct st_vertex_program *vp;
+    const struct pipe_shader_state *vs;
+    struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
+    GLuint attr;
+    struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
+    unsigned num_vbuffers, num_velements;
+    GLboolean userSpace;
+    /* sanity check for pointer arithmetic below */
+    assert(sizeof(arrays[0]->Ptr[0]) == 1);
+    st_validate_state(ctx->st);
+    /* must get these after state validation! */
+    vp = ctx->st->vp;
+    vs = &ctx->st->vp->state;
++#if 0
+    if (MESA_VERBOSE & VERBOSE_GLSL) {
+       check_uniforms(ctx);
+    }
++#endif
+    /*
+     * Setup the vbuffer[] and velements[] arrays.
+     */
+    if (is_interleaved_arrays(vp, arrays, &userSpace)) {
+       /*printf("Draw interleaved\n");*/
+       setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
+                                 vbuffer, velements);
+       num_vbuffers = 1;
+       num_velements = vp->num_inputs;
+       if (num_velements == 0)
+          num_vbuffers = 0;
+    }
+    else {
+       /*printf("Draw non-interleaved\n");*/
+       setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
+                                     &userSpace, vbuffer, velements);
+       num_vbuffers = vp->num_inputs;
+       num_velements = vp->num_inputs;
+    }
+ #if 0
+    {
+       GLuint i;
+       for (i = 0; i < num_vbuffers; i++) {
+          printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride);
+          printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
+          printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
+          printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
+       }
+       for (i = 0; i < num_velements; i++) {
+          printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
+          printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
+          printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components);
+          printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format));
+       }
+    }
+ #endif
+    pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
+    pipe->set_vertex_elements(pipe, num_velements, velements);
+    if (num_vbuffers == 0 || num_velements == 0)
+       return;
+    /* do actual drawing */
+    if (ib) {
+       /* indexed primitive */
+       struct gl_buffer_object *bufobj = ib->obj;
+       struct pipe_buffer *indexBuf = NULL;
+       unsigned indexSize, indexOffset, i;
+       switch (ib->type) {
+       case GL_UNSIGNED_INT:
+          indexSize = 4;
+          break;
+       case GL_UNSIGNED_SHORT:
+          indexSize = 2;
+          break;
+       case GL_UNSIGNED_BYTE:
+          indexSize = 1;
+          break;
+       default:
+          assert(0);
+        return;
+       }
+       /* get/create the index buffer object */
+       if (bufobj && bufobj->Name) {
+          /* elements/indexes are in a real VBO */
+          struct st_buffer_object *stobj = st_buffer_object(bufobj);
+          pipe_buffer_reference(pipe->screen, &indexBuf, stobj->buffer);
+          indexOffset = (unsigned) ib->ptr / indexSize;
+       }
+       else {
+          /* element/indicies are in user space memory */
+          indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
+                                             ib->count * indexSize);
+          indexOffset = 0;
+       }
+       /* draw */
+       if (nr_prims == 1 && pipe->draw_range_elements != NULL) {
+          i = 0;
+          /* XXX: exercise temporary path to pass min/max directly
+           * through to driver & draw module.  These interfaces still
+           * need a bit of work...
+           */
+          setup_edgeflags(ctx, prims[i].mode,
+                          prims[i].start + indexOffset, prims[i].count,
+                          arrays[VERT_ATTRIB_EDGEFLAG]);
+          pipe->draw_range_elements(pipe, indexBuf, indexSize,
+                                    min_index,
+                                    max_index,
+                                    prims[i].mode,
+                                    prims[i].start + indexOffset, prims[i].count);
+       }
+       else {
+          for (i = 0; i < nr_prims; i++) {
+             setup_edgeflags(ctx, prims[i].mode,
+                             prims[i].start + indexOffset, prims[i].count,
+                             arrays[VERT_ATTRIB_EDGEFLAG]);
+             
+             pipe->draw_elements(pipe, indexBuf, indexSize,
+                                 prims[i].mode,
+                                 prims[i].start + indexOffset, prims[i].count);
+          }
+       }
+       pipe_buffer_reference(pipe->screen, &indexBuf, NULL);
+    }
+    else {
+       /* non-indexed */
+       GLuint i;
+       for (i = 0; i < nr_prims; i++) {
+          setup_edgeflags(ctx, prims[i].mode,
+                          prims[i].start, prims[i].count,
+                          arrays[VERT_ATTRIB_EDGEFLAG]);
+          pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
+       }
+    }
+    /* unreference buffers (frees wrapped user-space buffer objects) */
+    for (attr = 0; attr < num_vbuffers; attr++) {
+       pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, NULL);
+       assert(!vbuffer[attr].buffer);
+    }
+    if (userSpace) 
+    {
+       pipe->set_vertex_buffers(pipe, 0, NULL);
+    }
+ }
+ void st_init_draw( struct st_context *st )
+ {
+    GLcontext *ctx = st->ctx;
+    vbo_set_draw_func(ctx, st_draw_vbo);
+ }
+ void st_destroy_draw( struct st_context *st )
+ {
+ }
Simple merge
Simple merge
index f6daa253fddb339d0b13d5fe31e7dbfbc59de273,a6ce26ffed860573edb729a6c17216ca1fb335ae..2743bf6b55cfe5cf524bc6c2adec12f2a86d5ba5
@@@ -146,29 -146,34 +146,33 @@@ static void vbo_exec_copy_to_current( s
           /* Note: the exec->vtx.current[i] pointers point into the
            * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
            */
-          if (exec->vtx.attrptr[i]) {
-        COPY_CLEAN_4V(current, 
-                      exec->vtx.attrsz[i], 
-                      exec->vtx.attrptr[i]);
-        }
-        /* Given that we explicitly state size here, there is no need
-         * for the COPY_CLEAN above, could just copy 16 bytes and be
-         * done.  The only problem is when Mesa accesses ctx->Current
-         * directly.
-         */
-        vbo->currval[i].Size = exec->vtx.attrsz[i];
-        /* This triggers rather too much recalculation of Mesa state
-         * that doesn't get used (eg light positions).
-         */
-        if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
-            i <= VBO_ATTRIB_MAT_BACK_INDEXES)
-           ctx->NewState |= _NEW_LIGHT;
+        GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+          GLfloat tmp[4];
+          COPY_CLEAN_4V(tmp, 
+                        exec->vtx.attrsz[i], 
+                        exec->vtx.attrptr[i]);
+          
+          if (memcmp(current, tmp, sizeof(tmp)) != 0)
+          { 
+             memcpy(current, tmp, sizeof(tmp));
 -
+        
+             /* Given that we explicitly state size here, there is no need
+              * for the COPY_CLEAN above, could just copy 16 bytes and be
+              * done.  The only problem is when Mesa accesses ctx->Current
+              * directly.
+              */
+             vbo->currval[i].Size = exec->vtx.attrsz[i];
+             /* This triggers rather too much recalculation of Mesa state
+              * that doesn't get used (eg light positions).
+              */
+             if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+                 i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+                ctx->NewState |= _NEW_LIGHT;
+             
+             ctx->NewState |= _NEW_CURRENT_ATTRIB;
+          }
        }
     }
  
Simple merge
index 7ee0a9a33f40f70d89b75d629073745bb2434b58,0488c5d718295dac46ea38d6f4e07c90e2c2d33a..617c5a77baf28b3e09d08d40b7f13f5ab233e7e0
@@@ -110,10 -118,8 +118,11 @@@ static void vbo_bind_vertex_list( GLcon
     GLuint data = node->buffer_offset;
     const GLuint *map;
     GLuint attr;
 +   GLubyte node_attrsz[VBO_ATTRIB_MAX];  /* copy of node->attrsz[] */
+    GLbitfield varying_inputs = 0x0;
  
 +   memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
 +
     /* Install the default (ie Current) attributes first, then overlay
      * all active ones.
      */