diff options
author | marha <marha@users.sourceforge.net> | 2011-06-09 09:27:21 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2011-06-09 09:27:21 +0200 |
commit | 0de14292c4fac98f91105baf9cc16e58f25d4d77 (patch) | |
tree | 1704165c3d7f05bde08dc6d3d52ee33aed0f270f /mesalib/src/mesa/vbo | |
parent | 637bc31135b378ea9521b5a93b14bdce482da209 (diff) | |
parent | 0a9d2abef2e6fac5d52556969655a62711df6418 (diff) | |
download | vcxsrv-0de14292c4fac98f91105baf9cc16e58f25d4d77.tar.gz vcxsrv-0de14292c4fac98f91105baf9cc16e58f25d4d77.tar.bz2 vcxsrv-0de14292c4fac98f91105baf9cc16e58f25d4d77.zip |
Merge remote-tracking branch 'origin/released'
Conflicts:
mesalib/include/GL/internal/dri_interface.h
mesalib/src/gallium/auxiliary/util/u_math.h
mesalib/src/mapi/glapi/gen/Makefile
mesalib/src/mapi/glapi/gen/gl_table.py
mesalib/src/mesa/SConscript
mesalib/src/mesa/main/dlist.c
mesalib/src/mesa/main/es_generator.py
mesalib/src/mesa/main/imports.h
mesalib/src/mesa/main/teximage.c
mesalib/src/mesa/main/uniforms.c
mesalib/src/mesa/state_tracker/st_draw.c
mesalib/src/mesa/state_tracker/st_program.c
mesalib/src/mesa/vbo/vbo_save_api.c
xorg-server/xkeyboard-config/configure.in
xorg-server/xkeyboard-config/rules/Makefile.am
xorg-server/xkeyboard-config/rules/base.xml.in
xorg-server/xkeyboard-config/symbols/cz
xorg-server/xkeyboard-config/symbols/in
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 52418788d..0b8b7dac8 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 */ |