diff options
Diffstat (limited to 'mesalib/src/mesa/vbo')
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_exec_api.c | 2250 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_save.h | 404 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_save_api.c | 845 | ||||
-rw-r--r-- | mesalib/src/mesa/vbo/vbo_save_draw.c | 618 |
4 files changed, 2108 insertions, 2009 deletions
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 6b919e8b4..2b8d38ef2 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -1,1123 +1,1127 @@ -/**************************************************************************
-
-Copyright 2002-2008 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
-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
-TUNGSTEN GRAPHICS AND/OR THEIR 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/glheader.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/macros.h"
-#include "main/mfeatures.h"
-#include "main/vtxfmt.h"
-#include "main/dlist.h"
-#include "main/eval.h"
-#include "main/state.h"
-#include "main/light.h"
-#include "main/api_arrayelt.h"
-#include "main/api_noop.h"
-#include "main/dispatch.h"
-
-#include "vbo_context.h"
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-
-/** ID/name for immediate-mode VBO */
-#define IMM_BUFFER_NAME 0xaabbccdd
-
-
-static void reset_attrfv( struct vbo_exec_context *exec );
-
-
-/**
- * Close off the last primitive, execute the buffer, restart the
- * primitive.
- */
-static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
-{
- if (exec->vtx.prim_count == 0) {
- exec->vtx.copied.nr = 0;
- exec->vtx.vert_count = 0;
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
- }
- else {
- GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
- GLuint last_count;
-
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- GLint i = exec->vtx.prim_count - 1;
- assert(i >= 0);
- exec->vtx.prim[i].count = (exec->vtx.vert_count -
- exec->vtx.prim[i].start);
- }
-
- last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
-
- /* Execute the buffer and save copied vertices.
- */
- if (exec->vtx.vert_count)
- vbo_exec_vtx_flush( exec, GL_FALSE );
- else {
- exec->vtx.prim_count = 0;
- exec->vtx.copied.nr = 0;
- }
-
- /* Emit a glBegin to start the new list.
- */
- assert(exec->vtx.prim_count == 0);
-
- if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
- exec->vtx.prim[0].start = 0;
- exec->vtx.prim[0].count = 0;
- exec->vtx.prim_count++;
-
- if (exec->vtx.copied.nr == last_count)
- exec->vtx.prim[0].begin = last_begin;
- }
- }
-}
-
-
-/**
- * Deal with buffer wrapping where provoked by the vertex buffer
- * filling up, as opposed to upgrade_vertex().
- */
-void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
-{
- GLfloat *data = exec->vtx.copied.buffer;
- GLuint i;
-
- /* Run pipeline on current vertices, copy wrapped vertices
- * to exec->vtx.copied.
- */
- vbo_exec_wrap_buffers( exec );
-
- /* Copy stored stored vertices to start of new list.
- */
- assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
-
- for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
- memcpy( exec->vtx.buffer_ptr, data,
- exec->vtx.vertex_size * sizeof(GLfloat));
- exec->vtx.buffer_ptr += exec->vtx.vertex_size;
- data += exec->vtx.vertex_size;
- exec->vtx.vert_count++;
- }
-
- exec->vtx.copied.nr = 0;
-}
-
-
-/**
- * Copy the active vertex's values to the ctx->Current fields.
- */
-static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
-{
- struct gl_context *ctx = exec->ctx;
- struct vbo_context *vbo = vbo_context(ctx);
- GLuint i;
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
- if (exec->vtx.attrsz[i]) {
- /* Note: the exec->vtx.current[i] pointers point into the
- * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
- */
- 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];
- assert(vbo->currval[i].Type == GL_FLOAT);
- vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
-
- /* 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;
- }
- }
- }
-
- /* Colormaterial -- this kindof sucks.
- */
- if (ctx->Light.ColorMaterialEnabled &&
- exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
- _mesa_update_color_material(ctx,
- ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
- }
-}
-
-
-/**
- * Copy current vertex attribute values into the current vertex.
- */
-static void
-vbo_exec_copy_from_current(struct vbo_exec_context *exec)
-{
- struct gl_context *ctx = exec->ctx;
- struct vbo_context *vbo = vbo_context(ctx);
- GLint i;
-
- for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
- const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr;
- switch (exec->vtx.attrsz[i]) {
- case 4: exec->vtx.attrptr[i][3] = current[3];
- case 3: exec->vtx.attrptr[i][2] = current[2];
- case 2: exec->vtx.attrptr[i][1] = current[1];
- case 1: exec->vtx.attrptr[i][0] = current[0];
- break;
- }
- }
-}
-
-
-/**
- * Flush existing data, set new attrib size, replay copied vertices.
- * This is called when we transition from a small vertex attribute size
- * to a larger one. Ex: glTexCoord2f -> glTexCoord4f.
- * We need to go back over the previous 2-component texcoords and insert
- * zero and one values.
- */
-static void
-vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
- GLuint attr, GLuint newSize )
-{
- struct gl_context *ctx = exec->ctx;
- struct vbo_context *vbo = vbo_context(ctx);
- const GLint lastcount = exec->vtx.vert_count;
- GLfloat *old_attrptr[VBO_ATTRIB_MAX];
- const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
- const GLuint oldSize = exec->vtx.attrsz[attr];
- GLuint i;
-
- /* Run pipeline on current vertices, copy wrapped vertices
- * to exec->vtx.copied.
- */
- vbo_exec_wrap_buffers( exec );
-
- if (unlikely(exec->vtx.copied.nr)) {
- /* We're in the middle of a primitive, keep the old vertex
- * format around to be able to translate the copied vertices to
- * the new format.
- */
- memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
- }
-
- if (unlikely(oldSize)) {
- /* Do a COPY_TO_CURRENT to ensure back-copying works for the
- * case when the attribute already exists in the vertex and is
- * having its size increased.
- */
- vbo_exec_copy_to_current( exec );
- }
-
- /* Heuristic: Attempt to isolate attributes received outside
- * begin/end so that they don't bloat the vertices.
- */
- if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
- !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
- vbo_exec_copy_to_current( exec );
- reset_attrfv( exec );
- }
-
- /* Fix up sizes:
- */
- exec->vtx.attrsz[attr] = newSize;
- exec->vtx.vertex_size += newSize - oldSize;
- exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
- (exec->vtx.vertex_size * sizeof(GLfloat)));
- exec->vtx.vert_count = 0;
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
-
- if (unlikely(oldSize)) {
- /* Size changed, recalculate all the attrptr[] values
- */
- GLfloat *tmp = exec->vtx.vertex;
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- if (exec->vtx.attrsz[i]) {
- exec->vtx.attrptr[i] = tmp;
- tmp += exec->vtx.attrsz[i];
- }
- else
- exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
- }
-
- /* Copy from current to repopulate the vertex with correct
- * values.
- */
- vbo_exec_copy_from_current( exec );
- }
- else {
- /* Just have to append the new attribute at the end */
- exec->vtx.attrptr[attr] = exec->vtx.vertex +
- exec->vtx.vertex_size - newSize;
- }
-
- /* Replay stored vertices to translate them
- * to new format here.
- *
- * -- No need to replay - just copy piecewise
- */
- if (unlikely(exec->vtx.copied.nr)) {
- GLfloat *data = exec->vtx.copied.buffer;
- GLfloat *dest = exec->vtx.buffer_ptr;
- GLuint j;
-
- assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
-
- for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
- for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
- GLuint sz = exec->vtx.attrsz[j];
-
- if (sz) {
- GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
- GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
-
- if (j == attr) {
- if (oldSize) {
- GLfloat tmp[4];
- COPY_CLEAN_4V(tmp, oldSize, data + old_offset);
- COPY_SZ_4V(dest + new_offset, newSize, tmp);
- } else {
- GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
- COPY_SZ_4V(dest + new_offset, sz, current);
- }
- }
- else {
- COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
- }
- }
- }
-
- data += old_vtx_size;
- dest += exec->vtx.vertex_size;
- }
-
- exec->vtx.buffer_ptr = dest;
- exec->vtx.vert_count += exec->vtx.copied.nr;
- exec->vtx.copied.nr = 0;
- }
-}
-
-
-/**
- * This is when a vertex attribute transitions to a different size.
- * For example, we saw a bunch of glTexCoord2f() calls and now we got a
- * glTexCoord4f() call. We promote the array from size=2 to size=4.
- */
-static void
-vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize)
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- if (newSize > exec->vtx.attrsz[attr]) {
- /* New size is larger. Need to flush existing vertices and get
- * an enlarged vertex format.
- */
- vbo_exec_wrap_upgrade_vertex( exec, attr, newSize );
- }
- else if (newSize < exec->vtx.active_sz[attr]) {
- static const GLfloat id[4] = { 0, 0, 0, 1 };
- GLuint i;
-
- /* New size is smaller - just need to fill in some
- * zeros. Don't need to flush or wrap.
- */
- for (i = newSize; i <= exec->vtx.attrsz[attr]; i++)
- exec->vtx.attrptr[attr][i-1] = id[i-1];
- }
-
- exec->vtx.active_sz[attr] = newSize;
-
- /* Does setting NeedFlush belong here? Necessitates resetting
- * vtxfmt on each flush (otherwise flags won't get reset
- * afterwards).
- */
- if (attr == 0)
- ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
-}
-
-
-/**
- * This macro is used to implement all the glVertex, glColor, glTexCoord,
- * glVertexAttrib, etc functions.
- */
-#define ATTR( A, N, V0, V1, V2, V3 ) \
-do { \
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
- \
- if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
- ctx->Driver.BeginVertices( ctx ); \
- \
- if (unlikely(exec->vtx.active_sz[A] != N)) \
- vbo_exec_fixup_vertex(ctx, A, N); \
- \
- { \
- GLfloat *dest = exec->vtx.attrptr[A]; \
- if (N>0) dest[0] = V0; \
- if (N>1) dest[1] = V1; \
- if (N>2) dest[2] = V2; \
- if (N>3) dest[3] = V3; \
- } \
- \
- if ((A) == 0) { \
- /* This is a glVertex call */ \
- GLuint i; \
- \
- for (i = 0; i < exec->vtx.vertex_size; i++) \
- exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
- \
- exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
- \
- /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \
- /* something to draw (not just updating a color or texcoord).*/ \
- ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
- \
- if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
- vbo_exec_vtx_wrap( exec ); \
- } \
-} while (0)
-
-
-#define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ )
-#define TAG(x) vbo_##x
-
-#include "vbo_attrib_tmp.h"
-
-
-#if FEATURE_beginend
-
-
-#if FEATURE_evaluators
-
-static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
-{
- GET_CURRENT_CONTEXT( ctx );
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- {
- GLint i;
- if (exec->eval.recalculate_maps)
- vbo_exec_eval_update( exec );
-
- for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
- if (exec->eval.map1[i].map)
- if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
- }
- }
-
-
- memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
- exec->vtx.vertex_size * sizeof(GLfloat));
-
- vbo_exec_do_EvalCoord1f( exec, u );
-
- memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
- exec->vtx.vertex_size * sizeof(GLfloat));
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
-{
- GET_CURRENT_CONTEXT( ctx );
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- {
- GLint i;
- if (exec->eval.recalculate_maps)
- vbo_exec_eval_update( exec );
-
- for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
- if (exec->eval.map2[i].map)
- if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
- vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
- }
-
- if (ctx->Eval.AutoNormal)
- if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
- vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
- }
-
- memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
- exec->vtx.vertex_size * sizeof(GLfloat));
-
- vbo_exec_do_EvalCoord2f( exec, u, v );
-
- memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
- exec->vtx.vertex_size * sizeof(GLfloat));
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
-{
- vbo_exec_EvalCoord1f( u[0] );
-}
-
-static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
-{
- vbo_exec_EvalCoord2f( u[0], u[1] );
-}
-
-static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
- (GLfloat) ctx->Eval.MapGrid1un);
- GLfloat u = i * du + ctx->Eval.MapGrid1u1;
-
- vbo_exec_EvalCoord1f( u );
-}
-
-
-static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
-{
- GET_CURRENT_CONTEXT( ctx );
- GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
- (GLfloat) ctx->Eval.MapGrid2un);
- GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
- (GLfloat) ctx->Eval.MapGrid2vn);
- GLfloat u = i * du + ctx->Eval.MapGrid2u1;
- GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
-
- vbo_exec_EvalCoord2f( u, v );
-}
-
-/* use noop eval mesh */
-#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
-#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
-
-#endif /* FEATURE_evaluators */
-
-
-/**
- * Flush (draw) vertices.
- * \param unmap - leave VBO unmapped after flushing?
- */
-static void
-vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap)
-{
- if (exec->vtx.vert_count || unmap) {
- vbo_exec_vtx_flush( exec, unmap );
- }
-
- if (exec->vtx.vertex_size) {
- vbo_exec_copy_to_current( exec );
- reset_attrfv( exec );
- }
-}
-
-
-/**
- * Called via glBegin.
- */
-static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
-{
- GET_CURRENT_CONTEXT( ctx );
-
- if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- int i;
-
- if (ctx->NewState) {
- _mesa_update_state( ctx );
-
- CALL_Begin(ctx->Exec, (mode));
- return;
- }
-
- if (!_mesa_valid_to_render(ctx, "glBegin")) {
- return;
- }
-
- /* Heuristic: attempt to isolate attributes occuring outside
- * begin/end pairs.
- */
- if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
- vbo_exec_FlushVertices_internal(exec, GL_FALSE);
-
- i = exec->vtx.prim_count++;
- exec->vtx.prim[i].mode = mode;
- exec->vtx.prim[i].begin = 1;
- exec->vtx.prim[i].end = 0;
- exec->vtx.prim[i].indexed = 0;
- exec->vtx.prim[i].weak = 0;
- exec->vtx.prim[i].pad = 0;
- exec->vtx.prim[i].start = exec->vtx.vert_count;
- exec->vtx.prim[i].count = 0;
- exec->vtx.prim[i].num_instances = 1;
-
- ctx->Driver.CurrentExecPrimitive = mode;
- }
- else
- _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
-
-}
-
-
-/**
- * Called via glEnd.
- */
-static void GLAPIENTRY vbo_exec_End( void )
-{
- GET_CURRENT_CONTEXT( ctx );
-
- if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- int idx = exec->vtx.vert_count;
- int i = exec->vtx.prim_count - 1;
-
- exec->vtx.prim[i].end = 1;
- exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
-
- ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
-
- if (exec->vtx.prim_count == VBO_MAX_PRIM)
- vbo_exec_vtx_flush( exec, GL_FALSE );
- }
- else
- _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
-}
-
-
-/**
- * Called via glPrimitiveRestartNV()
- */
-static void GLAPIENTRY
-vbo_exec_PrimitiveRestartNV(void)
-{
- GLenum curPrim;
- GET_CURRENT_CONTEXT( ctx );
-
- curPrim = ctx->Driver.CurrentExecPrimitive;
-
- if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
- _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
- }
- else {
- vbo_exec_End();
- vbo_exec_Begin(curPrim);
- }
-}
-
-
-
-static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
-{
- GLvertexformat *vfmt = &exec->vtxfmt;
-
- _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
-
- vfmt->Begin = vbo_exec_Begin;
- vfmt->End = vbo_exec_End;
- vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
-
- _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
- _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
-
- vfmt->Rectf = _mesa_noop_Rectf;
-
- /* from attrib_tmp.h:
- */
- vfmt->Color3f = vbo_Color3f;
- vfmt->Color3fv = vbo_Color3fv;
- vfmt->Color4f = vbo_Color4f;
- vfmt->Color4fv = vbo_Color4fv;
- vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
- vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
- vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
- vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
- vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
- vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
- vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
- vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
- vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
- vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
- vfmt->Normal3f = vbo_Normal3f;
- vfmt->Normal3fv = vbo_Normal3fv;
- vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
- vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
- vfmt->TexCoord1f = vbo_TexCoord1f;
- vfmt->TexCoord1fv = vbo_TexCoord1fv;
- vfmt->TexCoord2f = vbo_TexCoord2f;
- vfmt->TexCoord2fv = vbo_TexCoord2fv;
- vfmt->TexCoord3f = vbo_TexCoord3f;
- vfmt->TexCoord3fv = vbo_TexCoord3fv;
- vfmt->TexCoord4f = vbo_TexCoord4f;
- vfmt->TexCoord4fv = vbo_TexCoord4fv;
- vfmt->Vertex2f = vbo_Vertex2f;
- vfmt->Vertex2fv = vbo_Vertex2fv;
- vfmt->Vertex3f = vbo_Vertex3f;
- vfmt->Vertex3fv = vbo_Vertex3fv;
- vfmt->Vertex4f = vbo_Vertex4f;
- vfmt->Vertex4fv = vbo_Vertex4fv;
-
- vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
- vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
- vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
- vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
- vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
- vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
- vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
- vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
-
- vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
- vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
- vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
- vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
- vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
- vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
- vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
- vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
-
- /* integer-valued */
- vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
- vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
- vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
- vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
- vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
- vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
- vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
-
- /* unsigned integer-valued */
- vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
- vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
- vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
- vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
- vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
- vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
- vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
-
- vfmt->Materialfv = vbo_Materialfv;
-
- vfmt->EdgeFlag = vbo_EdgeFlag;
- vfmt->Indexf = vbo_Indexf;
- vfmt->Indexfv = vbo_Indexfv;
-
-}
-
-
-#else /* FEATURE_beginend */
-
-
-static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
-{
- /* silence warnings */
- (void) vbo_Color3f;
- (void) vbo_Color3fv;
- (void) vbo_Color4f;
- (void) vbo_Color4fv;
- (void) vbo_FogCoordfEXT;
- (void) vbo_FogCoordfvEXT;
- (void) vbo_MultiTexCoord1f;
- (void) vbo_MultiTexCoord1fv;
- (void) vbo_MultiTexCoord2f;
- (void) vbo_MultiTexCoord2fv;
- (void) vbo_MultiTexCoord3f;
- (void) vbo_MultiTexCoord3fv;
- (void) vbo_MultiTexCoord4f;
- (void) vbo_MultiTexCoord4fv;
- (void) vbo_Normal3f;
- (void) vbo_Normal3fv;
- (void) vbo_SecondaryColor3fEXT;
- (void) vbo_SecondaryColor3fvEXT;
- (void) vbo_TexCoord1f;
- (void) vbo_TexCoord1fv;
- (void) vbo_TexCoord2f;
- (void) vbo_TexCoord2fv;
- (void) vbo_TexCoord3f;
- (void) vbo_TexCoord3fv;
- (void) vbo_TexCoord4f;
- (void) vbo_TexCoord4fv;
- (void) vbo_Vertex2f;
- (void) vbo_Vertex2fv;
- (void) vbo_Vertex3f;
- (void) vbo_Vertex3fv;
- (void) vbo_Vertex4f;
- (void) vbo_Vertex4fv;
-
- (void) vbo_VertexAttrib1fARB;
- (void) vbo_VertexAttrib1fvARB;
- (void) vbo_VertexAttrib2fARB;
- (void) vbo_VertexAttrib2fvARB;
- (void) vbo_VertexAttrib3fARB;
- (void) vbo_VertexAttrib3fvARB;
- (void) vbo_VertexAttrib4fARB;
- (void) vbo_VertexAttrib4fvARB;
-
- (void) vbo_VertexAttrib1fNV;
- (void) vbo_VertexAttrib1fvNV;
- (void) vbo_VertexAttrib2fNV;
- (void) vbo_VertexAttrib2fvNV;
- (void) vbo_VertexAttrib3fNV;
- (void) vbo_VertexAttrib3fvNV;
- (void) vbo_VertexAttrib4fNV;
- (void) vbo_VertexAttrib4fvNV;
-
- (void) vbo_Materialfv;
-
- (void) vbo_EdgeFlag;
- (void) vbo_Indexf;
- (void) vbo_Indexfv;
-}
-
-
-#endif /* FEATURE_beginend */
-
-
-/**
- * Tell the VBO module to use a real OpenGL vertex buffer object to
- * store accumulated immediate-mode vertex data.
- * This replaces the malloced buffer which was created in
- * vb_exec_vtx_init() below.
- */
-void vbo_use_buffer_objects(struct gl_context *ctx)
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- /* Any buffer name but 0 can be used here since this bufferobj won't
- * go into the bufferobj hashtable.
- */
- GLuint bufName = IMM_BUFFER_NAME;
- GLenum target = GL_ARRAY_BUFFER_ARB;
- GLenum usage = GL_STREAM_DRAW_ARB;
- GLsizei size = VBO_VERT_BUFFER_SIZE;
-
- /* Make sure this func is only used once */
- assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
- if (exec->vtx.buffer_map) {
- _mesa_align_free(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- }
-
- /* Allocate a real buffer object now */
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
- exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
- ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
-}
-
-
-/**
- * If this function is called, all VBO buffers will be unmapped when
- * we flush.
- * Otherwise, if a simple command like glColor3f() is called and we flush,
- * the current VBO may be left mapped.
- */
-void
-vbo_always_unmap_buffers(struct gl_context *ctx)
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- exec->begin_vertices_flags |= FLUSH_STORED_VERTICES;
-}
-
-
-void vbo_exec_vtx_init( struct vbo_exec_context *exec )
-{
- struct gl_context *ctx = exec->ctx;
- struct vbo_context *vbo = vbo_context(ctx);
- GLuint i;
-
- /* Allocate a buffer object. Will just reuse this object
- * continuously, unless vbo_use_buffer_objects() is called to enable
- * use of real VBOs.
- */
- _mesa_reference_buffer_object(ctx,
- &exec->vtx.bufferobj,
- ctx->Shared->NullBufferObj);
-
- ASSERT(!exec->vtx.buffer_map);
- exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
-
- vbo_exec_vtxfmt_init( exec );
-
- /* Hook our functions into the dispatch table.
- */
- _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- ASSERT(i < Elements(exec->vtx.attrsz));
- exec->vtx.attrsz[i] = 0;
- ASSERT(i < Elements(exec->vtx.active_sz));
- exec->vtx.active_sz[i] = 0;
- }
- for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
- ASSERT(i < Elements(exec->vtx.inputs));
- ASSERT(i < Elements(exec->vtx.arrays));
- exec->vtx.inputs[i] = &exec->vtx.arrays[i];
- }
-
- {
- struct gl_client_array *arrays = exec->vtx.arrays;
- unsigned i;
-
- memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
- memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
-
- for (i = 0; i < 16; ++i) {
- arrays[i ].BufferObj = NULL;
- arrays[i + 16].BufferObj = NULL;
- _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
- vbo->legacy_currval[i].BufferObj);
- _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
- vbo->generic_currval[i].BufferObj);
- }
- }
-
- exec->vtx.vertex_size = 0;
-
- exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT;
-}
-
-
-void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
-{
- /* using a real VBO for vertex data */
- struct gl_context *ctx = exec->ctx;
- unsigned i;
-
- /* True VBOs should already be unmapped
- */
- if (exec->vtx.buffer_map) {
- ASSERT(exec->vtx.bufferobj->Name == 0 ||
- exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
- if (exec->vtx.bufferobj->Name == 0) {
- _mesa_align_free(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
- }
- }
-
- /* Drop any outstanding reference to the vertex buffer
- */
- for (i = 0; i < Elements(exec->vtx.arrays); i++) {
- _mesa_reference_buffer_object(ctx,
- &exec->vtx.arrays[i].BufferObj,
- NULL);
- }
-
- /* Free the vertex buffer. Unmap first if needed.
- */
- if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
- }
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
-}
-
-
-/**
- * Called upon first glVertex, glColor, glTexCoord, etc.
- */
-void vbo_exec_BeginVertices( struct gl_context *ctx )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
- vbo_exec_vtx_map( exec );
-
- assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
- assert(exec->begin_vertices_flags);
-
- ctx->Driver.NeedFlush |= exec->begin_vertices_flags;
-}
-
-
-/**
- * Called via ctx->Driver.FlushVertices()
- * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
- */
-void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
-
-#ifdef DEBUG
- /* debug check: make sure we don't get called recursively */
- exec->flush_call_depth++;
- assert(exec->flush_call_depth == 1);
-#endif
-
- if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
- /* We've had glBegin but not glEnd! */
-#ifdef DEBUG
- exec->flush_call_depth--;
- assert(exec->flush_call_depth == 0);
-#endif
- return;
- }
-
- /* Flush (draw), and make sure VBO is left unmapped when done */
- vbo_exec_FlushVertices_internal(exec, GL_TRUE);
-
- /* Need to do this to ensure BeginVertices gets called again:
- */
- ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags);
-
-#ifdef DEBUG
- exec->flush_call_depth--;
- assert(exec->flush_call_depth == 0);
-#endif
-}
-
-
-static void reset_attrfv( struct vbo_exec_context *exec )
-{
- GLuint i;
-
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- exec->vtx.attrsz[i] = 0;
- exec->vtx.active_sz[i] = 0;
- }
-
- exec->vtx.vertex_size = 0;
-}
-
-
-void GLAPIENTRY
-_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
-{
- vbo_Color4f(r, g, b, a);
-}
-
-
-void GLAPIENTRY
-_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
-{
- vbo_Normal3f(x, y, z);
-}
-
-
-void GLAPIENTRY
-_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-{
- vbo_MultiTexCoord4f(target, s, t, r, q);
-}
-
-
-void GLAPIENTRY
-_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
-{
- vbo_Materialfv(face, pname, params);
-}
-
-
-void GLAPIENTRY
-_es_Materialf(GLenum face, GLenum pname, GLfloat param)
-{
- GLfloat p[4];
- p[0] = param;
- p[1] = p[2] = p[3] = 0.0F;
- vbo_Materialfv(face, pname, p);
-}
-
-
-/**
- * A special version of glVertexAttrib4f that does not treat index 0 as
- * VBO_ATTRIB_POS.
- */
-static void
-VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GET_CURRENT_CONTEXT(ctx);
- if (index < MAX_VERTEX_GENERIC_ATTRIBS)
- ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
- else
- ERROR(GL_INVALID_VALUE);
-}
-
-void GLAPIENTRY
-_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- VertexAttrib4f_nopos(index, x, y, z, w);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib1f(GLuint indx, GLfloat x)
-{
- VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
-{
- VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
-{
- VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
-{
- VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-{
- VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
-{
- VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
-}
-
-
-void GLAPIENTRY
-_es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
-{
- VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
-}
+/************************************************************************** + +Copyright 2002-2008 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 +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 +TUNGSTEN GRAPHICS AND/OR THEIR 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/glheader.h" +#include "main/bufferobj.h" +#include "main/context.h" +#include "main/macros.h" +#include "main/mfeatures.h" +#include "main/vtxfmt.h" +#include "main/dlist.h" +#include "main/eval.h" +#include "main/state.h" +#include "main/light.h" +#include "main/api_arrayelt.h" +#include "main/api_noop.h" +#include "main/dispatch.h" + +#include "vbo_context.h" + +#ifdef ERROR +#undef ERROR +#endif + + +/** ID/name for immediate-mode VBO */ +#define IMM_BUFFER_NAME 0xaabbccdd + + +static void reset_attrfv( struct vbo_exec_context *exec ); + + +/** + * Close off the last primitive, execute the buffer, restart the + * primitive. + */ +static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) +{ + if (exec->vtx.prim_count == 0) { + exec->vtx.copied.nr = 0; + exec->vtx.vert_count = 0; + exec->vtx.buffer_ptr = exec->vtx.buffer_map; + } + else { + GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; + GLuint last_count; + + if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + GLint i = exec->vtx.prim_count - 1; + assert(i >= 0); + exec->vtx.prim[i].count = (exec->vtx.vert_count - + exec->vtx.prim[i].start); + } + + last_count = exec->vtx.prim[exec->vtx.prim_count-1].count; + + /* Execute the buffer and save copied vertices. + */ + if (exec->vtx.vert_count) + vbo_exec_vtx_flush( exec, GL_FALSE ); + else { + exec->vtx.prim_count = 0; + exec->vtx.copied.nr = 0; + } + + /* Emit a glBegin to start the new list. + */ + assert(exec->vtx.prim_count == 0); + + if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; + exec->vtx.prim[0].start = 0; + exec->vtx.prim[0].count = 0; + exec->vtx.prim_count++; + + if (exec->vtx.copied.nr == last_count) + exec->vtx.prim[0].begin = last_begin; + } + } +} + + +/** + * Deal with buffer wrapping where provoked by the vertex buffer + * filling up, as opposed to upgrade_vertex(). + */ +void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) +{ + GLfloat *data = exec->vtx.copied.buffer; + GLuint i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to exec->vtx.copied. + */ + vbo_exec_wrap_buffers( exec ); + + /* Copy stored stored vertices to start of new list. + */ + assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); + + for (i = 0 ; i < exec->vtx.copied.nr ; i++) { + memcpy( exec->vtx.buffer_ptr, data, + exec->vtx.vertex_size * sizeof(GLfloat)); + exec->vtx.buffer_ptr += exec->vtx.vertex_size; + data += exec->vtx.vertex_size; + exec->vtx.vert_count++; + } + + exec->vtx.copied.nr = 0; +} + + +/** + * Copy the active vertex's values to the ctx->Current fields. + */ +static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) +{ + struct gl_context *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLuint i; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + if (exec->vtx.attrsz[i]) { + /* Note: the exec->vtx.current[i] pointers point into the + * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. + */ + 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]; + assert(vbo->currval[i].Type == GL_FLOAT); + vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat); + + /* 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; + } + } + } + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled && + exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) { + _mesa_update_color_material(ctx, + ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); + } +} + + +/** + * Copy current vertex attribute values into the current vertex. + */ +static void +vbo_exec_copy_from_current(struct vbo_exec_context *exec) +{ + struct gl_context *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLint i; + + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { + const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr; + switch (exec->vtx.attrsz[i]) { + case 4: exec->vtx.attrptr[i][3] = current[3]; + case 3: exec->vtx.attrptr[i][2] = current[2]; + case 2: exec->vtx.attrptr[i][1] = current[1]; + case 1: exec->vtx.attrptr[i][0] = current[0]; + break; + } + } +} + + +/** + * Flush existing data, set new attrib size, replay copied vertices. + * This is called when we transition from a small vertex attribute size + * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. + * We need to go back over the previous 2-component texcoords and insert + * zero and one values. + */ +static void +vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, + GLuint attr, GLuint newSize ) +{ + struct gl_context *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + const GLint lastcount = exec->vtx.vert_count; + GLfloat *old_attrptr[VBO_ATTRIB_MAX]; + const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ + const GLuint oldSize = exec->vtx.attrsz[attr]; + GLuint i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to exec->vtx.copied. + */ + vbo_exec_wrap_buffers( exec ); + + if (unlikely(exec->vtx.copied.nr)) { + /* We're in the middle of a primitive, keep the old vertex + * format around to be able to translate the copied vertices to + * the new format. + */ + memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); + } + + if (unlikely(oldSize)) { + /* Do a COPY_TO_CURRENT to ensure back-copying works for the + * case when the attribute already exists in the vertex and is + * having its size increased. + */ + vbo_exec_copy_to_current( exec ); + } + + /* Heuristic: Attempt to isolate attributes received outside + * begin/end so that they don't bloat the vertices. + */ + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && + !oldSize && lastcount > 8 && exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } + + /* Fix up sizes: + */ + exec->vtx.attrsz[attr] = newSize; + exec->vtx.vertex_size += newSize - oldSize; + exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / + (exec->vtx.vertex_size * sizeof(GLfloat))); + exec->vtx.vert_count = 0; + exec->vtx.buffer_ptr = exec->vtx.buffer_map; + + if (unlikely(oldSize)) { + /* Size changed, recalculate all the attrptr[] values + */ + GLfloat *tmp = exec->vtx.vertex; + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + if (exec->vtx.attrsz[i]) { + exec->vtx.attrptr[i] = tmp; + tmp += exec->vtx.attrsz[i]; + } + else + exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ + } + + /* Copy from current to repopulate the vertex with correct + * values. + */ + vbo_exec_copy_from_current( exec ); + } + else { + /* Just have to append the new attribute at the end */ + exec->vtx.attrptr[attr] = exec->vtx.vertex + + exec->vtx.vertex_size - newSize; + } + + /* Replay stored vertices to translate them + * to new format here. + * + * -- No need to replay - just copy piecewise + */ + if (unlikely(exec->vtx.copied.nr)) { + GLfloat *data = exec->vtx.copied.buffer; + GLfloat *dest = exec->vtx.buffer_ptr; + GLuint j; + + assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); + + for (i = 0 ; i < exec->vtx.copied.nr ; i++) { + for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { + GLuint sz = exec->vtx.attrsz[j]; + + if (sz) { + GLint old_offset = old_attrptr[j] - exec->vtx.vertex; + GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; + + if (j == attr) { + if (oldSize) { + GLfloat tmp[4]; + COPY_CLEAN_4V(tmp, oldSize, data + old_offset); + COPY_SZ_4V(dest + new_offset, newSize, tmp); + } else { + GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; + COPY_SZ_4V(dest + new_offset, sz, current); + } + } + else { + COPY_SZ_4V(dest + new_offset, sz, data + old_offset); + } + } + } + + data += old_vtx_size; + dest += exec->vtx.vertex_size; + } + + exec->vtx.buffer_ptr = dest; + exec->vtx.vert_count += exec->vtx.copied.nr; + exec->vtx.copied.nr = 0; + } +} + + +/** + * This is when a vertex attribute transitions to a different size. + * For example, we saw a bunch of glTexCoord2f() calls and now we got a + * glTexCoord4f() call. We promote the array from size=2 to size=4. + */ +static void +vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (newSize > exec->vtx.attrsz[attr]) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + vbo_exec_wrap_upgrade_vertex( exec, attr, newSize ); + } + else if (newSize < exec->vtx.active_sz[attr]) { + static const GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; + + /* New size is smaller - just need to fill in some + * zeros. Don't need to flush or wrap. + */ + for (i = newSize; i <= exec->vtx.attrsz[attr]; i++) + exec->vtx.attrptr[attr][i-1] = id[i-1]; + } + + exec->vtx.active_sz[attr] = newSize; + + /* Does setting NeedFlush belong here? Necessitates resetting + * vtxfmt on each flush (otherwise flags won't get reset + * afterwards). + */ + if (attr == 0) + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; +} + + +/** + * This macro is used to implement all the glVertex, glColor, glTexCoord, + * glVertexAttrib, etc functions. + */ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ + \ + if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ + ctx->Driver.BeginVertices( ctx ); \ + \ + if (unlikely(exec->vtx.active_sz[A] != N)) \ + vbo_exec_fixup_vertex(ctx, A, N); \ + \ + { \ + GLfloat *dest = exec->vtx.attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + /* This is a glVertex call */ \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ + \ + exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ + \ + /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ + /* something to draw (not just updating a color or texcoord).*/ \ + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ +} while (0) + + +#define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ ) +#define TAG(x) vbo_##x + +#include "vbo_attrib_tmp.h" + + +#if FEATURE_beginend + + +#if FEATURE_evaluators + +static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) +{ + GET_CURRENT_CONTEXT( ctx ); + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + { + GLint i; + if (exec->eval.recalculate_maps) + vbo_exec_eval_update( exec ); + + for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { + if (exec->eval.map1[i].map) + if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) + vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz ); + } + } + + + memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord1f( exec, u ); + + memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); +} + +static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) +{ + GET_CURRENT_CONTEXT( ctx ); + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + { + GLint i; + if (exec->eval.recalculate_maps) + vbo_exec_eval_update( exec ); + + for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { + if (exec->eval.map2[i].map) + if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) + vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz ); + } + + if (ctx->Eval.AutoNormal) + if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) + vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); + } + + memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord2f( exec, u, v ); + + memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); +} + +static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u ) +{ + vbo_exec_EvalCoord1f( u[0] ); +} + +static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u ) +{ + vbo_exec_EvalCoord2f( u[0], u[1] ); +} + +static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / + (GLfloat) ctx->Eval.MapGrid1un); + GLfloat u = i * du + ctx->Eval.MapGrid1u1; + + vbo_exec_EvalCoord1f( u ); +} + + +static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / + (GLfloat) ctx->Eval.MapGrid2un); + GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / + (GLfloat) ctx->Eval.MapGrid2vn); + GLfloat u = i * du + ctx->Eval.MapGrid2u1; + GLfloat v = j * dv + ctx->Eval.MapGrid2v1; + + vbo_exec_EvalCoord2f( u, v ); +} + +/* use noop eval mesh */ +#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1 +#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2 + +#endif /* FEATURE_evaluators */ + + +/** + * Flush (draw) vertices. + * \param unmap - leave VBO unmapped after flushing? + */ +static void +vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap) +{ + if (exec->vtx.vert_count || unmap) { + vbo_exec_vtx_flush( exec, unmap ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } +} + + +/** + * Called via glBegin. + */ +static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) { + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int i; + + if (ctx->NewState) { + _mesa_update_state( ctx ); + + CALL_Begin(ctx->Exec, (mode)); + return; + } + + if (!_mesa_valid_to_render(ctx, "glBegin")) { + return; + } + + /* Heuristic: attempt to isolate attributes occuring outside + * begin/end pairs. + */ + if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) + vbo_exec_FlushVertices_internal(exec, GL_FALSE); + + i = exec->vtx.prim_count++; + exec->vtx.prim[i].mode = mode; + exec->vtx.prim[i].begin = 1; + exec->vtx.prim[i].end = 0; + exec->vtx.prim[i].indexed = 0; + exec->vtx.prim[i].weak = 0; + exec->vtx.prim[i].pad = 0; + exec->vtx.prim[i].start = exec->vtx.vert_count; + exec->vtx.prim[i].count = 0; + exec->vtx.prim[i].num_instances = 1; + + ctx->Driver.CurrentExecPrimitive = mode; + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + +} + + +/** + * Called via glEnd. + */ +static void GLAPIENTRY vbo_exec_End( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (exec->vtx.prim_count > 0) { + /* close off current primitive */ + int idx = exec->vtx.vert_count; + int i = exec->vtx.prim_count - 1; + + exec->vtx.prim[i].end = 1; + exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; + } + + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + + if (exec->vtx.prim_count == VBO_MAX_PRIM) + vbo_exec_vtx_flush( exec, GL_FALSE ); + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); +} + + +/** + * Called via glPrimitiveRestartNV() + */ +static void GLAPIENTRY +vbo_exec_PrimitiveRestartNV(void) +{ + GLenum curPrim; + GET_CURRENT_CONTEXT( ctx ); + + curPrim = ctx->Driver.CurrentExecPrimitive; + + if (curPrim == PRIM_OUTSIDE_BEGIN_END) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" ); + } + else { + vbo_exec_End(); + vbo_exec_Begin(curPrim); + } +} + + + +static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) +{ + GLvertexformat *vfmt = &exec->vtxfmt; + + _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_); + + vfmt->Begin = vbo_exec_Begin; + vfmt->End = vbo_exec_End; + vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV; + + _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_); + _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_); + + vfmt->Rectf = _mesa_noop_Rectf; + + /* from attrib_tmp.h: + */ + vfmt->Color3f = vbo_Color3f; + vfmt->Color3fv = vbo_Color3fv; + vfmt->Color4f = vbo_Color4f; + vfmt->Color4fv = vbo_Color4fv; + vfmt->FogCoordfEXT = vbo_FogCoordfEXT; + vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT; + vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv; + vfmt->Normal3f = vbo_Normal3f; + vfmt->Normal3fv = vbo_Normal3fv; + vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT; + vfmt->TexCoord1f = vbo_TexCoord1f; + vfmt->TexCoord1fv = vbo_TexCoord1fv; + vfmt->TexCoord2f = vbo_TexCoord2f; + vfmt->TexCoord2fv = vbo_TexCoord2fv; + vfmt->TexCoord3f = vbo_TexCoord3f; + vfmt->TexCoord3fv = vbo_TexCoord3fv; + vfmt->TexCoord4f = vbo_TexCoord4f; + vfmt->TexCoord4fv = vbo_TexCoord4fv; + vfmt->Vertex2f = vbo_Vertex2f; + vfmt->Vertex2fv = vbo_Vertex2fv; + vfmt->Vertex3f = vbo_Vertex3f; + vfmt->Vertex3fv = vbo_Vertex3fv; + vfmt->Vertex4f = vbo_Vertex4f; + vfmt->Vertex4fv = vbo_Vertex4fv; + + vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB; + + vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; + + /* integer-valued */ + vfmt->VertexAttribI1i = vbo_VertexAttribI1i; + vfmt->VertexAttribI2i = vbo_VertexAttribI2i; + vfmt->VertexAttribI3i = vbo_VertexAttribI3i; + vfmt->VertexAttribI4i = vbo_VertexAttribI4i; + vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv; + vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv; + vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv; + + /* unsigned integer-valued */ + vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui; + vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui; + vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui; + vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui; + vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv; + vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv; + vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv; + + vfmt->Materialfv = vbo_Materialfv; + + vfmt->EdgeFlag = vbo_EdgeFlag; + vfmt->Indexf = vbo_Indexf; + vfmt->Indexfv = vbo_Indexfv; + +} + + +#else /* FEATURE_beginend */ + + +static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) +{ + /* silence warnings */ + (void) vbo_Color3f; + (void) vbo_Color3fv; + (void) vbo_Color4f; + (void) vbo_Color4fv; + (void) vbo_FogCoordfEXT; + (void) vbo_FogCoordfvEXT; + (void) vbo_MultiTexCoord1f; + (void) vbo_MultiTexCoord1fv; + (void) vbo_MultiTexCoord2f; + (void) vbo_MultiTexCoord2fv; + (void) vbo_MultiTexCoord3f; + (void) vbo_MultiTexCoord3fv; + (void) vbo_MultiTexCoord4f; + (void) vbo_MultiTexCoord4fv; + (void) vbo_Normal3f; + (void) vbo_Normal3fv; + (void) vbo_SecondaryColor3fEXT; + (void) vbo_SecondaryColor3fvEXT; + (void) vbo_TexCoord1f; + (void) vbo_TexCoord1fv; + (void) vbo_TexCoord2f; + (void) vbo_TexCoord2fv; + (void) vbo_TexCoord3f; + (void) vbo_TexCoord3fv; + (void) vbo_TexCoord4f; + (void) vbo_TexCoord4fv; + (void) vbo_Vertex2f; + (void) vbo_Vertex2fv; + (void) vbo_Vertex3f; + (void) vbo_Vertex3fv; + (void) vbo_Vertex4f; + (void) vbo_Vertex4fv; + + (void) vbo_VertexAttrib1fARB; + (void) vbo_VertexAttrib1fvARB; + (void) vbo_VertexAttrib2fARB; + (void) vbo_VertexAttrib2fvARB; + (void) vbo_VertexAttrib3fARB; + (void) vbo_VertexAttrib3fvARB; + (void) vbo_VertexAttrib4fARB; + (void) vbo_VertexAttrib4fvARB; + + (void) vbo_VertexAttrib1fNV; + (void) vbo_VertexAttrib1fvNV; + (void) vbo_VertexAttrib2fNV; + (void) vbo_VertexAttrib2fvNV; + (void) vbo_VertexAttrib3fNV; + (void) vbo_VertexAttrib3fvNV; + (void) vbo_VertexAttrib4fNV; + (void) vbo_VertexAttrib4fvNV; + + (void) vbo_Materialfv; + + (void) vbo_EdgeFlag; + (void) vbo_Indexf; + (void) vbo_Indexfv; +} + + +#endif /* FEATURE_beginend */ + + +/** + * Tell the VBO module to use a real OpenGL vertex buffer object to + * store accumulated immediate-mode vertex data. + * This replaces the malloced buffer which was created in + * vb_exec_vtx_init() below. + */ +void vbo_use_buffer_objects(struct gl_context *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + /* Any buffer name but 0 can be used here since this bufferobj won't + * go into the bufferobj hashtable. + */ + GLuint bufName = IMM_BUFFER_NAME; + GLenum target = GL_ARRAY_BUFFER_ARB; + GLenum usage = GL_STREAM_DRAW_ARB; + GLsizei size = VBO_VERT_BUFFER_SIZE; + + /* Make sure this func is only used once */ + assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); + if (exec->vtx.buffer_map) { + _mesa_align_free(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; + exec->vtx.buffer_ptr = NULL; + } + + /* Allocate a real buffer object now */ + _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); + exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); + ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); +} + + +/** + * If this function is called, all VBO buffers will be unmapped when + * we flush. + * Otherwise, if a simple command like glColor3f() is called and we flush, + * the current VBO may be left mapped. + */ +void +vbo_always_unmap_buffers(struct gl_context *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + exec->begin_vertices_flags |= FLUSH_STORED_VERTICES; +} + + +void vbo_exec_vtx_init( struct vbo_exec_context *exec ) +{ + struct gl_context *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLuint i; + + /* Allocate a buffer object. Will just reuse this object + * continuously, unless vbo_use_buffer_objects() is called to enable + * use of real VBOs. + */ + _mesa_reference_buffer_object(ctx, + &exec->vtx.bufferobj, + ctx->Shared->NullBufferObj); + + ASSERT(!exec->vtx.buffer_map); + exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); + exec->vtx.buffer_ptr = exec->vtx.buffer_map; + + vbo_exec_vtxfmt_init( exec ); + + /* Hook our functions into the dispatch table. + */ + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + ASSERT(i < Elements(exec->vtx.attrsz)); + exec->vtx.attrsz[i] = 0; + ASSERT(i < Elements(exec->vtx.active_sz)); + exec->vtx.active_sz[i] = 0; + } + for (i = 0 ; i < VERT_ATTRIB_MAX; i++) { + ASSERT(i < Elements(exec->vtx.inputs)); + ASSERT(i < Elements(exec->vtx.arrays)); + exec->vtx.inputs[i] = &exec->vtx.arrays[i]; + } + + { + struct gl_client_array *arrays = exec->vtx.arrays; + unsigned i; + + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + + for (i = 0; i < 16; ++i) { + arrays[i ].BufferObj = NULL; + arrays[i + 16].BufferObj = NULL; + _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj, + vbo->legacy_currval[i].BufferObj); + _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj, + vbo->generic_currval[i].BufferObj); + } + } + + exec->vtx.vertex_size = 0; + + exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT; +} + + +void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) +{ + /* using a real VBO for vertex data */ + struct gl_context *ctx = exec->ctx; + unsigned i; + + /* True VBOs should already be unmapped + */ + if (exec->vtx.buffer_map) { + ASSERT(exec->vtx.bufferobj->Name == 0 || + exec->vtx.bufferobj->Name == IMM_BUFFER_NAME); + if (exec->vtx.bufferobj->Name == 0) { + _mesa_align_free(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; + exec->vtx.buffer_ptr = NULL; + } + } + + /* Drop any outstanding reference to the vertex buffer + */ + for (i = 0; i < Elements(exec->vtx.arrays); i++) { + _mesa_reference_buffer_object(ctx, + &exec->vtx.arrays[i].BufferObj, + NULL); + } + + /* Free the vertex buffer. Unmap first if needed. + */ + if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) { + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj); + } + _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); +} + + +/** + * Called upon first glVertex, glColor, glTexCoord, etc. + */ +void vbo_exec_BeginVertices( struct gl_context *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + vbo_exec_vtx_map( exec ); + + assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); + assert(exec->begin_vertices_flags); + + ctx->Driver.NeedFlush |= exec->begin_vertices_flags; +} + + +/** + * Called via ctx->Driver.FlushVertices() + * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT + */ +void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + +#ifdef DEBUG + /* debug check: make sure we don't get called recursively */ + exec->flush_call_depth++; + assert(exec->flush_call_depth == 1); +#endif + + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + /* We've had glBegin but not glEnd! */ +#ifdef DEBUG + exec->flush_call_depth--; + assert(exec->flush_call_depth == 0); +#endif + return; + } + + /* Flush (draw), and make sure VBO is left unmapped when done */ + vbo_exec_FlushVertices_internal(exec, GL_TRUE); + + /* Need to do this to ensure BeginVertices gets called again: + */ + ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); + +#ifdef DEBUG + exec->flush_call_depth--; + assert(exec->flush_call_depth == 0); +#endif +} + + +static void reset_attrfv( struct vbo_exec_context *exec ) +{ + GLuint i; + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + exec->vtx.attrsz[i] = 0; + exec->vtx.active_sz[i] = 0; + } + + exec->vtx.vertex_size = 0; +} + + +void GLAPIENTRY +_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) +{ + vbo_Color4f(r, g, b, a); +} + + +void GLAPIENTRY +_es_Normal3f(GLfloat x, GLfloat y, GLfloat z) +{ + vbo_Normal3f(x, y, z); +} + + +void GLAPIENTRY +_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + vbo_MultiTexCoord4f(target, s, t, r, q); +} + + +void GLAPIENTRY +_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + vbo_Materialfv(face, pname, params); +} + + +void GLAPIENTRY +_es_Materialf(GLenum face, GLenum pname, GLfloat param) +{ + GLfloat p[4]; + p[0] = param; + p[1] = p[2] = p[3] = 0.0F; + vbo_Materialfv(face, pname, p); +} + + +/** + * A special version of glVertexAttrib4f that does not treat index 0 as + * VBO_ATTRIB_POS. + */ +static void +VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w); + else + ERROR(GL_INVALID_VALUE); +} + +void GLAPIENTRY +_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + VertexAttrib4f_nopos(index, x, y, z, w); +} + + +void GLAPIENTRY +_es_VertexAttrib1f(GLuint indx, GLfloat x) +{ + VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib1fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib2fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + VertexAttrib4f_nopos(indx, x, y, z, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib3fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib4fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]); +} diff --git a/mesalib/src/mesa/vbo/vbo_save.h b/mesalib/src/mesa/vbo/vbo_save.h index 873777f17..45cd29979 100644 --- a/mesalib/src/mesa/vbo/vbo_save.h +++ b/mesalib/src/mesa/vbo/vbo_save.h @@ -1,202 +1,202 @@ -/**************************************************************************
-
-Copyright 2002 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
-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
-TUNGSTEN GRAPHICS AND/OR THEIR 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>
- *
- */
-
-#ifndef VBO_SAVE_H
-#define VBO_SAVE_H
-
-#include "main/mfeatures.h"
-#include "main/mtypes.h"
-#include "vbo.h"
-#include "vbo_attrib.h"
-
-
-struct vbo_save_copied_vtx {
- GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
- GLuint nr;
-};
-
-
-/* For display lists, this structure holds a run of vertices of the
- * same format, and a strictly well-formed set of begin/end pairs,
- * starting on the first vertex and ending at the last. Vertex
- * copying on buffer breaks is precomputed according to these
- * primitives, though there are situations where the copying will need
- * correction at execute-time, perhaps by replaying the list as
- * immediate mode commands.
- *
- * On executing this list, the 'current' values may be updated with
- * the values of the final vertex, and often no fixup of the start of
- * the vertex list is required.
- *
- * Eval and other commands that don't fit into these vertex lists are
- * compiled using the fallback opcode mechanism provided by dlist.c.
- */
-struct vbo_save_vertex_list {
- GLubyte attrsz[VBO_ATTRIB_MAX];
- GLuint vertex_size;
-
- /* Copy of the final vertex from node->vertex_store->bufferobj.
- * Keep this in regular (non-VBO) memory to avoid repeated
- * map/unmap of the VBO when updating GL current data.
- */
- GLfloat *current_data;
- GLuint current_size;
-
- GLuint buffer_offset;
- GLuint count;
- GLuint wrap_count; /* number of copied vertices at start */
- GLboolean dangling_attr_ref; /* current attr implicitly referenced
- outside the list */
-
- struct _mesa_prim *prim;
- GLuint prim_count;
-
- struct vbo_save_vertex_store *vertex_store;
- struct vbo_save_primitive_store *prim_store;
-};
-
-/* These buffers should be a reasonable size to support upload to
- * hardware. Current vbo implementation will re-upload on any
- * changes, so don't make too big or apps which dynamically create
- * dlists and use only a few times will suffer.
- *
- * Consider stategy of uploading regions from the VBO on demand in the
- * case of dynamic vbos. Then make the dlist code signal that
- * likelyhood as it occurs. No reason we couldn't change usage
- * internally even though this probably isn't allowed for client VBOs?
- */
-#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */
-#define VBO_SAVE_PRIM_SIZE 128
-#define VBO_SAVE_PRIM_MODE_MASK 0x3f
-#define VBO_SAVE_PRIM_WEAK 0x40
-#define VBO_SAVE_PRIM_NO_CURRENT_UPDATE 0x80
-
-#define VBO_SAVE_FALLBACK 0x10000000
-
-/* Storage to be shared among several vertex_lists.
- */
-struct vbo_save_vertex_store {
- struct gl_buffer_object *bufferobj;
- GLfloat *buffer;
- GLuint used;
- GLuint refcount;
-};
-
-struct vbo_save_primitive_store {
- struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE];
- GLuint used;
- GLuint refcount;
-};
-
-
-struct vbo_save_context {
- struct gl_context *ctx;
- GLvertexformat vtxfmt;
- struct gl_client_array arrays[VBO_ATTRIB_MAX];
- const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
-
- GLubyte attrsz[VBO_ATTRIB_MAX];
- GLubyte active_sz[VBO_ATTRIB_MAX];
- GLuint vertex_size;
-
- GLfloat *buffer;
- GLuint count;
- GLuint wrap_count;
- GLuint replay_flags;
-
- struct _mesa_prim *prim;
- GLuint prim_count, prim_max;
-
- struct vbo_save_vertex_store *vertex_store;
- struct vbo_save_primitive_store *prim_store;
-
- GLfloat *buffer_ptr; /* cursor, points into buffer */
- GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
- GLfloat *attrptr[VBO_ATTRIB_MAX];
- GLuint vert_count;
- GLuint max_vert;
- GLboolean dangling_attr_ref;
- GLboolean have_materials;
-
- GLuint opcode_vertex_list;
-
- struct vbo_save_copied_vtx copied;
-
- GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */
- GLubyte *currentsz[VBO_ATTRIB_MAX];
-};
-
-#if FEATURE_dlist
-
-void vbo_save_init( struct gl_context *ctx );
-void vbo_save_destroy( struct gl_context *ctx );
-void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback );
-
-/* save_loopback.c:
- */
-void vbo_loopback_vertex_list( struct gl_context *ctx,
- const GLfloat *buffer,
- const GLubyte *attrsz,
- const struct _mesa_prim *prim,
- GLuint prim_count,
- GLuint wrap_count,
- GLuint vertex_size);
-
-/* Callbacks:
- */
-void vbo_save_EndList( struct gl_context *ctx );
-void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode );
-void vbo_save_EndCallList( struct gl_context *ctx );
-void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *list );
-void vbo_save_SaveFlushVertices( struct gl_context *ctx );
-GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode );
-
-void vbo_save_playback_vertex_list( struct gl_context *ctx, void *data );
-
-void vbo_save_api_init( struct vbo_save_context *save );
-
-#else /* FEATURE_dlist */
-
-static INLINE void
-vbo_save_init( struct gl_context *ctx )
-{
-}
-
-static INLINE void
-vbo_save_destroy( struct gl_context *ctx )
-{
-}
-
-#endif /* FEATURE_dlist */
-
-#endif /* VBO_SAVE_H */
+/************************************************************************** + +Copyright 2002 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 +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 +TUNGSTEN GRAPHICS AND/OR THEIR 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> + * + */ + +#ifndef VBO_SAVE_H +#define VBO_SAVE_H + +#include "main/mfeatures.h" +#include "main/mtypes.h" +#include "vbo.h" +#include "vbo_attrib.h" + + +struct vbo_save_copied_vtx { + GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS]; + GLuint nr; +}; + + +/* For display lists, this structure holds a run of vertices of the + * same format, and a strictly well-formed set of begin/end pairs, + * starting on the first vertex and ending at the last. Vertex + * copying on buffer breaks is precomputed according to these + * primitives, though there are situations where the copying will need + * correction at execute-time, perhaps by replaying the list as + * immediate mode commands. + * + * On executing this list, the 'current' values may be updated with + * the values of the final vertex, and often no fixup of the start of + * the vertex list is required. + * + * Eval and other commands that don't fit into these vertex lists are + * compiled using the fallback opcode mechanism provided by dlist.c. + */ +struct vbo_save_vertex_list { + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLuint vertex_size; + + /* Copy of the final vertex from node->vertex_store->bufferobj. + * Keep this in regular (non-VBO) memory to avoid repeated + * map/unmap of the VBO when updating GL current data. + */ + GLfloat *current_data; + GLuint current_size; + + GLuint buffer_offset; + GLuint count; /**< vertex count */ + GLuint wrap_count; /* number of copied vertices at start */ + GLboolean dangling_attr_ref; /* current attr implicitly referenced + outside the list */ + + struct _mesa_prim *prim; + GLuint prim_count; + + struct vbo_save_vertex_store *vertex_store; + struct vbo_save_primitive_store *prim_store; +}; + +/* These buffers should be a reasonable size to support upload to + * hardware. Current vbo implementation will re-upload on any + * changes, so don't make too big or apps which dynamically create + * dlists and use only a few times will suffer. + * + * Consider stategy of uploading regions from the VBO on demand in the + * case of dynamic vbos. Then make the dlist code signal that + * likelyhood as it occurs. No reason we couldn't change usage + * internally even though this probably isn't allowed for client VBOs? + */ +#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */ +#define VBO_SAVE_PRIM_SIZE 128 +#define VBO_SAVE_PRIM_MODE_MASK 0x3f +#define VBO_SAVE_PRIM_WEAK 0x40 +#define VBO_SAVE_PRIM_NO_CURRENT_UPDATE 0x80 + +#define VBO_SAVE_FALLBACK 0x10000000 + +/* Storage to be shared among several vertex_lists. + */ +struct vbo_save_vertex_store { + struct gl_buffer_object *bufferobj; + GLfloat *buffer; + GLuint used; + GLuint refcount; +}; + +struct vbo_save_primitive_store { + struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE]; + GLuint used; + GLuint refcount; +}; + + +struct vbo_save_context { + struct gl_context *ctx; + GLvertexformat vtxfmt; + struct gl_client_array arrays[VBO_ATTRIB_MAX]; + const struct gl_client_array *inputs[VBO_ATTRIB_MAX]; + + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLubyte active_sz[VBO_ATTRIB_MAX]; + GLuint vertex_size; + + GLfloat *buffer; + GLuint count; + GLuint wrap_count; + GLuint replay_flags; + + struct _mesa_prim *prim; + GLuint prim_count, prim_max; + + struct vbo_save_vertex_store *vertex_store; + struct vbo_save_primitive_store *prim_store; + + GLfloat *buffer_ptr; /* cursor, points into buffer */ + GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */ + GLfloat *attrptr[VBO_ATTRIB_MAX]; + GLuint vert_count; + GLuint max_vert; + GLboolean dangling_attr_ref; + GLboolean have_materials; + + GLuint opcode_vertex_list; + + struct vbo_save_copied_vtx copied; + + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */ + GLubyte *currentsz[VBO_ATTRIB_MAX]; +}; + +#if FEATURE_dlist + +void vbo_save_init( struct gl_context *ctx ); +void vbo_save_destroy( struct gl_context *ctx ); +void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback ); + +/* save_loopback.c: + */ +void vbo_loopback_vertex_list( struct gl_context *ctx, + const GLfloat *buffer, + const GLubyte *attrsz, + const struct _mesa_prim *prim, + GLuint prim_count, + GLuint wrap_count, + GLuint vertex_size); + +/* Callbacks: + */ +void vbo_save_EndList( struct gl_context *ctx ); +void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode ); +void vbo_save_EndCallList( struct gl_context *ctx ); +void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *list ); +void vbo_save_SaveFlushVertices( struct gl_context *ctx ); +GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode ); + +void vbo_save_playback_vertex_list( struct gl_context *ctx, void *data ); + +void vbo_save_api_init( struct vbo_save_context *save ); + +#else /* FEATURE_dlist */ + +static INLINE void +vbo_save_init( struct gl_context *ctx ) +{ +} + +static INLINE void +vbo_save_destroy( struct gl_context *ctx ) +{ +} + +#endif /* FEATURE_dlist */ + +#endif /* VBO_SAVE_H */ diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 836c76fe8..9041f791e 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -100,12 +100,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * NOTE: Old 'parity' issue is gone, but copying can still be * wrong-footed on replay. */ -static GLuint _save_copy_vertices( struct gl_context *ctx, - const struct vbo_save_vertex_list *node, - const GLfloat *src_buffer) +static GLuint +_save_copy_vertices(struct gl_context *ctx, + const struct vbo_save_vertex_list *node, + const GLfloat * src_buffer) { - struct vbo_save_context *save = &vbo_context( ctx )->save; - const struct _mesa_prim *prim = &node->prim[node->prim_count-1]; + struct vbo_save_context *save = &vbo_context(ctx)->save; + const struct _mesa_prim *prim = &node->prim[node->prim_count - 1]; GLuint nr = prim->count; GLuint sz = save->vertex_size; const GLfloat *src = src_buffer + prim->start * sz; @@ -114,55 +115,65 @@ static GLuint _save_copy_vertices( struct gl_context *ctx, if (prim->end) return 0; - - switch( prim->mode ) - { + + switch (prim->mode) { case GL_POINTS: return 0; case GL_LINES: - ovf = nr&1; - for (i = 0 ; i < ovf ; i++) - memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + ovf = nr & 1; + for (i = 0; i < ovf; i++) + memcpy(dst + i * sz, src + (nr - ovf + i) * sz, + sz * sizeof(GLfloat)); return i; case GL_TRIANGLES: - ovf = nr%3; - for (i = 0 ; i < ovf ; i++) - memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + ovf = nr % 3; + for (i = 0; i < ovf; i++) + memcpy(dst + i * sz, src + (nr - ovf + i) * sz, + sz * sizeof(GLfloat)); return i; case GL_QUADS: - ovf = nr&3; - for (i = 0 ; i < ovf ; i++) - memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + ovf = nr & 3; + for (i = 0; i < ovf; i++) + memcpy(dst + i * sz, src + (nr - ovf + i) * sz, + sz * sizeof(GLfloat)); return i; case GL_LINE_STRIP: - if (nr == 0) - return 0; + if (nr == 0) + return 0; else { - memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) ); - return 1; + memcpy(dst, src + (nr - 1) * sz, sz * sizeof(GLfloat)); + return 1; } case GL_LINE_LOOP: case GL_TRIANGLE_FAN: case GL_POLYGON: - if (nr == 0) - return 0; + if (nr == 0) + return 0; else if (nr == 1) { - memcpy( dst, src+0, sz*sizeof(GLfloat) ); - return 1; - } else { - memcpy( dst, src+0, sz*sizeof(GLfloat) ); - memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) ); - return 2; + memcpy(dst, src + 0, sz * sizeof(GLfloat)); + return 1; + } + else { + memcpy(dst, src + 0, sz * sizeof(GLfloat)); + memcpy(dst + sz, src + (nr - 1) * sz, sz * sizeof(GLfloat)); + return 2; } case GL_TRIANGLE_STRIP: case GL_QUAD_STRIP: switch (nr) { - case 0: ovf = 0; break; - case 1: ovf = 1; break; - default: ovf = 2 + (nr&1); break; + case 0: + ovf = 0; + break; + case 1: + ovf = 1; + break; + default: + ovf = 2 + (nr & 1); + break; } - for (i = 0 ; i < ovf ; i++) - memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + for (i = 0; i < ovf; i++) + memcpy(dst + i * sz, src + (nr - ovf + i) * sz, + sz * sizeof(GLfloat)); return i; default: assert(0); @@ -171,9 +182,11 @@ static GLuint _save_copy_vertices( struct gl_context *ctx, } -static struct vbo_save_vertex_store *alloc_vertex_store( struct gl_context *ctx ) +static struct vbo_save_vertex_store * +alloc_vertex_store(struct gl_context *ctx) { - struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store); + struct vbo_save_vertex_store *vertex_store = + CALLOC_STRUCT(vbo_save_vertex_store); /* obj->Name needs to be non-zero, but won't ever be examined more * closely than that. In particular these buffers won't be entered @@ -185,12 +198,10 @@ static struct vbo_save_vertex_store *alloc_vertex_store( struct gl_context *ctx VBO_BUF_ID, GL_ARRAY_BUFFER_ARB); - ctx->Driver.BufferData( ctx, - GL_ARRAY_BUFFER_ARB, - VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), - NULL, - GL_STATIC_DRAW_ARB, - vertex_store->bufferobj); + ctx->Driver.BufferData(ctx, + GL_ARRAY_BUFFER_ARB, + VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), + NULL, GL_STATIC_DRAW_ARB, vertex_store->bufferobj); vertex_store->buffer = NULL; vertex_store->used = 0; @@ -199,7 +210,10 @@ static struct vbo_save_vertex_store *alloc_vertex_store( struct gl_context *ctx return vertex_store; } -static void free_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store ) + +static void +free_vertex_store(struct gl_context *ctx, + struct vbo_save_vertex_store *vertex_store) { assert(!vertex_store->buffer); @@ -207,51 +221,62 @@ static void free_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_st _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL); } - FREE( vertex_store ); + FREE(vertex_store); } -static GLfloat *map_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store ) + +static GLfloat * +map_vertex_store(struct gl_context *ctx, + struct vbo_save_vertex_store *vertex_store) { assert(vertex_store->bufferobj); assert(!vertex_store->buffer); - vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx, - GL_ARRAY_BUFFER_ARB, /* not used */ - GL_WRITE_ONLY, /* not used */ - vertex_store->bufferobj); + vertex_store->buffer = + (GLfloat *) ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* not used */ + GL_WRITE_ONLY, /* not used */ + vertex_store-> + bufferobj); assert(vertex_store->buffer); return vertex_store->buffer + vertex_store->used; } -static void unmap_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store ) + +static void +unmap_vertex_store(struct gl_context *ctx, + struct vbo_save_vertex_store *vertex_store) { - ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj ); + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj); vertex_store->buffer = NULL; } -static struct vbo_save_primitive_store *alloc_prim_store( struct gl_context *ctx ) +static struct vbo_save_primitive_store * +alloc_prim_store(struct gl_context *ctx) { - struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store); + struct vbo_save_primitive_store *store = + CALLOC_STRUCT(vbo_save_primitive_store); (void) ctx; store->used = 0; store->refcount = 1; return store; } -static void _save_reset_counters( struct gl_context *ctx ) + +static void +_save_reset_counters(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; save->prim = save->prim_store->buffer + save->prim_store->used; - save->buffer = (save->vertex_store->buffer + - save->vertex_store->used); + save->buffer = save->vertex_store->buffer + save->vertex_store->used; assert(save->buffer == save->buffer_ptr); if (save->vertex_size) - save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / - save->vertex_size); + save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / + save->vertex_size); else save->max_vert = 0; @@ -262,10 +287,12 @@ static void _save_reset_counters( struct gl_context *ctx ) } -/* Insert the active immediate struct onto the display list currently +/** + * Insert the active immediate struct onto the display list currently * being built. */ -static void _save_compile_vertex_list( struct gl_context *ctx ) +static void +_save_compile_vertex_list(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_list *node; @@ -283,7 +310,8 @@ static void _save_compile_vertex_list( struct gl_context *ctx ) */ memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz)); node->vertex_size = save->vertex_size; - node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); + node->buffer_offset = + (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); node->count = save->vert_count; node->wrap_count = save->copied.nr; node->dangling_attr_ref = save->dangling_attr_ref; @@ -298,34 +326,33 @@ static void _save_compile_vertex_list( struct gl_context *ctx ) if (node->prim[0].no_current_update) { node->current_size = 0; node->current_data = NULL; - } else { + } + else { node->current_size = node->vertex_size - node->attrsz[0]; node->current_data = NULL; - + if (node->current_size) { /* If the malloc fails, we just pull the data out of the VBO * later instead. */ - node->current_data = MALLOC( node->current_size * sizeof(GLfloat) ); + node->current_data = MALLOC(node->current_size * sizeof(GLfloat)); if (node->current_data) { - const char *buffer = (const char *)save->vertex_store->buffer; + const char *buffer = (const char *) save->vertex_store->buffer; unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat); unsigned vertex_offset = 0; - + if (node->count) - vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat); - - memcpy( node->current_data, - buffer + node->buffer_offset + vertex_offset + attr_offset, - node->current_size * sizeof(GLfloat) ); + vertex_offset = + (node->count - 1) * node->vertex_size * sizeof(GLfloat); + + memcpy(node->current_data, + buffer + node->buffer_offset + vertex_offset + attr_offset, + node->current_size * sizeof(GLfloat)); } } } - - - assert(node->attrsz[VBO_ATTRIB_POS] != 0 || - node->count == 0); + assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0); if (save->dangling_attr_ref) ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS; @@ -333,11 +360,9 @@ static void _save_compile_vertex_list( struct gl_context *ctx ) save->vertex_store->used += save->vertex_size * node->count; save->prim_store->used += node->prim_count; - /* Copy duplicated vertices */ - save->copied.nr = _save_copy_vertices( ctx, node, save->buffer ); - + save->copied.nr = _save_copy_vertices(ctx, node, save->buffer); /* Deal with GL_COMPILE_AND_EXECUTE: */ @@ -346,57 +371,55 @@ static void _save_compile_vertex_list( struct gl_context *ctx ) _glapi_set_dispatch(ctx->Exec); - vbo_loopback_vertex_list( ctx, - (const GLfloat *)((const char *)save->vertex_store->buffer + - node->buffer_offset), - node->attrsz, - node->prim, - node->prim_count, - node->wrap_count, - node->vertex_size); + vbo_loopback_vertex_list(ctx, + (const GLfloat *) ((const char *) save-> + vertex_store->buffer + + node->buffer_offset), + node->attrsz, node->prim, node->prim_count, + node->wrap_count, node->vertex_size); _glapi_set_dispatch(dispatch); } - /* Decide whether the storage structs are full, or can be used for * the next vertex lists as well. */ - if (save->vertex_store->used > + if (save->vertex_store->used > VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) { /* Unmap old store: */ - unmap_vertex_store( ctx, save->vertex_store ); + unmap_vertex_store(ctx, save->vertex_store); /* Release old reference: */ - save->vertex_store->refcount--; + save->vertex_store->refcount--; assert(save->vertex_store->refcount != 0); save->vertex_store = NULL; /* Allocate and map new store: */ - save->vertex_store = alloc_vertex_store( ctx ); - save->buffer_ptr = map_vertex_store( ctx, save->vertex_store ); - } + save->vertex_store = alloc_vertex_store(ctx); + save->buffer_ptr = map_vertex_store(ctx, save->vertex_store); + } if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { - save->prim_store->refcount--; + save->prim_store->refcount--; assert(save->prim_store->refcount != 0); - save->prim_store = alloc_prim_store( ctx ); - } + save->prim_store = alloc_prim_store(ctx); + } /* Reset our structures for the next run of vertices: */ - _save_reset_counters( ctx ); + _save_reset_counters(ctx); } -/* TODO -- If no new vertices have been stored, don't bother saving - * it. +/** + * TODO -- If no new vertices have been stored, don't bother saving it. */ -static void _save_wrap_buffers( struct gl_context *ctx ) +static void +_save_wrap_buffers(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i = save->prim_count - 1; @@ -409,15 +432,14 @@ static void _save_wrap_buffers( struct gl_context *ctx ) /* Close off in-progress primitive. */ - save->prim[i].count = (save->vert_count - - save->prim[i].start); + save->prim[i].count = (save->vert_count - save->prim[i].start); mode = save->prim[i].mode; weak = save->prim[i].weak; no_current_update = save->prim[i].no_current_update; - + /* store the copied vertices, and allocate a new list. */ - _save_compile_vertex_list( ctx ); + _save_compile_vertex_list(ctx); /* Restart interrupted primitive */ @@ -434,11 +456,12 @@ static void _save_wrap_buffers( struct gl_context *ctx ) } - -/* Called only when buffers are wrapped as the result of filling the +/** + * Called only when buffers are wrapped as the result of filling the * vertex_store struct. */ -static void _save_wrap_filled_vertex( struct gl_context *ctx ) +static void +_save_wrap_filled_vertex(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLfloat *data = save->copied.buffer; @@ -446,14 +469,14 @@ static void _save_wrap_filled_vertex( struct gl_context *ctx ) /* Emit a glEnd to close off the last vertex list. */ - _save_wrap_buffers( ctx ); - - /* Copy stored stored vertices to start of new list. + _save_wrap_buffers(ctx); + + /* Copy stored stored vertices to start of new list. */ assert(save->max_vert - save->vert_count > save->copied.nr); - for (i = 0 ; i < save->copied.nr ; i++) { - memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat)); + for (i = 0; i < save->copied.nr; i++) { + memcpy(save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat)); data += save->vertex_size; save->buffer_ptr += save->vertex_size; save->vert_count++; @@ -461,46 +484,48 @@ static void _save_wrap_filled_vertex( struct gl_context *ctx ) } -static void _save_copy_to_current( struct gl_context *ctx ) +static void +_save_copy_to_current(struct gl_context *ctx) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i; - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { if (save->attrsz[i]) { - save->currentsz[i][0] = save->attrsz[i]; - COPY_CLEAN_4V(save->current[i], - save->attrsz[i], - save->attrptr[i]); + save->currentsz[i][0] = save->attrsz[i]; + COPY_CLEAN_4V(save->current[i], save->attrsz[i], save->attrptr[i]); } } } -static void _save_copy_from_current( struct gl_context *ctx ) +static void +_save_copy_from_current(struct gl_context *ctx) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i; - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { switch (save->attrsz[i]) { - case 4: save->attrptr[i][3] = save->current[i][3]; - case 3: save->attrptr[i][2] = save->current[i][2]; - case 2: save->attrptr[i][1] = save->current[i][1]; - case 1: save->attrptr[i][0] = save->current[i][0]; - case 0: break; + case 4: + save->attrptr[i][3] = save->current[i][3]; + case 3: + save->attrptr[i][2] = save->current[i][2]; + case 2: + save->attrptr[i][1] = save->current[i][1]; + case 1: + save->attrptr[i][0] = save->current[i][0]; + case 0: + break; } } } - - /* Flush existing data, set new attrib size, replay copied vertices. - */ -static void _save_upgrade_vertex( struct gl_context *ctx, - GLuint attr, - GLuint newsz ) + */ +static void +_save_upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint oldsz; @@ -510,16 +535,16 @@ static void _save_upgrade_vertex( struct gl_context *ctx, /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ - if (save->vert_count) - _save_wrap_buffers( ctx ); + if (save->vert_count) + _save_wrap_buffers(ctx); else - assert( save->copied.nr == 0 ); + assert(save->copied.nr == 0); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ - _save_copy_to_current( ctx ); + _save_copy_to_current(ctx); /* Fix up sizes: */ @@ -527,24 +552,25 @@ static void _save_upgrade_vertex( struct gl_context *ctx, save->attrsz[attr] = newsz; save->vertex_size += newsz - oldsz; - save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / - save->vertex_size); + save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / + save->vertex_size); save->vert_count = 0; /* Recalculate all the attrptr[] values: */ - for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) { + for (i = 0, tmp = save->vertex; i < VBO_ATTRIB_MAX; i++) { if (save->attrsz[i]) { - save->attrptr[i] = tmp; - tmp += save->attrsz[i]; + save->attrptr[i] = tmp; + tmp += save->attrsz[i]; + } + else { + save->attrptr[i] = NULL; /* will not be dereferenced. */ } - else - save->attrptr[i] = NULL; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ - _save_copy_from_current( ctx ); + _save_copy_from_current(ctx); /* Replay stored vertices to translate them to new format here. * @@ -552,8 +578,7 @@ static void _save_upgrade_vertex( struct gl_context *ctx, * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ - if (save->copied.nr) - { + if (save->copied.nr) { GLfloat *data = save->copied.buffer; GLfloat *dest = save->buffer; GLuint j; @@ -561,32 +586,32 @@ static void _save_upgrade_vertex( struct gl_context *ctx, /* Need to note this and fix up at runtime (or loopback): */ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { - assert(oldsz == 0); - save->dangling_attr_ref = GL_TRUE; + assert(oldsz == 0); + save->dangling_attr_ref = GL_TRUE; } - for (i = 0 ; i < save->copied.nr ; i++) { - for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { - if (save->attrsz[j]) { - if (j == attr) { - if (oldsz) { - COPY_CLEAN_4V( dest, oldsz, data ); - data += oldsz; - dest += newsz; - } - else { - COPY_SZ_4V( dest, newsz, save->current[attr] ); - dest += newsz; - } - } - else { - GLint sz = save->attrsz[j]; - COPY_SZ_4V( dest, sz, data ); - data += sz; - dest += sz; - } - } - } + for (i = 0; i < save->copied.nr; i++) { + for (j = 0; j < VBO_ATTRIB_MAX; j++) { + if (save->attrsz[j]) { + if (j == attr) { + if (oldsz) { + COPY_CLEAN_4V(dest, oldsz, data); + data += oldsz; + dest += newsz; + } + else { + COPY_SZ_4V(dest, newsz, save->current[attr]); + dest += newsz; + } + } + else { + GLint sz = save->attrsz[j]; + COPY_SZ_4V(dest, sz, data); + data += sz; + dest += sz; + } + } + } } save->buffer_ptr = dest; @@ -594,15 +619,17 @@ static void _save_upgrade_vertex( struct gl_context *ctx, } } -static void save_fixup_vertex( struct gl_context *ctx, GLuint attr, GLuint sz ) + +static void +save_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint sz) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_context *save = &vbo_context(ctx)->save; if (sz > save->attrsz[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ - _save_upgrade_vertex( ctx, attr, sz ); + _save_upgrade_vertex(ctx, attr, sz); } else if (sz < save->active_sz[attr]) { static GLfloat id[4] = { 0, 0, 0, 1 }; @@ -611,29 +638,31 @@ static void save_fixup_vertex( struct gl_context *ctx, GLuint attr, GLuint sz ) /* New size is equal or smaller - just need to fill in some * zeros. */ - for (i = sz ; i <= save->attrsz[attr] ; i++) - save->attrptr[attr][i-1] = id[i-1]; + for (i = sz; i <= save->attrsz[attr]; i++) + save->attrptr[attr][i - 1] = id[i - 1]; } save->active_sz[attr] = sz; } -static void _save_reset_vertex( struct gl_context *ctx ) + +static void +_save_reset_vertex(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i; - for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + for (i = 0; i < VBO_ATTRIB_MAX; i++) { save->attrsz[i] = 0; save->active_sz[i] = 0; } - + save->vertex_size = 0; } -#define ERROR(err) _mesa_compile_error( ctx, err, __FUNCTION__ ); +#define ERROR(err) _mesa_compile_error(ctx, err, __FUNCTION__); /* Only one size for each attribute may be active at once. Eg. if @@ -642,7 +671,7 @@ static void _save_reset_vertex( struct gl_context *ctx ) * 3f version won't otherwise set color[3] to 1.0 -- this is the job * of the chooser function when switching between Color4f and Color3f. */ -#define ATTR( A, N, V0, V1, V2, V3 ) \ +#define ATTR(A, N, V0, V1, V2, V3) \ do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ \ @@ -666,7 +695,7 @@ do { \ save->buffer_ptr += save->vertex_size; \ \ if (++save->vert_count >= save->max_vert) \ - _save_wrap_filled_vertex( ctx ); \ + _save_wrap_filled_vertex(ctx); \ } \ } while (0) @@ -681,99 +710,108 @@ do { \ * -- Flush current buffer * -- Fallback to opcodes for the rest of the begin/end object. */ -static void DO_FALLBACK( struct gl_context *ctx ) +static void +dlist_fallback(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; if (save->vert_count || save->prim_count) { - GLint i = save->prim_count - 1; - - /* Close off in-progress primitive. - */ - save->prim[i].count = (save->vert_count - - save->prim[i].start); + if (save->prim_count > 0) { + /* Close off in-progress primitive. */ + GLint i = save->prim_count - 1; + save->prim[i].count = save->vert_count - save->prim[i].start; + } /* Need to replay this display list with loopback, * unfortunately, otherwise this primitive won't be handled * properly: */ save->dangling_attr_ref = 1; - - _save_compile_vertex_list( ctx ); + + _save_compile_vertex_list(ctx); } - _save_copy_to_current( ctx ); - _save_reset_vertex( ctx ); - _save_reset_counters( ctx ); - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); + _save_copy_to_current(ctx); + _save_reset_vertex(ctx); + _save_reset_counters(ctx); + _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); ctx->Driver.SaveNeedFlush = 0; } -static void GLAPIENTRY _save_EvalCoord1f( GLfloat u ) + +static void GLAPIENTRY +_save_EvalCoord1f(GLfloat u) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalCoord1f(ctx->Save, (u)); } -static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v ) +static void GLAPIENTRY +_save_EvalCoord1fv(const GLfloat * v) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalCoord1fv(ctx->Save, (v)); } -static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v ) +static void GLAPIENTRY +_save_EvalCoord2f(GLfloat u, GLfloat v) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalCoord2f(ctx->Save, (u, v)); } -static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v ) +static void GLAPIENTRY +_save_EvalCoord2fv(const GLfloat * v) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalCoord2fv(ctx->Save, (v)); } -static void GLAPIENTRY _save_EvalPoint1( GLint i ) +static void GLAPIENTRY +_save_EvalPoint1(GLint i) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalPoint1(ctx->Save, (i)); } -static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j ) +static void GLAPIENTRY +_save_EvalPoint2(GLint i, GLint j) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_EvalPoint2(ctx->Save, (i, j)); } -static void GLAPIENTRY _save_CallList( GLuint l ) +static void GLAPIENTRY +_save_CallList(GLuint l) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_CallList(ctx->Save, (l)); } -static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v ) +static void GLAPIENTRY +_save_CallLists(GLsizei n, GLenum type, const GLvoid * v) { GET_CURRENT_CONTEXT(ctx); - DO_FALLBACK(ctx); + dlist_fallback(ctx); CALL_CallLists(ctx->Save, (n, type, v)); } - /* This begin is hooked into ... Updating of * ctx->Driver.CurrentSavePrimitive is already taken care of. */ -GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode ) +GLboolean +vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i = save->prim_count++; @@ -782,133 +820,169 @@ GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode ) save->prim[i].begin = 1; save->prim[i].end = 0; save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; - save->prim[i].no_current_update = (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0; + save->prim[i].no_current_update = + (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0; save->prim[i].pad = 0; save->prim[i].start = save->vert_count; - save->prim[i].count = 0; - save->prim[i].num_instances = 1; + save->prim[i].count = 0; + save->prim[i].num_instances = 1; - _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); + _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); ctx->Driver.SaveNeedFlush = 1; return GL_TRUE; } - -static void GLAPIENTRY _save_End( void ) +static void GLAPIENTRY +_save_End(void) { - GET_CURRENT_CONTEXT( ctx ); - struct vbo_save_context *save = &vbo_context(ctx)->save; + GET_CURRENT_CONTEXT(ctx); + struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i = save->prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; save->prim[i].end = 1; - save->prim[i].count = (save->vert_count - - save->prim[i].start); + save->prim[i].count = (save->vert_count - save->prim[i].start); if (i == (GLint) save->prim_max - 1) { - _save_compile_vertex_list( ctx ); + _save_compile_vertex_list(ctx); assert(save->copied.nr == 0); } /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. - */ - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); + */ + _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } /* These are all errors as this vtxfmt is only installed inside * begin/end pairs. */ -static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) +static void GLAPIENTRY +_save_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) count; (void) type; (void) indices; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" ); + (void) mode; + (void) count; + (void) type; + (void) indices; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawElements"); } -static void GLAPIENTRY _save_DrawRangeElements(GLenum mode, - GLuint start, GLuint end, - GLsizei count, GLenum type, - const GLvoid *indices) +static void GLAPIENTRY +_save_DrawRangeElements(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid * indices) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" ); + (void) mode; + (void) start; + (void) end; + (void) count; + (void) type; + (void) indices; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements"); } -static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLint basevertex) + +static void GLAPIENTRY +_save_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices, GLint basevertex) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) count; (void) type; (void) indices; (void)basevertex; - - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" ); + (void) mode; + (void) count; + (void) type; + (void) indices; + (void) basevertex; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawElements"); } -static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode, - GLuint start, - GLuint end, - GLsizei count, - GLenum type, - const GLvoid *indices, - GLint basevertex) + +static void GLAPIENTRY +_save_DrawRangeElementsBaseVertex(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid * indices, GLint basevertex) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) start; (void) end; (void) count; (void) type; - (void) indices; (void)basevertex; - - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" ); + (void) mode; + (void) start; + (void) end; + (void) count; + (void) type; + (void) indices; + (void) basevertex; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements"); } -static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count) + +static void GLAPIENTRY +_save_DrawArrays(GLenum mode, GLint start, GLsizei count) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) start; (void) count; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" ); + (void) mode; + (void) start; + (void) count; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawArrays"); } -static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) + +static void GLAPIENTRY +_save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { GET_CURRENT_CONTEXT(ctx); - (void) x1; (void) y1; (void) x2; (void) y2; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" ); + (void) x1; + (void) y1; + (void) x2; + (void) y2; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glRectf"); } -static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) + +static void GLAPIENTRY +_save_EvalMesh1(GLenum mode, GLint i1, GLint i2) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) i1; (void) i2; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" ); + (void) mode; + (void) i1; + (void) i2; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glEvalMesh1"); } -static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2, - GLint j1, GLint j2 ) + +static void GLAPIENTRY +_save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) { GET_CURRENT_CONTEXT(ctx); - (void) mode; (void) i1; (void) i2; (void) j1; (void) j2; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" ); + (void) mode; + (void) i1; + (void) i2; + (void) j1; + (void) j2; + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glEvalMesh2"); } -static void GLAPIENTRY _save_Begin( GLenum mode ) + +static void GLAPIENTRY +_save_Begin(GLenum mode) { - GET_CURRENT_CONTEXT( ctx ); + GET_CURRENT_CONTEXT(ctx); (void) mode; - _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" ); + _mesa_compile_error(ctx, GL_INVALID_OPERATION, "Recursive glBegin"); } -static void GLAPIENTRY _save_PrimitiveRestartNV( void ) +static void GLAPIENTRY +_save_PrimitiveRestartNV(void) { GLenum curPrim; - GET_CURRENT_CONTEXT( ctx ); + GET_CURRENT_CONTEXT(ctx); curPrim = ctx->Driver.CurrentSavePrimitive; @@ -921,96 +995,102 @@ static void GLAPIENTRY _save_PrimitiveRestartNV( void ) * maintained in ctx->ListState, active when the list is known or * suspected to be outside any begin/end primitive. */ -static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +static void GLAPIENTRY +_save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { GET_CURRENT_CONTEXT(ctx); - vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK ); - CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 )); - CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 )); - CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 )); - CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 )); + vbo_save_NotifyBegin(ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK); + CALL_Vertex2f(GET_DISPATCH(), (x1, y1)); + CALL_Vertex2f(GET_DISPATCH(), (x2, y1)); + CALL_Vertex2f(GET_DISPATCH(), (x2, y2)); + CALL_Vertex2f(GET_DISPATCH(), (x1, y2)); CALL_End(GET_DISPATCH(), ()); } -static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) +static void GLAPIENTRY +_save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) { GET_CURRENT_CONTEXT(ctx); GLint i; - if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + if (!_mesa_validate_DrawArrays(ctx, mode, start, count)) return; - _ae_map_vbos( ctx ); + _ae_map_vbos(ctx); - vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE); + vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK + | VBO_SAVE_PRIM_NO_CURRENT_UPDATE)); for (i = 0; i < count; i++) - CALL_ArrayElement(GET_DISPATCH(), (start + i)); + CALL_ArrayElement(GET_DISPATCH(), (start + i)); CALL_End(GET_DISPATCH(), ()); - _ae_unmap_vbos( ctx ); + _ae_unmap_vbos(ctx); } + /* Could do better by copying the arrays and element list intact and * then emitting an indexed prim at runtime. */ -static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) +static void GLAPIENTRY +_save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) { GET_CURRENT_CONTEXT(ctx); GLint i; - if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 )) + if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices, 0)) return; - _ae_map_vbos( ctx ); + _ae_map_vbos(ctx); if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) - indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices); + indices = + ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices); - vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE ); + vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK | + VBO_SAVE_PRIM_NO_CURRENT_UPDATE)); switch (type) { case GL_UNSIGNED_BYTE: - for (i = 0 ; i < count ; i++) - CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] )); + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (((GLubyte *) indices)[i])); break; case GL_UNSIGNED_SHORT: - for (i = 0 ; i < count ; i++) - CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] )); + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (((GLushort *) indices)[i])); break; case GL_UNSIGNED_INT: - for (i = 0 ; i < count ; i++) - CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] )); + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (((GLuint *) indices)[i])); break; default: - _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)"); break; } CALL_End(GET_DISPATCH(), ()); - _ae_unmap_vbos( ctx ); + _ae_unmap_vbos(ctx); } -static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode, - GLuint start, GLuint end, - GLsizei count, GLenum type, - const GLvoid *indices) + +static void GLAPIENTRY +_save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid * indices) { GET_CURRENT_CONTEXT(ctx); - if (_mesa_validate_DrawRangeElements( ctx, mode, - start, end, - count, type, indices, 0 )) - _save_OBE_DrawElements( mode, count, type, indices ); + if (_mesa_validate_DrawRangeElements(ctx, mode, + start, end, count, type, indices, 0)) { + _save_OBE_DrawElements(mode, count, type, indices); + } } - - - -static void _save_vtxfmt_init( struct gl_context *ctx ) +static void +_save_vtxfmt_init(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLvertexformat *vfmt = &save->vtxfmt; @@ -1073,7 +1153,7 @@ static void _save_vtxfmt_init( struct gl_context *ctx ) vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV; vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV; vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV; - + /* integer-valued */ vfmt->VertexAttribI1i = _save_VertexAttribI1i; vfmt->VertexAttribI2i = _save_VertexAttribI2i; @@ -1093,8 +1173,8 @@ static void _save_vtxfmt_init( struct gl_context *ctx ) vfmt->VertexAttribI4uiv = _save_VertexAttribI4uiv; /* This will all require us to fallback to saving the list as opcodes: - */ - _MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */ + */ + _MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */ _MESA_INIT_EVAL_VTXFMT(vfmt, _save_); @@ -1114,7 +1194,8 @@ static void _save_vtxfmt_init( struct gl_context *ctx ) } -void vbo_save_SaveFlushVertices( struct gl_context *ctx ) +void +vbo_save_SaveFlushVertices(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; @@ -1124,36 +1205,40 @@ void vbo_save_SaveFlushVertices( struct gl_context *ctx ) ctx->Driver.CurrentSavePrimitive <= GL_POLYGON) return; - if (save->vert_count || - save->prim_count) - _save_compile_vertex_list( ctx ); - - _save_copy_to_current( ctx ); - _save_reset_vertex( ctx ); - _save_reset_counters( ctx ); + if (save->vert_count || save->prim_count) + _save_compile_vertex_list(ctx); + + _save_copy_to_current(ctx); + _save_reset_vertex(ctx); + _save_reset_counters(ctx); ctx->Driver.SaveNeedFlush = 0; } -void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode ) + +void +vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode) { struct vbo_save_context *save = &vbo_context(ctx)->save; - (void) list; (void) mode; + (void) list; + (void) mode; if (!save->prim_store) - save->prim_store = alloc_prim_store( ctx ); - - if (!save->vertex_store) - save->vertex_store = alloc_vertex_store( ctx ); - - save->buffer_ptr = map_vertex_store( ctx, save->vertex_store ); - - _save_reset_vertex( ctx ); - _save_reset_counters( ctx ); + save->prim_store = alloc_prim_store(ctx); + + if (!save->vertex_store) + save->vertex_store = alloc_vertex_store(ctx); + + save->buffer_ptr = map_vertex_store(ctx, save->vertex_store); + + _save_reset_vertex(ctx); + _save_reset_counters(ctx); ctx->Driver.SaveNeedFlush = 0; } -void vbo_save_EndList( struct gl_context *ctx ) + +void +vbo_save_EndList(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; @@ -1165,38 +1250,41 @@ void vbo_save_EndList( struct gl_context *ctx ) GLint i = save->prim_count - 1; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; save->prim[i].end = 0; - save->prim[i].count = (save->vert_count - - save->prim[i].start); + save->prim[i].count = (save->vert_count - save->prim[i].start); } /* Make sure this vertex list gets replayed by the "loopback" * mechanism: */ save->dangling_attr_ref = 1; - vbo_save_SaveFlushVertices( ctx ); + vbo_save_SaveFlushVertices(ctx); /* Swap out this vertex format while outside begin/end. Any color, * etc. received between here and the next begin will be compiled * as opcodes. - */ - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); + */ + _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } - unmap_vertex_store( ctx, save->vertex_store ); + unmap_vertex_store(ctx, save->vertex_store); assert(save->vertex_size == 0); } - -void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *dlist ) + + +void +vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *dlist) { struct vbo_save_context *save = &vbo_context(ctx)->save; save->replay_flags |= dlist->Flags; } -void vbo_save_EndCallList( struct gl_context *ctx ) + +void +vbo_save_EndCallList(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; - + if (ctx->ListState.CallDepth == 1) { /* This is correct: want to keep only the VBO_SAVE_FALLBACK * flag, if it is set: @@ -1206,16 +1294,17 @@ void vbo_save_EndCallList( struct gl_context *ctx ) } -static void vbo_destroy_vertex_list( struct gl_context *ctx, void *data ) +static void +vbo_destroy_vertex_list(struct gl_context *ctx, void *data) { - struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data; + struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; (void) ctx; - if ( --node->vertex_store->refcount == 0 ) - free_vertex_store( ctx, node->vertex_store ); + if (--node->vertex_store->refcount == 0) + free_vertex_store(ctx, node->vertex_store); - if ( --node->prim_store->refcount == 0 ) - FREE( node->prim_store ); + if (--node->prim_store->refcount == 0) + FREE(node->prim_store); if (node->current_data) { FREE(node->current_data); @@ -1224,32 +1313,32 @@ static void vbo_destroy_vertex_list( struct gl_context *ctx, void *data ) } -static void vbo_print_vertex_list( struct gl_context *ctx, void *data ) +static void +vbo_print_vertex_list(struct gl_context *ctx, void *data) { - struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data; + struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; GLuint i; (void) ctx; printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n", - node->count, - node->prim_count, - node->vertex_size); + node->count, node->prim_count, node->vertex_size); - for (i = 0 ; i < node->prim_count ; i++) { + for (i = 0; i < node->prim_count; i++) { struct _mesa_prim *prim = &node->prim[i]; _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n", - i, - _mesa_lookup_prim_by_nr(prim->mode), - prim->weak ? " (weak)" : "", - prim->start, - prim->start + prim->count, - (prim->begin) ? "BEGIN" : "(wrap)", - (prim->end) ? "END" : "(wrap)"); + i, + _mesa_lookup_prim_by_nr(prim->mode), + prim->weak ? " (weak)" : "", + prim->start, + prim->start + prim->count, + (prim->begin) ? "BEGIN" : "(wrap)", + (prim->end) ? "END" : "(wrap)"); } } -static void _save_current_init( struct gl_context *ctx ) +static void +_save_current_init(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i; @@ -1269,25 +1358,27 @@ static void _save_current_init( struct gl_context *ctx ) } } + /** * Initialize the display list compiler */ -void vbo_save_api_init( struct vbo_save_context *save ) +void +vbo_save_api_init(struct vbo_save_context *save) { struct gl_context *ctx = save->ctx; GLuint i; save->opcode_vertex_list = - _mesa_dlist_alloc_opcode( ctx, - sizeof(struct vbo_save_vertex_list), - vbo_save_playback_vertex_list, - vbo_destroy_vertex_list, - vbo_print_vertex_list ); + _mesa_dlist_alloc_opcode(ctx, + sizeof(struct vbo_save_vertex_list), + vbo_save_playback_vertex_list, + vbo_destroy_vertex_list, + vbo_print_vertex_list); ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; - _save_vtxfmt_init( ctx ); - _save_current_init( ctx ); + _save_vtxfmt_init(ctx); + _save_current_init(ctx); /* These will actually get set again when binding/drawing */ for (i = 0; i < VBO_ATTRIB_MAX; i++) @@ -1301,9 +1392,11 @@ void vbo_save_api_init( struct vbo_save_context *save ) ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; /* loops back into _save_OBE_DrawElements */ - ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements; - ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex; - _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); + ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = + _mesa_noop_MultiDrawElements; + ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = + _mesa_noop_MultiDrawElementsBaseVertex; + _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); } diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index d0f627a35..a37af73e0 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -1,308 +1,310 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.2
- *
- * Copyright (C) 1999-2008 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.
- */
-
-/* Author:
- * Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/imports.h"
-#include "main/mfeatures.h"
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/light.h"
-#include "main/state.h"
-
-#include "vbo_context.h"
-
-
-#if FEATURE_dlist
-
-
-/**
- * After playback, copy everything but the position from the
- * last vertex to the saved state
- */
-static void
-_playback_copy_to_current(struct gl_context *ctx,
- const struct vbo_save_vertex_list *node)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- GLfloat vertex[VBO_ATTRIB_MAX * 4];
- GLfloat *data;
- GLuint i, offset;
-
- if (node->current_size == 0)
- return;
-
- if (node->current_data) {
- data = node->current_data;
- }
- else {
- data = vertex;
-
- if (node->count)
- offset = (node->buffer_offset +
- (node->count-1) * node->vertex_size * sizeof(GLfloat));
- else
- offset = node->buffer_offset;
-
- ctx->Driver.GetBufferSubData( ctx, 0, offset,
- node->vertex_size * sizeof(GLfloat),
- data, node->vertex_store->bufferobj );
-
- data += node->attrsz[0]; /* skip vertex position */
- }
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
- if (node->attrsz[i]) {
- GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
- GLfloat tmp[4];
-
- COPY_CLEAN_4V(tmp,
- node->attrsz[i],
- data);
-
- if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
- memcpy(current, tmp, 4 * sizeof(GLfloat));
-
- vbo->currval[i].Size = node->attrsz[i];
- assert(vbo->currval[i].Type == GL_FLOAT);
- vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
-
- if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
- i <= VBO_ATTRIB_LAST_MATERIAL)
- ctx->NewState |= _NEW_LIGHT;
-
- ctx->NewState |= _NEW_CURRENT_ATTRIB;
- }
-
- data += node->attrsz[i];
- }
- }
-
- /* Colormaterial -- this kindof sucks.
- */
- if (ctx->Light.ColorMaterialEnabled) {
- _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
- }
-
- /* CurrentExecPrimitive
- */
- if (node->prim_count) {
- const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
- if (prim->end)
- ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
- else
- ctx->Driver.CurrentExecPrimitive = prim->mode;
- }
-}
-
-
-
-/**
- * Treat the vertex storage as a VBO, define vertex arrays pointing
- * into it:
- */
-static void vbo_bind_vertex_list(struct gl_context *ctx,
- const struct vbo_save_vertex_list *node)
-{
- struct vbo_context *vbo = vbo_context(ctx);
- struct vbo_save_context *save = &vbo->save;
- struct gl_client_array *arrays = save->arrays;
- GLuint buffer_offset = 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.
- */
- switch (get_program_mode(ctx)) {
- case VP_NONE:
- for (attr = 0; attr < 16; attr++) {
- save->inputs[attr] = &vbo->legacy_currval[attr];
- }
- for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
- save->inputs[attr + 16] = &vbo->mat_currval[attr];
- }
- map = vbo->map_vp_none;
- break;
- case VP_NV:
- case VP_ARB:
- /* The aliasing of attributes for NV vertex programs has already
- * occurred. NV vertex programs cannot access material values,
- * nor attributes greater than VERT_ATTRIB_TEX7.
- */
- for (attr = 0; attr < 16; attr++) {
- save->inputs[attr] = &vbo->legacy_currval[attr];
- save->inputs[attr + 16] = &vbo->generic_currval[attr];
- }
- map = vbo->map_vp_arb;
-
- /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
- * In that case we effectively need to route the data from
- * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
- */
- if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
- (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
- save->inputs[16] = save->inputs[0];
- node_attrsz[16] = node_attrsz[0];
- node_attrsz[0] = 0;
- }
- break;
- default:
- assert(0);
- }
-
- for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
- const GLuint src = map[attr];
-
- if (node_attrsz[src]) {
- /* override the default array set above */
- save->inputs[attr] = &arrays[attr];
-
- arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
- arrays[attr].Size = node->attrsz[src];
- arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
- arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
- arrays[attr].Type = GL_FLOAT;
- arrays[attr].Format = GL_RGBA;
- arrays[attr].Enabled = 1;
- arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
- _mesa_reference_buffer_object(ctx,
- &arrays[attr].BufferObj,
- node->vertex_store->bufferobj);
- arrays[attr]._MaxElement = node->count; /* ??? */
-
- assert(arrays[attr].BufferObj->Name);
-
- buffer_offset += node->attrsz[src] * sizeof(GLfloat);
- varying_inputs |= 1<<attr;
- ctx->NewState |= _NEW_ARRAY;
- }
- }
-
- _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-}
-
-
-static void
-vbo_save_loopback_vertex_list(struct gl_context *ctx,
- const struct vbo_save_vertex_list *list)
-{
- const char *buffer = ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB,
- GL_READ_ONLY, /* ? */
- list->vertex_store->bufferobj);
-
- vbo_loopback_vertex_list(ctx,
- (const GLfloat *)(buffer + list->buffer_offset),
- list->attrsz,
- list->prim,
- list->prim_count,
- list->wrap_count,
- list->vertex_size);
-
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
- list->vertex_store->bufferobj);
-}
-
-
-/**
- * Execute the buffer and save copied verts.
- * This is called from the display list code when executing
- * a drawing command.
- */
-void
-vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
-{
- const struct vbo_save_vertex_list *node =
- (const struct vbo_save_vertex_list *) data;
- struct vbo_save_context *save = &vbo_context(ctx)->save;
-
- FLUSH_CURRENT(ctx, 0);
-
- if (node->prim_count > 0 && node->count > 0) {
-
- if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
- node->prim[0].begin) {
-
- /* Degenerate case: list is called inside begin/end pair and
- * includes operations such as glBegin or glDrawArrays.
- */
- if (0)
- printf("displaylist recursive begin");
-
- vbo_save_loopback_vertex_list( ctx, node );
- return;
- }
- else if (save->replay_flags) {
- /* Various degnerate cases: translate into immediate mode
- * calls rather than trying to execute in place.
- */
- vbo_save_loopback_vertex_list( ctx, node );
- return;
- }
-
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- /* XXX also need to check if shader enabled, but invalid */
- if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
- (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBegin (invalid vertex/fragment program)");
- return;
- }
-
- vbo_bind_vertex_list( ctx, node );
-
- /* Again...
- */
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
- vbo_context(ctx)->draw_prims(ctx,
- save->inputs,
- node->prim,
- node->prim_count,
- NULL,
- GL_TRUE,
- 0, /* Node is a VBO, so this is ok */
- node->count - 1);
- }
-
- /* Copy to current?
- */
- _playback_copy_to_current( ctx, node );
-}
-
-
-#endif /* FEATURE_dlist */
+/* + * Mesa 3-D graphics library + * Version: 7.2 + * + * Copyright (C) 1999-2008 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. + */ + +/* Author: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "main/glheader.h" +#include "main/bufferobj.h" +#include "main/context.h" +#include "main/imports.h" +#include "main/mfeatures.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "main/light.h" +#include "main/state.h" + +#include "vbo_context.h" + + +#if FEATURE_dlist + + +/** + * After playback, copy everything but the position from the + * last vertex to the saved state + */ +static void +_playback_copy_to_current(struct gl_context *ctx, + const struct vbo_save_vertex_list *node) +{ + struct vbo_context *vbo = vbo_context(ctx); + GLfloat vertex[VBO_ATTRIB_MAX * 4]; + GLfloat *data; + GLuint i, offset; + + if (node->current_size == 0) + return; + + if (node->current_data) { + data = node->current_data; + } + else { + data = vertex; + + if (node->count) + offset = (node->buffer_offset + + (node->count-1) * node->vertex_size * sizeof(GLfloat)); + else + offset = node->buffer_offset; + + ctx->Driver.GetBufferSubData( ctx, 0, offset, + node->vertex_size * sizeof(GLfloat), + data, node->vertex_store->bufferobj ); + + data += node->attrsz[0]; /* skip vertex position */ + } + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + if (node->attrsz[i]) { + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + GLfloat tmp[4]; + + COPY_CLEAN_4V(tmp, + node->attrsz[i], + data); + + if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) { + memcpy(current, tmp, 4 * sizeof(GLfloat)); + + vbo->currval[i].Size = node->attrsz[i]; + assert(vbo->currval[i].Type == GL_FLOAT); + vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat); + + if (i >= VBO_ATTRIB_FIRST_MATERIAL && + i <= VBO_ATTRIB_LAST_MATERIAL) + ctx->NewState |= _NEW_LIGHT; + + ctx->NewState |= _NEW_CURRENT_ATTRIB; + } + + data += node->attrsz[i]; + } + } + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); + } + + /* CurrentExecPrimitive + */ + if (node->prim_count) { + const struct _mesa_prim *prim = &node->prim[node->prim_count - 1]; + if (prim->end) + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + else + ctx->Driver.CurrentExecPrimitive = prim->mode; + } +} + + + +/** + * Treat the vertex storage as a VBO, define vertex arrays pointing + * into it: + */ +static void vbo_bind_vertex_list(struct gl_context *ctx, + const struct vbo_save_vertex_list *node) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_save_context *save = &vbo->save; + struct gl_client_array *arrays = save->arrays; + GLuint buffer_offset = 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. + */ + switch (get_program_mode(ctx)) { + case VP_NONE: + for (attr = 0; attr < 16; attr++) { + save->inputs[attr] = &vbo->legacy_currval[attr]; + } + for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { + save->inputs[attr + 16] = &vbo->mat_currval[attr]; + } + map = vbo->map_vp_none; + break; + case VP_NV: + case VP_ARB: + /* The aliasing of attributes for NV vertex programs has already + * occurred. NV vertex programs cannot access material values, + * nor attributes greater than VERT_ATTRIB_TEX7. + */ + for (attr = 0; attr < 16; attr++) { + save->inputs[attr] = &vbo->legacy_currval[attr]; + save->inputs[attr + 16] = &vbo->generic_currval[attr]; + } + map = vbo->map_vp_arb; + + /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. + * In that case we effectively need to route the data from + * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. + */ + if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && + (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { + save->inputs[16] = save->inputs[0]; + node_attrsz[16] = node_attrsz[0]; + node_attrsz[0] = 0; + } + break; + default: + assert(0); + } + + for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { + const GLuint src = map[attr]; + + if (node_attrsz[src]) { + /* override the default array set above */ + save->inputs[attr] = &arrays[attr]; + + arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; + arrays[attr].Size = node->attrsz[src]; + arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); + arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); + arrays[attr].Type = GL_FLOAT; + arrays[attr].Format = GL_RGBA; + arrays[attr].Enabled = 1; + arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); + _mesa_reference_buffer_object(ctx, + &arrays[attr].BufferObj, + node->vertex_store->bufferobj); + arrays[attr]._MaxElement = node->count; /* ??? */ + + assert(arrays[attr].BufferObj->Name); + + buffer_offset += node->attrsz[src] * sizeof(GLfloat); + varying_inputs |= 1<<attr; + ctx->NewState |= _NEW_ARRAY; + } + } + + _mesa_set_varying_vp_inputs( ctx, varying_inputs ); +} + + +static void +vbo_save_loopback_vertex_list(struct gl_context *ctx, + const struct vbo_save_vertex_list *list) +{ + const char *buffer = ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, + GL_READ_ONLY, /* ? */ + list->vertex_store->bufferobj); + + vbo_loopback_vertex_list(ctx, + (const GLfloat *)(buffer + list->buffer_offset), + list->attrsz, + list->prim, + list->prim_count, + list->wrap_count, + list->vertex_size); + + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, + list->vertex_store->bufferobj); +} + + +/** + * Execute the buffer and save copied verts. + * This is called from the display list code when executing + * a drawing command. + */ +void +vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) +{ + const struct vbo_save_vertex_list *node = + (const struct vbo_save_vertex_list *) data; + struct vbo_save_context *save = &vbo_context(ctx)->save; + + FLUSH_CURRENT(ctx, 0); + + if (node->prim_count > 0) { + + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && + node->prim[0].begin) { + + /* Degenerate case: list is called inside begin/end pair and + * includes operations such as glBegin or glDrawArrays. + */ + if (0) + printf("displaylist recursive begin"); + + vbo_save_loopback_vertex_list( ctx, node ); + return; + } + else if (save->replay_flags) { + /* Various degnerate cases: translate into immediate mode + * calls rather than trying to execute in place. + */ + vbo_save_loopback_vertex_list( ctx, node ); + return; + } + + if (ctx->NewState) + _mesa_update_state( ctx ); + + /* XXX also need to check if shader enabled, but invalid */ + if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || + (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBegin (invalid vertex/fragment program)"); + return; + } + + vbo_bind_vertex_list( ctx, node ); + + /* Again... + */ + if (ctx->NewState) + _mesa_update_state( ctx ); + + if (node->count > 0) { + vbo_context(ctx)->draw_prims(ctx, + save->inputs, + node->prim, + node->prim_count, + NULL, + GL_TRUE, + 0, /* Node is a VBO, so this is ok */ + node->count - 1); + } + } + + /* Copy to current? + */ + _playback_copy_to_current( ctx, node ); +} + + +#endif /* FEATURE_dlist */ |