From fd12b37dbada6f945a94b93ecf332d0b6a8eef06 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Sun, 29 Oct 2006 09:46:11 +0000 Subject: Checkpoint of new vbo-building code. Currently builds regular arrays rather than VBO's - VBOs are easy but need to look closer at the driver interface. The trivial/tri demo works. --- src/mesa/vbo/vbo_attrib.h | 131 +++++ src/mesa/vbo/vbo_attrib_tmp.h | 485 ++++++++++++++++ src/mesa/vbo/vbo_context.c | 86 +++ src/mesa/vbo/vbo_context.h | 101 ++++ src/mesa/vbo/vbo_exec.c | 227 ++++++++ src/mesa/vbo/vbo_exec.h | 175 ++++++ src/mesa/vbo/vbo_exec_api.c | 716 +++++++++++++++++++++++ src/mesa/vbo/vbo_exec_array.c | 367 ++++++++++++ src/mesa/vbo/vbo_exec_draw.c | 199 +++++++ src/mesa/vbo/vbo_exec_eval.c | 255 +++++++++ src/mesa/vbo/vbo_save.c | 94 +++ src/mesa/vbo/vbo_save.h | 180 ++++++ src/mesa/vbo/vbo_save_api.c | 1160 ++++++++++++++++++++++++++++++++++++++ src/mesa/vbo/vbo_save_draw.c | 202 +++++++ src/mesa/vbo/vbo_save_loopback.c | 327 +++++++++++ 15 files changed, 4705 insertions(+) create mode 100644 src/mesa/vbo/vbo_attrib.h create mode 100644 src/mesa/vbo/vbo_attrib_tmp.h create mode 100644 src/mesa/vbo/vbo_context.c create mode 100644 src/mesa/vbo/vbo_context.h create mode 100644 src/mesa/vbo/vbo_exec.c create mode 100644 src/mesa/vbo/vbo_exec.h create mode 100644 src/mesa/vbo/vbo_exec_api.c create mode 100644 src/mesa/vbo/vbo_exec_array.c create mode 100644 src/mesa/vbo/vbo_exec_draw.c create mode 100644 src/mesa/vbo/vbo_exec_eval.c create mode 100644 src/mesa/vbo/vbo_save.c create mode 100644 src/mesa/vbo/vbo_save.h create mode 100644 src/mesa/vbo/vbo_save_api.c create mode 100644 src/mesa/vbo/vbo_save_draw.c create mode 100644 src/mesa/vbo/vbo_save_loopback.c (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_attrib.h b/src/mesa/vbo/vbo_attrib.h new file mode 100644 index 00000000000..caedbd5ea69 --- /dev/null +++ b/src/mesa/vbo/vbo_attrib.h @@ -0,0 +1,131 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + 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 (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 NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + **********************************************************************/ + /* + * Authors: + * Keith Whitwell + */ + +#ifndef VBO_ATTRIB_H +#define VBO_ATTRIB_H + + +/* + * Note: The first attributes match the VERT_ATTRIB_* definitions + * in mtypes.h. However, the tnl module has additional attributes + * for materials, color indexes, edge flags, etc. + */ +/* Although it's nice to use these as bit indexes in a DWORD flag, we + * could manage without if necessary. Another limit currently is the + * number of bits allocated for these numbers in places like vertex + * program instruction formats and register layouts. + */ +enum { + VBO_ATTRIB_POS = 0, + VBO_ATTRIB_WEIGHT = 1, + VBO_ATTRIB_NORMAL = 2, + VBO_ATTRIB_COLOR0 = 3, + VBO_ATTRIB_COLOR1 = 4, + VBO_ATTRIB_FOG = 5, + VBO_ATTRIB_INDEX = 6, + VBO_ATTRIB_EDGEFLAG = 7, + VBO_ATTRIB_TEX0 = 8, + VBO_ATTRIB_TEX1 = 9, + VBO_ATTRIB_TEX2 = 10, + VBO_ATTRIB_TEX3 = 11, + VBO_ATTRIB_TEX4 = 12, + VBO_ATTRIB_TEX5 = 13, + VBO_ATTRIB_TEX6 = 14, + VBO_ATTRIB_TEX7 = 15, + + VBO_ATTRIB_GENERIC0 = 16, /* Not used? */ + VBO_ATTRIB_GENERIC1 = 17, + VBO_ATTRIB_GENERIC2 = 18, + VBO_ATTRIB_GENERIC3 = 19, + VBO_ATTRIB_GENERIC4 = 20, + VBO_ATTRIB_GENERIC5 = 21, + VBO_ATTRIB_GENERIC6 = 22, + VBO_ATTRIB_GENERIC7 = 23, + VBO_ATTRIB_GENERIC8 = 24, + VBO_ATTRIB_GENERIC9 = 25, + VBO_ATTRIB_GENERIC10 = 26, + VBO_ATTRIB_GENERIC11 = 27, + VBO_ATTRIB_GENERIC12 = 28, + VBO_ATTRIB_GENERIC13 = 29, + VBO_ATTRIB_GENERIC14 = 30, + VBO_ATTRIB_GENERIC15 = 31, + + /* XXX: in the vertex program InputsRead flag, we alias + * materials and generics and use knowledge about the program + * (whether it is a fixed-function emulation) to + * differentiate. Here we must keep them apart instead. + */ + VBO_ATTRIB_MAT_FRONT_AMBIENT = 32, + VBO_ATTRIB_MAT_BACK_AMBIENT = 33, + VBO_ATTRIB_MAT_FRONT_DIFFUSE = 34, + VBO_ATTRIB_MAT_BACK_DIFFUSE = 35, + VBO_ATTRIB_MAT_FRONT_SPECULAR = 36, + VBO_ATTRIB_MAT_BACK_SPECULAR = 37, + VBO_ATTRIB_MAT_FRONT_EMISSION = 38, + VBO_ATTRIB_MAT_BACK_EMISSION = 39, + VBO_ATTRIB_MAT_FRONT_SHININESS = 40, + VBO_ATTRIB_MAT_BACK_SHININESS = 41, + VBO_ATTRIB_MAT_FRONT_INDEXES = 42, + VBO_ATTRIB_MAT_BACK_INDEXES = 43, + + VBO_ATTRIB_MAX = 44 +}; + +#define VBO_ATTRIB_FIRST_MATERIAL VBO_ATTRIB_MAT_FRONT_AMBIENT + +#define VBO_MAX_COPIED_VERTS 3 + +struct _mesa_prim { + GLuint mode:8; + GLuint indexed:1; + GLuint begin:1; + GLuint end:1; + GLuint weak:1; + GLuint pad:20; + + GLuint start; + GLuint count; +}; + +/* Would like to call this a "vbo_index_buffer", but this would be + * confusing as the indices are not neccessarily yet in a non-null + * buffer object. + */ +struct _mesa_index_buffer { + GLuint count; + GLenum type; + struct gl_buffer_object *obj; + const void *ptr; + GLuint rebase; +}; + + +#endif diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h new file mode 100644 index 00000000000..72a8b04aca1 --- /dev/null +++ b/src/mesa/vbo/vbo_attrib_tmp.h @@ -0,0 +1,485 @@ +/************************************************************************** + +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. + +**************************************************************************/ + +#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 ) +#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 ) +#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 ) +#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) + +#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 ) +#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 ) +#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 ) +#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W ) + +#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] ) + +static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2F( VBO_ATTRIB_POS, x, y ); +} + +static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_POS, x, y, z ); +} + +static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_POS, x, y, z, w ); +} + +static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(TexCoord1f)( GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_TEX0, x ); +} + +static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord2f)( GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2F( VBO_ATTRIB_TEX0, x, y ); +} + +static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_TEX0, x, y, z ); +} + +static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_TEX0, x, y, z, w ); +} + +static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_NORMAL, x, y, z ); +} + +static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_NORMAL, v ); +} + +static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_FOG, x ); +} + +static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_FOG, v ); +} + +static void GLAPIENTRY TAG(Color3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_COLOR0, x, y, z ); +} + +static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY TAG(Color4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_COLOR0, x, y, z, w ); +} + +static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_COLOR1, x, y, z ); +} + +static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_COLOR1, v ); +} + + +static void GLAPIENTRY TAG(EdgeFlag)( GLboolean b ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_EDGEFLAG, (GLfloat)b ); +} + +static void GLAPIENTRY TAG(Indexf)( GLfloat f ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_INDEX, f ); +} + +static void GLAPIENTRY TAG(Indexfv)( const GLfloat *f ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_INDEX, f ); +} + + +static void GLAPIENTRY TAG(MultiTexCoord1f)( GLenum target, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR1F( attr, x ); +} + +static void GLAPIENTRY TAG(MultiTexCoord1fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR1FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord2f)( GLenum target, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR2F( attr, x, y ); +} + +static void GLAPIENTRY TAG(MultiTexCoord2fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR2FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord3f)( GLenum target, GLfloat x, GLfloat y, + GLfloat z) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR3F( attr, x, y, z ); +} + +static void GLAPIENTRY TAG(MultiTexCoord3fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR3FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord4f)( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR4F( attr, x, y, z, w ); +} + +static void GLAPIENTRY TAG(MultiTexCoord4fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR4FV( attr, v ); +} + + +static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR1F(0, x); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR1F(VBO_ATTRIB_GENERIC0 + index, x); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR1FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x, + GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR2F(0, x, y); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR2FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR3F(0, x, y, z); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR3FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR4F(0, x, y, z, w); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR4FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + + +/* Although we don't export NV_vertex_program, these entrypoints are + * used by the display list and other code specifically because of + * their property of aliasing with other attributes. + */ +static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR1F(index, x); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR1FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x, + GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR2F(index, x, y); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR2FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR3F(index, x, y, z); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR3FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR4F(index, x, y, z, w); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR4FV(index, v); +} + + +#define MAT( ATTR, N, face, params ) \ +do { \ + if (face != GL_BACK) \ + MAT_ATTR( ATTR, N, params ); /* front */ \ + if (face != GL_FRONT) \ + MAT_ATTR( ATTR + 1, N, params ); /* back */ \ +} while (0) + + +/* Colormaterial conflicts are dealt with later. + */ +static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname, + const GLfloat *params ) +{ + GET_CURRENT_CONTEXT( ctx ); + switch (pname) { + case GL_EMISSION: + MAT( VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); + break; + case GL_AMBIENT: + MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + break; + case GL_DIFFUSE: + MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + case GL_SPECULAR: + MAT( VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); + break; + case GL_SHININESS: + MAT( VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); + break; + case GL_COLOR_INDEXES: + MAT( VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); + break; + case GL_AMBIENT_AND_DIFFUSE: + MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + default: + ERROR(); + return; + } +} + + +#undef ATTR1FV +#undef ATTR2FV +#undef ATTR3FV +#undef ATTR4FV + +#undef ATTR1F +#undef ATTR2F +#undef ATTR3F +#undef ATTR4F + +#undef MAT +#undef MAT_ATTR diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c new file mode 100644 index 00000000000..5f28e6b0e07 --- /dev/null +++ b/src/mesa/vbo/vbo_context.c @@ -0,0 +1,86 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +#include "mtypes.h" +#include "vbo_context.h" +#include "imports.h" +#include "api_arrayelt.h" + +/* Reach out and grab this to use as the default: + */ +extern void _tnl_draw_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index ); + +GLboolean _vbo_CreateContext( GLcontext *ctx ) +{ + struct vbo_context *vbo = CALLOC_STRUCT(vbo_context); + + ctx->swtnl_im = (void *)vbo; + + /* Initialize the arrayelt helper + */ + if (!ctx->aelt_context && + !_ae_create_context( ctx )) { + return GL_FALSE; + } + + /* Hook our functions into exec and compile dispatch tables. These + * will pretty much be permanently installed, which means that the + * vtxfmt mechanism can be removed now. + */ + vbo_exec_init( ctx ); + vbo_save_init( ctx ); + + /* By default: + */ + vbo->draw_prims = _tnl_draw_prims; + + return GL_TRUE; +} + +void vbo_save_invalidate_state( GLcontext *ctx, GLuint new_state ) +{ + _ae_invalidate_state(ctx, new_state); +} + + +void _vbo_DestroyContext( GLcontext *ctx ) +{ + if (ctx->aelt_context) { + _ae_destroy_context( ctx ); + ctx->aelt_context = NULL; + } + + FREE(vbo_context(ctx)); + ctx->swtnl_im = NULL; + +} diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h new file mode 100644 index 00000000000..6b0f14d70ea --- /dev/null +++ b/src/mesa/vbo/vbo_context.h @@ -0,0 +1,101 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +/** + * \mainpage The VBO builder module + * + * This module hooks into the GL dispatch table and catches all vertex + * building and drawing commands, such as glVertex3f, glBegin and + * glDrawArrays. The module stores all incoming vertex data as arrays + * in GL vertex buffer objects (VBOs), and translates all drawing + * commands into calls to a driver supplied DrawPrimitives() callback. + * + * The module captures both immediate mode and display list drawing, + * and manages the allocation, reference counting and deallocation of + * vertex buffer objects itself. + * + * The DrawPrimitives() callback can be either implemented by the + * driver itself or hooked to the tnl module's _tnl_draw_primitives() + * function for hardware without tnl capablilties or during fallbacks. + */ + + +#ifndef _VBO_CONTEXT_H +#define _VBO_CONTEXT_H + +#include "vbo_attrib.h" +#include "vbo_save.h" +#include "vbo_exec.h" + +GLboolean _vbo_CreateContext( GLcontext *ctx ); +void _vbo_DestroyContext( GLcontext *ctx ); + + +struct vbo_context { + struct vbo_exec_context exec; + struct vbo_save_context save; + + /* Callback into the driver. This must always succeed, the driver + * is responsible for initiating any fallback actions required: + */ + void (*draw_prims)( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index ); +}; + + +static INLINE struct vbo_context *vbo_context(GLcontext *ctx) +{ + return (struct vbo_context *)(ctx->swtnl_im); +} + +enum { + VP_NONE = 1, + VP_NV, + VP_ARB +}; + +static INLINE GLuint get_program_mode( GLcontext *ctx ) +{ + if (!ctx->VertexProgram._Enabled) + return VP_NONE; + else if (ctx->VertexProgram.Current->IsNVProgram) + return VP_NV; + else + return VP_ARB; +} + + +#endif diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c new file mode 100644 index 00000000000..4499803b8c7 --- /dev/null +++ b/src/mesa/vbo/vbo_exec.c @@ -0,0 +1,227 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + + +#include "api_arrayelt.h" +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" +#include "dlist.h" +#include "vtxfmt.h" + +#include "vbo_context.h" + + +#define NR_LEGACY_ATTRIBS 16 +#define NR_GENERIC_ATTRIBS 16 +#define NR_MAT_ATTRIBS 12 + +static void init_legacy_currval(GLcontext *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + struct gl_client_array *arrays = exec->legacy_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_LEGACY_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + switch (i) { + case VBO_ATTRIB_EDGEFLAG: + cl->Type = GL_UNSIGNED_BYTE; + cl->Ptr = (const void *)&ctx->Current.EdgeFlag; + break; + case VBO_ATTRIB_INDEX: + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)&ctx->Current.Index; + break; + default: + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[i]; + break; + } + + /* This will have to be determined at runtime: + */ + cl->Size = 1; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_generic_currval(GLcontext *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + struct gl_client_array *arrays = exec->generic_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + + for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* This will have to be determined at runtime: + */ + cl->Size = 1; + + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_mat_currval(GLcontext *ctx) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + struct gl_client_array *arrays = exec->mat_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* Size is fixed for the material attributes, for others will + * be determined at runtime: + */ + switch (i - VERT_ATTRIB_GENERIC0) { + case MAT_ATTRIB_FRONT_SHININESS: + case MAT_ATTRIB_BACK_SHININESS: + cl->Size = 1; + break; + case MAT_ATTRIB_FRONT_INDEXES: + case MAT_ATTRIB_BACK_INDEXES: + cl->Size = 3; + break; + default: + cl->Size = 4; + break; + } + + if (i < MAT_ATTRIB_MAX) + cl->Ptr = (const void *)ctx->Light.Material.Attrib[i]; + else + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + + cl->Type = GL_FLOAT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +void vbo_exec_init( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + exec->ctx = ctx; + + /* Initialize the arrayelt helper + */ + if (!ctx->aelt_context && + !_ae_create_context( ctx )) + return; + + vbo_exec_vtx_init( exec ); + vbo_exec_array_init( exec ); + + init_legacy_currval( ctx ); + init_generic_currval( ctx ); + init_mat_currval( ctx ); + + ctx->Driver.NeedFlush = 0; + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + ctx->Driver.FlushVertices = vbo_exec_FlushVertices; + + exec->eval.recalculate_maps = 1; +} + + +void vbo_exec_destroy( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (ctx->aelt_context) { + _ae_destroy_context( ctx ); + ctx->aelt_context = NULL; + } + + vbo_exec_vtx_destroy( exec ); + vbo_exec_array_destroy( exec ); +} + +/* Really want to install these callbacks to a central facility to be + * invoked according to the state flags. That will have to wait for a + * mesa rework: + */ +void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (new_state & (_NEW_PROGRAM|_NEW_EVAL)) + exec->eval.recalculate_maps = 1; + + _ae_invalidate_state(ctx, new_state); +} + + +void vbo_exec_wakeup( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + ctx->Driver.FlushVertices = vbo_exec_FlushVertices; + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; + + /* Hook our functions into exec and compile dispatch tables. + */ + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); + + /* Assume we haven't been getting state updates either: + */ + vbo_exec_invalidate_state( ctx, ~0 ); +} + + + diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h new file mode 100644 index 00000000000..4542d2807cd --- /dev/null +++ b/src/mesa/vbo/vbo_exec.h @@ -0,0 +1,175 @@ +/************************************************************************** + +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 + * + */ + +#ifndef __VBO_EXEC_H__ +#define __VBO_EXEC_H__ + +#include "mtypes.h" +#include "vbo_attrib.h" + + +#define VBO_MAX_PRIM 64 + +/* Wierd implementation stuff: + */ +#define VBO_VERT_BUFFER_SIZE (1024*16) /* dwords == 64k */ +#define VBO_MAX_ATTR_CODEGEN 16 +#define ERROR_ATTRIB 16 + + + + +struct vbo_exec_eval1_map { + struct gl_1d_map *map; + GLuint sz; +}; + +struct vbo_exec_eval2_map { + struct gl_2d_map *map; + GLuint sz; +}; + + + +struct vbo_exec_copied_vtx { + GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS]; + GLuint nr; +}; + + +typedef void (*vbo_attrfv_func)( const GLfloat * ); + + +struct vbo_exec_context +{ + GLcontext *ctx; + GLvertexformat vtxfmt; + + struct gl_client_array legacy_currval[16]; + struct gl_client_array generic_currval[16]; + struct gl_client_array mat_currval[16]; + + struct { + struct gl_buffer_object *bufferobj; + GLubyte *buffer_map; + + GLuint vertex_size; + + struct _mesa_prim prim[VBO_MAX_PRIM]; + GLuint prim_count; + + GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */ + + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */ + GLfloat CurrentFloatEdgeFlag; + + GLuint vert_count; + GLuint max_vert; + struct vbo_exec_copied_vtx copied; + + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLubyte active_sz[VBO_ATTRIB_MAX]; + + GLfloat *attrptr[VBO_ATTRIB_MAX]; + struct gl_client_array arrays[VBO_ATTRIB_MAX]; + + /* According to program mode, the values above plus current + * values are squashed down to the 32 attributes passed to the + * vertex program below: + */ + GLuint program_mode; + GLuint enabled_flags; + const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; + } vtx; + + + struct { + GLboolean recalculate_maps; + struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX]; + struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX]; + } eval; + + struct { + GLuint program_mode; + GLuint enabled_flags; + GLuint array_obj; + + /* These just mirror the current arrayobj (todo: make arrayobj + * look like this and remove the mirror): + */ + const struct gl_client_array *legacy_array[16]; + const struct gl_client_array *generic_array[16]; + + /* Arrays and current values manipulated according to program + * mode, etc. These are the attributes as seen by vertex + * programs: + */ + const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; + + + struct gl_buffer_object *index_obj; + } array; +}; + + + +/* External API: + */ +void vbo_exec_init( GLcontext *ctx ); +void vbo_exec_destroy( GLcontext *ctx ); +void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ); +void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ); +void vbo_exec_wakeup( GLcontext *ctx ); + + +/* Internal functions: + */ +void vbo_exec_array_init( struct vbo_exec_context *exec ); +void vbo_exec_array_destroy( struct vbo_exec_context *exec ); + + +void vbo_exec_vtx_init( struct vbo_exec_context *exec ); +void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ); +void vbo_exec_vtx_flush( struct vbo_exec_context *exec ); +void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ); + +void vbo_exec_eval_update( struct vbo_exec_context *exec ); + +void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, + GLfloat u, GLfloat v ); + +void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec, + GLfloat u); + +#endif diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c new file mode 100644 index 00000000000..c764c4d8b63 --- /dev/null +++ b/src/mesa/vbo/vbo_exec_api.c @@ -0,0 +1,716 @@ +/************************************************************************** + +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 + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "vtxfmt.h" +#include "dlist.h" +#include "state.h" +#include "light.h" +#include "api_arrayelt.h" +#include "api_noop.h" +#include "dispatch.h" + +#include "vbo_context.h" + +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.vbptr = (GLfloat *)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 != GL_POLYGON+1) { + 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 ); + 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 != GL_POLYGON+1) { + 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++) { + _mesa_memcpy( exec->vtx.vbptr, data, + exec->vtx.vertex_size * sizeof(GLfloat)); + exec->vtx.vbptr += 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 ) +{ + GLcontext *ctx = exec->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. + */ + COPY_CLEAN_4V(exec->vtx.current[i], + exec->vtx.attrsz[i], + exec->vtx.attrptr[i]); + + /* This triggers rather too much recalculation of Mesa state + * that doesn't get used (eg light positions). + */ + if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && + i <= VBO_ATTRIB_MAT_BACK_INDEXES) + ctx->NewState |= _NEW_LIGHT; + } + } + + /* color index is special (it's not a float[4] so COPY_CLEAN_4V above + * will trash adjacent memory!) + */ + if (exec->vtx.attrsz[VBO_ATTRIB_INDEX]) { + ctx->Current.Index = exec->vtx.attrptr[VBO_ATTRIB_INDEX][0]; + } + + /* Edgeflag requires additional treatment: + */ + if (exec->vtx.attrsz[VBO_ATTRIB_EDGEFLAG]) { + ctx->Current.EdgeFlag = (exec->vtx.CurrentFloatEdgeFlag == 1.0); + } + + /* 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]); + } + + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} + + +static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLint i; + + /* Edgeflag requires additional treatment: + */ + exec->vtx.CurrentFloatEdgeFlag = + (GLfloat)ctx->Current.EdgeFlag; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) + switch (exec->vtx.attrsz[i]) { + case 4: exec->vtx.attrptr[i][3] = exec->vtx.current[i][3]; + case 3: exec->vtx.attrptr[i][2] = exec->vtx.current[i][2]; + case 2: exec->vtx.attrptr[i][1] = exec->vtx.current[i][1]; + case 1: exec->vtx.attrptr[i][0] = exec->vtx.current[i][0]; + break; + } + + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, + GLuint attr, + GLuint newsz ) +{ + GLcontext *ctx = exec->ctx; + GLint lastcount = exec->vtx.vert_count; + GLfloat *tmp; + GLuint oldsz; + GLuint i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to exec->vtx.copied. + */ + vbo_exec_wrap_buffers( exec ); + + + /* 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 && + exec->vtx.attrsz[attr] == 0 && + lastcount > 8 && + exec->vtx.vertex_size) { + reset_attrfv( exec ); + } + + /* Fix up sizes: + */ + oldsz = exec->vtx.attrsz[attr]; + exec->vtx.attrsz[attr] = newsz; + + exec->vtx.vertex_size += newsz - oldsz; + exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size; + exec->vtx.vert_count = 0; + exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; + + + /* Recalculate all the attrptr[] values + */ + for (i = 0, tmp = exec->vtx.vertex ; 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 ); + + /* Replay stored vertices to translate them + * to new format here. + * + * -- No need to replay - just copy piecewise + */ + if (exec->vtx.copied.nr) + { + GLfloat *data = exec->vtx.copied.buffer; + GLfloat *dest = exec->vtx.vbptr; + GLuint j; + + assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map); + + for (i = 0 ; i < exec->vtx.copied.nr ; i++) { + for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { + if (exec->vtx.attrsz[j]) { + if (j == attr) { + if (oldsz) { + COPY_CLEAN_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } else { + COPY_SZ_4V( dest, newsz, exec->vtx.current[j] ); + dest += newsz; + } + } + else { + GLuint sz = exec->vtx.attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + dest += sz; + data += sz; + } + } + } + } + + exec->vtx.vbptr = dest; + exec->vtx.vert_count += exec->vtx.copied.nr; + exec->vtx.copied.nr = 0; + } +} + + +static void vbo_exec_fixup_vertex( GLcontext *ctx, + GLuint attr, GLuint sz ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int i; + + if (sz > 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, sz ); + } + else if (sz < exec->vtx.active_sz[attr]) { + static const GLfloat id[4] = { 0, 0, 0, 1 }; + + /* New size is smaller - just need to fill in some + * zeros. Don't need to flush or wrap. + */ + for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) + exec->vtx.attrptr[attr][i-1] = id[i-1]; + } + + exec->vtx.active_sz[attr] = sz; + + /* Does setting NeedFlush belong here? Necessitates resetting + * vtxfmt on each flush (otherwise flags won't get reset + * afterwards). + */ + if (attr == 0) + exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + else + exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + + + +/* + */ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ + \ + if (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) { \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \ + \ + exec->vtx.vbptr += exec->vtx.vertex_size; \ + exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ +} while (0) + + +#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ) +#define TAG(x) vbo_##x + +#include "vbo_attrib_tmp.h" + + + + + +/* Eval + */ +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_INDEX ; 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 ); + } + } + + + _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord1f( exec, u ); + + _mesa_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_INDEX ; 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 ); + } + + _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord2f( exec, u, v ); + + _mesa_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 ); +} + + +/* Build a list of primitives on the fly. Keep + * ctx->Driver.CurrentExecPrimitive uptodate as well. + */ +static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int i; + + if (ctx->NewState) { + _mesa_update_state( ctx ); + + 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; + } + + CALL_Begin(ctx->Exec, (mode)); + return; + } + + /* Heuristic: attempt to isolate attributes occuring outside + * begin/end pairs. + */ + if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) + vbo_exec_FlushVertices( ctx, ~0 ); + + 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; + + ctx->Driver.CurrentExecPrimitive = mode; + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + +} + +static void GLAPIENTRY vbo_exec_End( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + 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 = GL_POLYGON+1; + + if (exec->vtx.prim_count == VBO_MAX_PRIM) + vbo_exec_vtx_flush( exec ); + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); +} + + +static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) +{ + GLvertexformat *vfmt = &exec->vtxfmt; + + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = vbo_exec_Begin; + vfmt->CallList = _mesa_CallList; + vfmt->CallLists = _mesa_CallLists; + vfmt->End = vbo_exec_End; + vfmt->EvalCoord1f = vbo_exec_EvalCoord1f; + vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv; + vfmt->EvalCoord2f = vbo_exec_EvalCoord2f; + vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv; + vfmt->EvalPoint1 = vbo_exec_EvalPoint1; + vfmt->EvalPoint2 = vbo_exec_EvalPoint2; + + vfmt->Rectf = _mesa_noop_Rectf; + vfmt->EvalMesh1 = _mesa_noop_EvalMesh1; + vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; + + + /* 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; + + vfmt->Materialfv = vbo_Materialfv; + + vfmt->EdgeFlag = vbo_EdgeFlag; + vfmt->Indexf = vbo_Indexf; + vfmt->Indexfv = vbo_Indexfv; + +} + + +static void vbo_exec_current_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLint i; + + /* setup the pointers for the typical 16 vertex attributes */ + for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) + exec->vtx.current[i] = ctx->Current.Attrib[i]; + + /* setup pointers for the 12 material attributes */ + for (i = 0; i < MAT_ATTRIB_MAX; i++) + exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = + ctx->Light.Material.Attrib[i]; + + exec->vtx.current[VBO_ATTRIB_INDEX] = &ctx->Current.Index; + exec->vtx.current[VBO_ATTRIB_EDGEFLAG] = &exec->vtx.CurrentFloatEdgeFlag; +} + +void vbo_exec_vtx_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLuint i; + + /* Allocate a buffer object. Will just reuse this object + * continuously. + */ + exec->vtx.bufferobj = ctx->Array.NullBufferObj; + exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); + + vbo_exec_current_init( exec ); + vbo_exec_vtxfmt_init( exec ); + + /* Hook our functions into the dispatch table. + */ + _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + exec->vtx.attrsz[i] = 0; + exec->vtx.active_sz[i] = 0; + exec->vtx.inputs[i] = &exec->vtx.arrays[i]; + } + + exec->vtx.vertex_size = 0; +} + + +void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) +{ + if (exec->vtx.buffer_map) { + ALIGN_FREE(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; + } +} + + +void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) + return; + + if (exec->vtx.vert_count) { + vbo_exec_vtx_flush( exec ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } + + exec->ctx->Driver.NeedFlush = 0; +} + + +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; +} + diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c new file mode 100644 index 00000000000..5cfa7a01a96 --- /dev/null +++ b/src/mesa/vbo/vbo_exec_array.c @@ -0,0 +1,367 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "state.h" +#include "api_validate.h" +#include "api_noop.h" +#include "dispatch.h" + +#include "vbo_context.h" + +static GLuint get_max_index( GLuint count, GLuint type, + const GLvoid *indices ) +{ + GLint i; + + /* Compute max element. This is only needed for upload of non-VBO, + * non-constant data elements. + * + * XXX: Postpone this calculation until it is known that it is + * needed. Otherwise could scan this pointlessly in the all-vbo + * case. + */ + switch(type) { + case GL_UNSIGNED_INT: { + const GLuint *ui_indices = (const GLuint *)indices; + GLuint max_ui = 0; + for (i = 0; i < count; i++) + if (ui_indices[i] > max_ui) + max_ui = ui_indices[i]; + return max_ui; + } + case GL_UNSIGNED_SHORT: { + const GLushort *us_indices = (const GLushort *)indices; + GLuint max_us = 0; + for (i = 0; i < count; i++) + if (us_indices[i] > max_us) + max_us = us_indices[i]; + return max_us; + } + case GL_UNSIGNED_BYTE: { + const GLubyte *ub_indices = (const GLubyte *)indices; + GLuint max_ub = 0; + for (i = 0; i < count; i++) + if (ub_indices[i] > max_ub) + max_ub = ub_indices[i]; + return max_ub; + } + default: + return 0; + } +} + + +/* Just translate the arrayobj into a sane layout. + */ +static void bind_array_obj( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + GLuint i; + + /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array + * rather than as individual named arrays. Then this function can + * go away. + */ + exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex; + exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal; + exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color; + exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; + exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord; + exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index; + exec->array.legacy_array[VBO_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; + + for (i = 0; i < 8; i++) + exec->array.legacy_array[VBO_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i]; + + exec->array.array_obj = ctx->Array.ArrayObj->Name; +} + +static void recalculate_input_bindings( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + const struct gl_client_array **inputs = &exec->array.inputs[0]; + GLuint i; + + exec->array.program_mode = get_program_mode(ctx); + exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; + + /* TODO: Get rid of NV_program (please!). + */ + switch (exec->array.program_mode) { + case VP_NONE: + /* When no vertex program is active, we put the material values + * into the generic slots. This is the only situation where + * material values are available as per-vertex attributes. + */ + for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &exec->legacy_currval[i]; + } + + for (i = 0; i < MAT_ATTRIB_MAX; i++) { + inputs[VERT_ATTRIB_GENERIC0 + i] = &exec->mat_currval[i]; + } + break; + case VP_NV: + /* NV_vertex_program - attribute arrays alias and override + * conventional, legacy arrays. No materials, and the generic + * slots are vacant. + */ + for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.generic_array[i]->Enabled) + inputs[i] = exec->array.generic_array[i]; + else if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &exec->legacy_currval[i]; + } + break; + case VP_ARB: + /* ARB_vertex_program - Only the attribute zero (position) array + * aliases and overrides the legacy position array. + * + * Otherwise, legacy attributes available in the legacy slots, + * generic attributes in the generic slots and materials are not + * available as per-vertex attributes. + */ + if (exec->array.generic_array[0]->Enabled) + inputs[0] = exec->array.generic_array[0]; + else if (exec->array.legacy_array[0]->Enabled) + inputs[0] = exec->array.legacy_array[0]; + else + inputs[0] = &exec->legacy_currval[0]; + + + for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &exec->legacy_currval[i]; + } + + for (i = 0; i < 16; i++) { + if (exec->array.generic_array[0]->Enabled) + inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; + else + inputs[VERT_ATTRIB_GENERIC0 + i] = &exec->generic_currval[i]; + } + break; + } +} + +static void bind_arrays( GLcontext *ctx ) +{ +#if 0 + if (ctx->Array.ArrayObj.Name != exec->array.array_obj) { + bind_array_obj(ctx); + recalculate_input_bindings(ctx); + } + else if (exec->array.program_mode != get_program_mode(ctx) || + exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) { + + recalculate_input_bindings(ctx); + } +#else + bind_array_obj(ctx); + recalculate_input_bindings(ctx); +#endif +} + + + +/*********************************************************************** + * API functions. + */ + +static void GLAPIENTRY +vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_prim prim[1]; + + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + return; + + FLUSH_CURRENT( ctx, 0 ); + + if (ctx->NewState) + _mesa_update_state( ctx ); + + bind_arrays( ctx ); + + prim[0].begin = 1; + prim[0].end = 1; + prim[0].weak = 0; + prim[0].pad = 0; + + if (exec->array.inputs[0]->BufferObj->Name) { + /* Use vertex attribute as a hint to tell us if we expect all + * arrays to be in VBO's and if so, don't worry about avoiding + * the upload of elements < start. + */ + prim[0].mode = mode; + prim[0].start = start; + prim[0].count = count; + prim[0].indexed = 0; + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count ); + } + else { + /* If not using VBO's, we don't want to upload any more elements + * than necessary from the arrays as they will not be valid next + * time the application tries to draw with them. + */ + prim[0].mode = mode; + prim[0].start = 0; + prim[0].count = count; + prim[0].indexed = 0; + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count ); + } +} + + + +static void GLAPIENTRY +vbo_exec_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_index_buffer ib; + struct _mesa_prim prim[1]; + + if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) + return; + + FLUSH_CURRENT( ctx, 0 ); + + if (ctx->NewState) + _mesa_update_state( ctx ); + + ib.count = count; + ib.type = type; + ib.obj = ctx->Array.ElementArrayBufferObj; + ib.ptr = indices; + + if (ctx->Array.ElementArrayBufferObj->Name) { + /* Use the fact that indices are in a VBO as a hint that the + * program has put all the arrays in VBO's and we don't have to + * worry about performance implications of start > 0. + * + * XXX: consider passing start as min_index to draw_prims instead. + */ + ib.rebase = 0; + } + else { + ib.rebase = start; + } + + prim[0].begin = 1; + prim[0].end = 1; + prim[0].weak = 0; + prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = 0; + prim[0].count = count; + prim[0].indexed = 1; + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, ib.rebase, end+1 ); +} + + +static void GLAPIENTRY +vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint max_index; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + if (ctx->Array.ElementArrayBufferObj->Name) { + const GLvoid *map = ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + GL_DYNAMIC_READ_ARB, + ctx->Array.ElementArrayBufferObj); + + max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); + + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + ctx->Array.ElementArrayBufferObj); + } + else { + max_index = get_max_index(count, type, indices); + } + + vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices); +} + + +/*********************************************************************** + * Initialization + */ + + + + +void vbo_exec_array_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + +#if 1 + exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; + exec->vtxfmt.DrawElements = vbo_exec_DrawElements; + exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; +#else + exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays; + exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; + exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; +#endif + + exec->array.index_obj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); +} + + +void vbo_exec_array_destroy( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + + ctx->Driver.DeleteBuffer(ctx, exec->array.index_obj); +} diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c new file mode 100644 index 00000000000..f665c64c7ac --- /dev/null +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -0,0 +1,199 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "state.h" +#include "macros.h" + +#include "vbo_context.h" + + +static void vbo_exec_debug_verts( struct vbo_exec_context *exec ) +{ + GLuint count = exec->vtx.vert_count; + GLuint i; + + _mesa_printf("%s: %u vertices %d primitives, %d vertsize\n", + __FUNCTION__, + count, + exec->vtx.prim_count, + exec->vtx.vertex_size); + + for (i = 0 ; i < exec->vtx.prim_count ; i++) { + struct _mesa_prim *prim = &exec->vtx.prim[i]; + _mesa_printf(" prim %d: %s%s %d..%d %s %s\n", + i, + _mesa_lookup_enum_by_nr(prim->mode), + prim->weak ? " (weak)" : "", + prim->start, + prim->start + prim->count, + prim->begin ? "BEGIN" : "(wrap)", + prim->end ? "END" : "(wrap)"); + } +} + + +/* + * NOTE: Need to have calculated primitives by this point -- do it on the fly. + * NOTE: Old 'parity' issue is gone. + */ +static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) +{ + GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count; + GLuint ovf, i; + GLuint sz = exec->vtx.vertex_size; + GLfloat *dst = exec->vtx.copied.buffer; + GLfloat *src = ((GLfloat *)exec->vtx.buffer_map + + exec->vtx.prim[exec->vtx.prim_count-1].start * + exec->vtx.vertex_size); + + + switch( exec->ctx->Driver.CurrentExecPrimitive ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + _mesa_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++) + _mesa_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++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + else { + _mesa_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; + else if (nr == 1) { + _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); + return 1; + } else { + _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); + _mesa_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; + } + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_POLYGON+1: + return 0; + default: + assert(0); + return 0; + } +} + + +/* TODO: populate these as the vertex is defined: + */ +static void vbo_exec_bind_arrays( struct vbo_exec_context *exec ) +{ + struct gl_client_array *arrays = exec->vtx.arrays; + GLuint count = exec->vtx.vert_count; + GLubyte *data = exec->vtx.buffer_map; + GLuint attr; + + memcpy(arrays, exec->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, exec->mat_currval, 16 * sizeof(arrays[0])); + + /* Make all active attributes (including edgeflag) available as + * arrays of floats. + */ + for (attr = 0; attr < VBO_ATTRIB_MAX ; attr++) { + if (exec->vtx.attrsz[attr]) { + arrays[attr].Ptr = (void *)data; + arrays[attr].Size = exec->vtx.attrsz[attr]; + arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); + arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); + arrays[attr].Type = GL_FLOAT; + arrays[attr].Enabled = 1; + arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */ + arrays[attr]._MaxElement = count; /* ??? */ + + data += exec->vtx.attrsz[attr] * sizeof(GLfloat); + } + } +} + + +/** + * Execute the buffer and save copied verts. + */ +void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) +{ + if (0) + vbo_exec_debug_verts( exec ); + + + if (exec->vtx.prim_count && + exec->vtx.vert_count) { + + exec->vtx.copied.nr = vbo_copy_vertices( exec ); + + if (exec->vtx.copied.nr != exec->vtx.vert_count) { + GLcontext *ctx = exec->ctx; + + vbo_exec_bind_arrays( exec ); + + vbo_context(ctx)->draw_prims( ctx, + exec->vtx.inputs, + exec->vtx.prim, + exec->vtx.prim_count, + NULL, + 0, + exec->vtx.vert_count ); + } + } + + exec->vtx.prim_count = 0; + exec->vtx.vert_count = 0; + exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; +} diff --git a/src/mesa/vbo/vbo_exec_eval.c b/src/mesa/vbo/vbo_exec_eval.c new file mode 100644 index 00000000000..99a80445763 --- /dev/null +++ b/src/mesa/vbo/vbo_exec_eval.c @@ -0,0 +1,255 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +#include "glheader.h" +#include "api_eval.h" +#include "context.h" +#include "macros.h" +#include "math/m_eval.h" +#include "vbo_exec.h" +#include "dispatch.h" + + +static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr ) +{ + exec->eval.map1[attr].map = NULL; +} + +static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr ) +{ + exec->eval.map2[attr].map = NULL; +} + +static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim, + struct gl_1d_map *map ) +{ + if (!exec->eval.map1[attr].map) { + exec->eval.map1[attr].map = map; + exec->eval.map1[attr].sz = dim; + } +} + +static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim, + struct gl_2d_map *map ) +{ + if (!exec->eval.map2[attr].map) { + exec->eval.map2[attr].map = map; + exec->eval.map2[attr].sz = dim; + } +} + +void vbo_exec_eval_update( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLuint attr; + + /* Vertex program maps have priority over conventional attribs */ + + for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) { + clear_active_eval1( exec, attr ); + clear_active_eval2( exec, attr ); + } + + /* _NEW_PROGRAM */ + if (ctx->VertexProgram._Enabled) { + for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) { + /* _NEW_EVAL */ + if (ctx->Eval.Map1Attrib[attr]) + set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] ); + + if (ctx->Eval.Map2Attrib[attr]) + set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] ); + } + } + + if (ctx->Eval.Map1Color4) + set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 ); + + if (ctx->Eval.Map2Color4) + set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 ); + + if (ctx->Eval.Map1TextureCoord4) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 ); + else if (ctx->Eval.Map1TextureCoord3) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 ); + else if (ctx->Eval.Map1TextureCoord2) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 ); + else if (ctx->Eval.Map1TextureCoord1) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 ); + + if (ctx->Eval.Map2TextureCoord4) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 ); + else if (ctx->Eval.Map2TextureCoord3) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 ); + else if (ctx->Eval.Map2TextureCoord2) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 ); + else if (ctx->Eval.Map2TextureCoord1) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 ); + + if (ctx->Eval.Map1Normal) + set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal ); + + if (ctx->Eval.Map2Normal) + set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal ); + + if (ctx->Eval.Map1Vertex4) + set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 ); + else if (ctx->Eval.Map1Vertex3) + set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 ); + + if (ctx->Eval.Map2Vertex4) + set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 ); + else if (ctx->Eval.Map2Vertex3) + set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 ); + + exec->eval.recalculate_maps = 0; +} + + + +void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u) +{ + GLuint attr; + + for (attr = 1; attr <= VBO_ATTRIB_INDEX; attr++) { + struct gl_1d_map *map = exec->eval.map1[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, data, uu, + exec->eval.map1[attr].sz, + map->Order); + + COPY_SZ_4V( exec->vtx.attrptr[attr], + exec->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord1f is a noop if this map not enabled: + **/ + if (exec->eval.map1[0].map) { + struct gl_1d_map *map = exec->eval.map1[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, vertex, uu, + exec->eval.map1[0].sz, + map->Order); + + if (exec->eval.map1[0].sz == 4) + CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); + else + CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); + } +} + + + +void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, + GLfloat u, GLfloat v ) +{ + GLuint attr; + + for (attr = 1; attr <= VBO_ATTRIB_INDEX; attr++) { + struct gl_2d_map *map = exec->eval.map2[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_surf(map->Points, + data, + uu, vv, + exec->eval.map2[attr].sz, + map->Uorder, map->Vorder); + + COPY_SZ_4V( exec->vtx.attrptr[attr], + exec->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord2f is a noop if this map not enabled: + **/ + if (exec->eval.map2[0].map) { + struct gl_2d_map *map = exec->eval.map2[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + if (exec->ctx->Eval.AutoNormal) { + GLfloat normal[4]; + GLfloat du[4], dv[4]; + + _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, + exec->eval.map2[0].sz, + map->Uorder, map->Vorder); + + if (exec->eval.map2[0].sz == 4) { + du[0] = du[0]*vertex[3] - du[3]*vertex[0]; + du[1] = du[1]*vertex[3] - du[3]*vertex[1]; + du[2] = du[2]*vertex[3] - du[3]*vertex[2]; + + dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; + dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; + dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; + } + + + CROSS3(normal, du, dv); + NORMALIZE_3FV(normal); + normal[3] = 1.0; + + COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL], + exec->vtx.attrsz[VBO_ATTRIB_NORMAL], + normal ); + + } + else { + _math_horner_bezier_surf(map->Points, vertex, uu, vv, + exec->eval.map2[0].sz, + map->Uorder, map->Vorder); + } + + if (exec->vtx.attrsz[0] == 4) + CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); + else + CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); + } +} + + diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c new file mode 100644 index 00000000000..0a5b7054005 --- /dev/null +++ b/src/mesa/vbo/vbo_save.c @@ -0,0 +1,94 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + + +#include "mtypes.h" +#include "dlist.h" +#include "vtxfmt.h" +#include "imports.h" + +#include "vbo_context.h" + + + +void vbo_save_init( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + save->ctx = ctx; + + vbo_save_api_init( save ); + vbo_save_wakeup(ctx); + + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; +} + + +void vbo_save_destroy( GLcontext *ctx ) +{ +} + + + + +/* Note that this can occur during the playback of a display list: + */ +void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + if (fallback) + save->replay_flags |= VBO_SAVE_FALLBACK; + else + save->replay_flags &= ~VBO_SAVE_FALLBACK; +} + + +/* I don't see any reason to swap this code out on fallbacks. It + * wouldn't really mean anything to do so anyway as the old lists are + * still around from pre-fallback. Instead, the above code ensures + * that vertices are routed back through immediate mode dispatch on + * fallback. + * + * The below can be moved into init or removed: + */ +void vbo_save_wakeup( GLcontext *ctx ) +{ + ctx->Driver.NewList = vbo_save_NewList; + ctx->Driver.EndList = vbo_save_EndList; + ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices; + ctx->Driver.BeginCallList = vbo_save_BeginCallList; + ctx->Driver.EndCallList = vbo_save_EndCallList; + ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; + + /* Assume we haven't been getting state updates either: + */ + vbo_save_invalidate_state( ctx, ~0 ); +} + + + diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h new file mode 100644 index 00000000000..dbe5cafb999 --- /dev/null +++ b/src/mesa/vbo/vbo_save.h @@ -0,0 +1,180 @@ +/************************************************************************** + +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 + * + */ + +#ifndef VBO_SAVE_H +#define VBO_SAVE_H + +#include "mtypes.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; + + 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_WEAK 0x40 + +#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 { + GLcontext *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 *vbptr; /* 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 CurrentFloatEdgeFlag; + + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */ + GLubyte *currentsz[VBO_ATTRIB_MAX]; +}; + + +void vbo_save_init( GLcontext *ctx ); +void vbo_save_destroy( GLcontext *ctx ); +void vbo_save_wakeup( GLcontext *ctx ); +void vbo_save_invalidate_state( GLcontext *ctx, GLuint new_state ); +void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ); + +/* save_loopback.c: + */ +void vbo_loopback_vertex_list( GLcontext *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( GLcontext *ctx ); +void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode ); +void vbo_save_EndCallList( GLcontext *ctx ); +void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *list ); +void vbo_save_SaveFlushVertices( GLcontext *ctx ); +GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ); + +void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ); + +void vbo_save_api_init( struct vbo_save_context *save ); + +#endif diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c new file mode 100644 index 00000000000..8ceba2b832b --- /dev/null +++ b/src/mesa/vbo/vbo_save_api.c @@ -0,0 +1,1160 @@ +/************************************************************************** + +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 + */ + + + +/* Display list compiler attempts to store lists of vertices with the + * same vertex layout. Additionally it attempts to minimize the need + * for execute-time fixup of these vertex lists, allowing them to be + * cached on hardware. + * + * There are still some circumstances where this can be thwarted, for + * example by building a list that consists of one very long primitive + * (eg Begin(Triangles), 1000 vertices, End), and calling that list + * from inside a different begin/end object (Begin(Lines), CallList, + * End). + * + * In that case the code will have to replay the list as individual + * commands through the Exec dispatch table, or fix up the copied + * vertices at execute-time. + * + * The other case where fixup is required is when a vertex attribute + * is introduced in the middle of a primitive. Eg: + * Begin(Lines) + * TexCoord1f() Vertex2f() + * TexCoord1f() Color3f() Vertex2f() + * End() + * + * If the current value of Color isn't known at compile-time, this + * primitive will require fixup. + * + * + * The list compiler currently doesn't attempt to compile lists + * containing EvalCoord or EvalPoint commands. On encountering one of + * these, compilation falls back to opcodes. + * + * This could be improved to fallback only when a mix of EvalCoord and + * Vertex commands are issued within a single primitive. + */ + + +#include "glheader.h" +#include "context.h" +#include "dlist.h" +#include "enums.h" +#include "macros.h" +#include "api_validate.h" +#include "api_arrayelt.h" +#include "vtxfmt.h" +#include "dispatch.h" + +#include "vbo_context.h" + + + +/* + * NOTE: Old 'parity' issue is gone, but copying can still be + * wrong-footed on replay. + */ +static GLuint _save_copy_vertices( GLcontext *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]; + GLuint nr = prim->count; + GLuint sz = save->vertex_size; + const GLfloat *src = src_buffer + prim->start * sz; + GLfloat *dst = save->copied.buffer; + GLuint ovf, i; + + if (prim->end) + return 0; + + switch( prim->mode ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + _mesa_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++) + _mesa_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++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + else { + _mesa_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; + else if (nr == 1) { + _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) ); + return 1; + } else { + _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) ); + _mesa_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; + } + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + default: + assert(0); + return 0; + } +} + + +static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx ) +{ + 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 + * into the hash and can never be confused with ones visible to the + * user. Perhaps there could be a special number for internal + * buffers: + */ + vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, 1, 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); + + vertex_store->buffer = NULL; + vertex_store->used = 0; + vertex_store->refcount = 1; + + return vertex_store; +} + +static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store ) +{ + assert(!vertex_store->buffer); + + if (vertex_store->bufferobj) + ctx->Driver.DeleteBuffer( ctx, vertex_store->bufferobj ); + + FREE( vertex_store ); +} + +static GLfloat *map_vertex_store( GLcontext *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_STATIC_DRAW_ARB, /* not used */ + vertex_store->bufferobj); + + assert(vertex_store->buffer); + return vertex_store->buffer + vertex_store->used; +} + +static void unmap_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store ) +{ + ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj ); + vertex_store->buffer = NULL; +} + + +static struct vbo_save_primitive_store *alloc_prim_store( GLcontext *ctx ) +{ + 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( GLcontext *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); + + assert(save->buffer == save->vbptr); + + if (save->vertex_size) + save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / + save->vertex_size); + else + save->max_vert = 0; + + save->vert_count = 0; + save->prim_count = 0; + save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used; + save->dangling_attr_ref = 0; +} + + +/* Insert the active immediate struct onto the display list currently + * being built. + */ +static void _save_compile_vertex_list( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_vertex_list *node; + + /* Allocate space for this structure in the display list currently + * being compiled. + */ + node = (struct vbo_save_vertex_list *) + _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node)); + + if (!node) + return; + + /* Duplicate our template, increment refcounts to the storage structs: + */ + _mesa_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->count = save->vert_count; + node->wrap_count = save->copied.nr; + node->dangling_attr_ref = save->dangling_attr_ref; + node->prim = save->prim; + node->prim_count = save->prim_count; + node->vertex_store = save->vertex_store; + node->prim_store = save->prim_store; + + node->vertex_store->refcount++; + node->prim_store->refcount++; + + assert(node->attrsz[VBO_ATTRIB_POS] != 0 || + node->count == 0); + + if (save->dangling_attr_ref) + ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS; + + 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 ); + + + /* Deal with GL_COMPILE_AND_EXECUTE: + */ + if (ctx->ExecuteFlag) { + struct _glapi_table *dispatch = GET_DISPATCH(); + + _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); + + _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 > + VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) { + + /* Unmap old store: + */ + unmap_vertex_store( ctx, save->vertex_store ); + + /* Release old reference: + */ + 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->vbptr = map_vertex_store( ctx, save->vertex_store ); + } + + if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { + save->prim_store->refcount--; + assert(save->prim_store->refcount != 0); + save->prim_store = alloc_prim_store( ctx ); + } + + /* Reset our structures for the next run of vertices: + */ + _save_reset_counters( ctx ); +} + + +/* TODO -- If no new vertices have been stored, don't bother saving + * it. + */ +static void _save_wrap_buffers( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i = save->prim_count - 1; + GLenum mode; + GLboolean weak; + + assert(i < (GLint) save->prim_max); + assert(i >= 0); + + /* Close off in-progress primitive. + */ + save->prim[i].count = (save->vert_count - + save->prim[i].start); + mode = save->prim[i].mode; + weak = save->prim[i].weak; + + /* store the copied vertices, and allocate a new list. + */ + _save_compile_vertex_list( ctx ); + + /* Restart interrupted primitive + */ + save->prim[0].mode = mode; + save->prim[0].weak = weak; + save->prim[0].begin = 0; + save->prim[0].end = 0; + save->prim[0].pad = 0; + save->prim[0].start = 0; + save->prim[0].count = 0; + save->prim_count = 1; +} + + + +/* Called only when buffers are wrapped as the result of filling the + * vertex_store struct. + */ +static void _save_wrap_filled_vertex( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLfloat *data = save->copied.buffer; + GLuint i; + + /* Emit a glEnd to close off the last vertex 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++) { + _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat)); + data += save->vertex_size; + save->vbptr += save->vertex_size; + save->vert_count++; + } +} + + +static void _save_copy_to_current( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint i; + + for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; i++) { + if (save->attrsz[i]) { + save->currentsz[i][0] = save->attrsz[i]; + COPY_CLEAN_4V(save->current[i], + save->attrsz[i], + save->attrptr[i]); + } + } + + /* Edgeflag requires special treatment: + * + * TODO: change edgeflag to GLfloat in Mesa. + */ + if (save->attrsz[VBO_ATTRIB_EDGEFLAG]) { + ctx->ListState.ActiveEdgeFlag = 1; + save->CurrentFloatEdgeFlag = + save->attrptr[VBO_ATTRIB_EDGEFLAG][0]; + ctx->ListState.CurrentEdgeFlag = + (save->CurrentFloatEdgeFlag == 1.0); + } +} + + +static void _save_copy_from_current( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i; + + for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; 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; + } + + /* Edgeflag requires special treatment: + */ + if (save->attrsz[VBO_ATTRIB_EDGEFLAG]) { + save->CurrentFloatEdgeFlag = (GLfloat)ctx->ListState.CurrentEdgeFlag; + save->attrptr[VBO_ATTRIB_EDGEFLAG][0] = save->CurrentFloatEdgeFlag; + } +} + + + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _save_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint oldsz; + GLuint i; + GLfloat *tmp; + + /* 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 ); + else + 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 ); + + /* Fix up sizes: + */ + oldsz = save->attrsz[attr]; + save->attrsz[attr] = newsz; + + save->vertex_size += newsz - oldsz; + 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++) { + if (save->attrsz[i]) { + save->attrptr[i] = tmp; + tmp += save->attrsz[i]; + } + else + save->attrptr[i] = NULL; /* will not be dereferenced. */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + _save_copy_from_current( ctx ); + + /* Replay stored vertices to translate them to new format here. + * + * If there are copied vertices and the new (upgraded) attribute + * has not been defined before, this list is somewhat degenerate, + * and will need fixup at runtime. + */ + if (save->copied.nr) + { + GLfloat *data = save->copied.buffer; + GLfloat *dest = save->buffer; + GLuint j; + + /* Need to note this and fix up at runtime (or loopback): + */ + if (save->currentsz[attr][0] == 0) { + 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; + } + } + } + } + + save->vbptr = dest; + save->vert_count += save->copied.nr; + } +} + +static void save_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) +{ + 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 ); + } + else if (sz < save->active_sz[attr]) { + static GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; + + /* 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]; + } + + save->active_sz[attr] = sz; +} + +static void _save_reset_vertex( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint i; + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + save->attrsz[i] = 0; + save->active_sz[i] = 0; + } + + save->vertex_size = 0; +} + + + +#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); + + +/* Only one size for each attribute may be active at once. Eg. if + * Color3f is installed/active, then Color4f may not be, even if the + * vertex actually contains 4 color coordinates. This is because the + * 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 ) \ +do { \ + struct vbo_save_context *save = &vbo_context(ctx)->save; \ + \ + if (save->active_sz[A] != N) \ + save_fixup_vertex(ctx, A, N); \ + \ + { \ + GLfloat *dest = save->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) { \ + GLuint i; \ + \ + for (i = 0; i < save->vertex_size; i++) \ + save->vbptr[i] = save->vertex[i]; \ + \ + save->vbptr += save->vertex_size; \ + \ + if (++save->vert_count >= save->max_vert) \ + _save_wrap_filled_vertex( ctx ); \ + } \ +} while (0) + +#define TAG(x) _save_##x + +#include "vbo_attrib_tmp.h" + + + + +/* Cope with EvalCoord/CallList called within a begin/end object: + * -- Flush current buffer + * -- Fallback to opcodes for the rest of the begin/end object. + */ +#define DO_FALLBACK(ctx) \ +do { \ + struct vbo_save_context *save = &vbo_context(ctx)->save; \ + \ + 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 ); \ + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \ + ctx->Driver.SaveNeedFlush = 0; \ +} while (0) + +static void GLAPIENTRY _save_EvalCoord1f( GLfloat u ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord1f( u ); +} + +static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord1fv( v ); +} + +static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord2f( u, v ); +} + +static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord2fv( v ); +} + +static void GLAPIENTRY _save_EvalPoint1( GLint i ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalPoint1( i ); +} + +static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalPoint2( i, j ); +} + +static void GLAPIENTRY _save_CallList( GLuint l ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->CallList( l ); +} + +static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->CallLists( n, type, v ); +} + + + + +/* This begin is hooked into ... Updating of + * ctx->Driver.CurrentSavePrimitive is already taken care of. + */ +GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + GLuint i = save->prim_count++; + + assert(i < save->prim_max); + save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK; + save->prim[i].begin = 1; + save->prim[i].end = 0; + save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; + save->prim[i].pad = 0; + save->prim[i].start = save->vert_count; + save->prim[i].count = 0; + + _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); + ctx->Driver.SaveNeedFlush = 1; + return GL_TRUE; +} + + + +static void GLAPIENTRY _save_End( void ) +{ + 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); + + if (i == (GLint) save->prim_max - 1) { + _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 ); +} + + +/* 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) +{ + GET_CURRENT_CONTEXT(ctx); + (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) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" ); +} + +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" ); +} + +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" ); +} + +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" ); +} + +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" ); +} + +static void GLAPIENTRY _save_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + (void) mode; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" ); +} + + +/* Unlike the functions above, these are to be hooked into the vtxfmt + * 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 ) +{ + 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 )); + CALL_End(GET_DISPATCH(), ()); +} + + +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 )) + return; + + vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK ); + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (start + i)); + CALL_End(GET_DISPATCH(), ()); +} + +/* 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) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK ); + + switch (type) { + case GL_UNSIGNED_BYTE: + 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] )); + break; + case GL_UNSIGNED_INT: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] )); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + break; + } + + CALL_End(GET_DISPATCH(), ()); +} + +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 )) + _save_OBE_DrawElements( mode, count, type, indices ); +} + + + + + +static void _save_vtxfmt_init( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLvertexformat *vfmt = &save->vtxfmt; + + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = _save_Begin; + vfmt->Color3f = _save_Color3f; + vfmt->Color3fv = _save_Color3fv; + vfmt->Color4f = _save_Color4f; + vfmt->Color4fv = _save_Color4fv; + vfmt->EdgeFlag = _save_EdgeFlag; + vfmt->End = _save_End; + vfmt->FogCoordfEXT = _save_FogCoordfEXT; + vfmt->FogCoordfvEXT = _save_FogCoordfvEXT; + vfmt->Indexf = _save_Indexf; + vfmt->Indexfv = _save_Indexfv; + vfmt->Materialfv = _save_Materialfv; + vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv; + vfmt->Normal3f = _save_Normal3f; + vfmt->Normal3fv = _save_Normal3fv; + vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT; + vfmt->TexCoord1f = _save_TexCoord1f; + vfmt->TexCoord1fv = _save_TexCoord1fv; + vfmt->TexCoord2f = _save_TexCoord2f; + vfmt->TexCoord2fv = _save_TexCoord2fv; + vfmt->TexCoord3f = _save_TexCoord3f; + vfmt->TexCoord3fv = _save_TexCoord3fv; + vfmt->TexCoord4f = _save_TexCoord4f; + vfmt->TexCoord4fv = _save_TexCoord4fv; + vfmt->Vertex2f = _save_Vertex2f; + vfmt->Vertex2fv = _save_Vertex2fv; + vfmt->Vertex3f = _save_Vertex3f; + vfmt->Vertex3fv = _save_Vertex3fv; + vfmt->Vertex4f = _save_Vertex4f; + vfmt->Vertex4fv = _save_Vertex4fv; + vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB; + + vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV; + + /* This will all require us to fallback to saving the list as opcodes: + */ + vfmt->CallList = _save_CallList; /* inside begin/end */ + vfmt->CallLists = _save_CallLists; /* inside begin/end */ + vfmt->EvalCoord1f = _save_EvalCoord1f; + vfmt->EvalCoord1fv = _save_EvalCoord1fv; + vfmt->EvalCoord2f = _save_EvalCoord2f; + vfmt->EvalCoord2fv = _save_EvalCoord2fv; + vfmt->EvalPoint1 = _save_EvalPoint1; + vfmt->EvalPoint2 = _save_EvalPoint2; + + /* These are all errors as we at least know we are in some sort of + * begin/end pair: + */ + vfmt->EvalMesh1 = _save_EvalMesh1; + vfmt->EvalMesh2 = _save_EvalMesh2; + vfmt->Begin = _save_Begin; + vfmt->Rectf = _save_Rectf; + vfmt->DrawArrays = _save_DrawArrays; + vfmt->DrawElements = _save_DrawElements; + vfmt->DrawRangeElements = _save_DrawRangeElements; + +} + + +void vbo_save_SaveFlushVertices( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + /* Noop when we are actually active: + */ + if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM || + 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 ); + ctx->Driver.SaveNeedFlush = 0; +} + +void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + (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->vbptr = map_vertex_store( ctx, save->vertex_store ); + + _save_reset_vertex( ctx ); + _save_reset_counters( ctx ); + ctx->Driver.SaveNeedFlush = 0; +} + +void vbo_save_EndList( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + unmap_vertex_store( ctx, save->vertex_store ); + + assert(save->vertex_size == 0); +} + +void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + save->replay_flags |= dlist->flags; +} + +void vbo_save_EndCallList( GLcontext *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: + */ + save->replay_flags &= VBO_SAVE_FALLBACK; + } +} + + +static void vbo_destroy_vertex_list( GLcontext *ctx, void *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->prim_store->refcount == 0 ) + FREE( node->prim_store ); +} + + +static void vbo_print_vertex_list( GLcontext *ctx, void *data ) +{ + struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data; + GLuint i; + (void) ctx; + + _mesa_debug(NULL, "VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n", + node->count, + node->prim_count, + node->vertex_size); + + 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_enum_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( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i; + + for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) { + save->currentsz[i] = &ctx->ListState.ActiveAttribSize[i]; + save->current[i] = ctx->ListState.CurrentAttrib[i]; + } + + for (i = VBO_ATTRIB_FIRST_MATERIAL; i < VBO_ATTRIB_INDEX; i++) { + const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL; + ASSERT(j < MAT_ATTRIB_MAX); + save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j]; + save->current[i] = ctx->ListState.CurrentMaterial[j]; + } + + save->currentsz[VBO_ATTRIB_INDEX] = &ctx->ListState.ActiveIndex; + save->current[VBO_ATTRIB_INDEX] = &ctx->ListState.CurrentIndex; + + save->currentsz[VBO_ATTRIB_EDGEFLAG] = &ctx->ListState.ActiveEdgeFlag; + save->current[VBO_ATTRIB_EDGEFLAG] = &save->CurrentFloatEdgeFlag; +} + +/** + * Initialize the display list compiler + */ +void vbo_save_api_init( struct vbo_save_context *save ) +{ + GLcontext *ctx = save->ctx; + GLuint i; + + save->opcode_vertex_list = + _mesa_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 ); + + for (i = 0; i < VBO_ATTRIB_MAX; i++) + save->inputs[i] = &save->arrays[i]; + + /* Hook our array functions into the outside-begin-end vtxfmt in + * ctx->ListState. + */ + ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf; + ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays; + ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; + ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); +} + diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c new file mode 100644 index 00000000000..44e01712330 --- /dev/null +++ b/src/mesa/vbo/vbo_save_draw.c @@ -0,0 +1,202 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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 + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "macros.h" +#include "light.h" +#include "state.h" + +#include "vbo_context.h" + + + +static void _playback_copy_to_current( GLcontext *ctx, + const struct vbo_save_vertex_list *node ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex; + GLuint i, offset; + + if (node->count) + offset = node->buffer_offset + (node->count-1) * node->vertex_size; + else + offset = node->buffer_offset; + + ctx->Driver.GetBufferSubData( ctx, 0, offset, node->vertex_size, + data, node->vertex_store->bufferobj ); + + for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; i++) { + if (node->attrsz[i]) { + COPY_CLEAN_4V(save->current[i], node->attrsz[i], data); + data += node->attrsz[i]; + + if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && + i <= VBO_ATTRIB_MAT_BACK_INDEXES) + ctx->NewState |= _NEW_LIGHT; + } + } + + /* Edgeflag requires special treatment: + */ + if (node->attrsz[VBO_ATTRIB_EDGEFLAG]) { + ctx->Current.EdgeFlag = (data[0] == 1.0); + } + + +#if 1 + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); + } +#endif + + /* 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 vbo_save_context *save, + const struct vbo_save_vertex_list *node ) +{ + struct gl_client_array *arrays = save->arrays; + GLuint data = node->buffer_offset; + GLuint attr; + + memset(arrays, 0, VBO_ATTRIB_MAX * sizeof(arrays[0])); + + for (attr = 0; attr <= VBO_ATTRIB_INDEX; attr++) { + if (node->attrsz[attr]) { + arrays[attr].Ptr = (const GLubyte *)data; + arrays[attr].Size = node->attrsz[attr]; + arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); + arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); + arrays[attr].Type = GL_FLOAT; + arrays[attr].Enabled = 1; + arrays[attr].BufferObj = node->vertex_store->bufferobj; + arrays[attr]._MaxElement = node->count; /* ??? */ + + assert(arrays[attr].BufferObj->Name); + + data += node->attrsz[attr] * sizeof(GLfloat); + } + } +} + +static void vbo_save_loopback_vertex_list( GLcontext *ctx, + const struct vbo_save_vertex_list *list ) +{ + const char *buffer = ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, + GL_DYNAMIC_READ_ARB, /* ? */ + 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. + */ +void vbo_save_playback_vertex_list( GLcontext *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) + _mesa_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 ); + + 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( save, node ); + + vbo_context(ctx)->draw_prims( ctx, + save->inputs, + node->prim, + node->prim_count, + NULL, + 0, /* Node is a VBO, so this is ok */ + node->count ); + } + + /* Copy to current? + */ + _playback_copy_to_current( ctx, node ); +} diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c new file mode 100644 index 00000000000..941c4beea94 --- /dev/null +++ b/src/mesa/vbo/vbo_save_loopback.c @@ -0,0 +1,327 @@ +/************************************************************************** + * + * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "swrast_setup/swrast_setup.h" +#include "swrast/swrast.h" +#include "tnl/tnl.h" +#include "context.h" + +#include "vbo_context.h" + +#include "glheader.h" +#include "enums.h" +#include "glapi.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "dispatch.h" + + +typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); + + +/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */ +static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib1fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib2fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib3fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib4fvNV(ctx->Exec, (target, v)); +} + +static attr_func vert_attrfunc[4] = { + VertexAttrib1fvNV, + VertexAttrib2fvNV, + VertexAttrib3fvNV, + VertexAttrib4fvNV +}; + +#if 0 +static void VertexAttrib1fvARB(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib1fvARB(ctx->Exec, (target, v)); +} + +static void VertexAttrib2fvARB(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib2fvARB(ctx->Exec, (target, v)); +} + +static void VertexAttrib3fvARB(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib3fvARB(ctx->Exec, (target, v)); +} + +static void VertexAttrib4fvARB(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib4fvARB(ctx->Exec, (target, v)); +} + + +static attr_func vert_attrfunc_arb[4] = { + VertexAttrib1fvARB, + VertexAttrib2fvARB, + VertexAttrib3fvARB, + VertexAttrib4fvARB +}; +#endif + + + + + + +static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case VBO_ATTRIB_MAT_FRONT_SHININESS: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SHININESS, v )); + break; + case VBO_ATTRIB_MAT_BACK_SHININESS: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SHININESS, v )); + break; + } +} + + +static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case VBO_ATTRIB_MAT_FRONT_INDEXES: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_COLOR_INDEXES, v )); + break; + case VBO_ATTRIB_MAT_BACK_INDEXES: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_COLOR_INDEXES, v )); + break; + } +} + + +static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case VBO_ATTRIB_MAT_FRONT_EMISSION: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_EMISSION, v )); + break; + case VBO_ATTRIB_MAT_BACK_EMISSION: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_EMISSION, v )); + break; + case VBO_ATTRIB_MAT_FRONT_AMBIENT: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_AMBIENT, v )); + break; + case VBO_ATTRIB_MAT_BACK_AMBIENT: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_AMBIENT, v )); + break; + case VBO_ATTRIB_MAT_FRONT_DIFFUSE: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_DIFFUSE, v )); + break; + case VBO_ATTRIB_MAT_BACK_DIFFUSE: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_DIFFUSE, v )); + break; + case VBO_ATTRIB_MAT_FRONT_SPECULAR: + CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SPECULAR, v )); + break; + case VBO_ATTRIB_MAT_BACK_SPECULAR: + CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SPECULAR, v )); + break; + } +} + + +static attr_func mat_attrfunc[4] = { + mat_attr1fv, + NULL, + mat_attr3fv, + mat_attr4fv +}; + + +static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + (void) target; + CALL_Indexf(ctx->Exec, (v[0])); +} + +static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + (void) target; + CALL_EdgeFlag(ctx->Exec, ((GLboolean)(v[0] == 1.0))); +} + +struct loopback_attr { + GLint target; + GLint sz; + attr_func func; +}; + +/* Don't emit ends and begins on wrapped primitives. Don't replay + * wrapped vertices. If we get here, it's probably because the the + * precalculated wrapping is wrong. + */ +static void loopback_prim( GLcontext *ctx, + const GLfloat *buffer, + const struct _mesa_prim *prim, + GLuint wrap_count, + GLuint vertex_size, + const struct loopback_attr *la, GLuint nr ) +{ + GLint start = prim->start; + GLint end = start + prim->count; + const GLfloat *data; + GLint j; + GLuint k; + + if (0) + _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n", + _mesa_lookup_enum_by_nr(prim->mode), + prim->begin ? "begin" : "..", + prim->end ? "end" : "..", + start, + end); + + if (prim->begin) { + CALL_Begin(GET_DISPATCH(), ( prim->mode )); + } + else { + assert(start == 0); + start += wrap_count; + } + + data = buffer + start * vertex_size; + + for (j = start ; j < end ; j++) { + const GLfloat *tmp = data + la[0].sz; + + for (k = 1 ; k < nr ; k++) { + la[k].func( ctx, la[k].target, tmp ); + tmp += la[k].sz; + } + + /* Fire the vertex + */ + la[0].func( ctx, VBO_ATTRIB_POS, data ); + data = tmp; + } + + if (prim->end) { + CALL_End(GET_DISPATCH(), ()); + } +} + +/* Primitives generated by DrawArrays/DrawElements/Rectf may be + * caught here. If there is no primitive in progress, execute them + * normally, otherwise need to track and discard the generated + * primitives. + */ +static void loopback_weak_prim( GLcontext *ctx, + const struct _mesa_prim *prim ) +{ + /* Use the prim_weak flag to ensure that if this primitive + * wraps, we don't mistake future vertex_lists for part of the + * surrounding primitive. + * + * While this flag is set, we are simply disposing of data + * generated by an operation now known to be a noop. + */ + if (prim->begin) + ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK; + if (prim->end) + ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK; +} + + +void vbo_loopback_vertex_list( GLcontext *ctx, + const GLfloat *buffer, + const GLubyte *attrsz, + const struct _mesa_prim *prim, + GLuint prim_count, + GLuint wrap_count, + GLuint vertex_size) +{ + struct loopback_attr la[VBO_ATTRIB_MAX]; + GLuint i, nr = 0; + + for (i = 0 ; i <= VBO_ATTRIB_TEX7 ; i++) { + if (attrsz[i]) { + la[nr].target = i; + la[nr].sz = attrsz[i]; + la[nr].func = vert_attrfunc[attrsz[i]-1]; + nr++; + } + } + + for (i = VBO_ATTRIB_MAT_FRONT_AMBIENT ; + i <= VBO_ATTRIB_MAT_BACK_INDEXES ; + i++) { + if (attrsz[i]) { + la[nr].target = i; + la[nr].sz = attrsz[i]; + la[nr].func = mat_attrfunc[attrsz[i]-1]; + nr++; + } + } + + if (attrsz[VBO_ATTRIB_EDGEFLAG]) { + la[nr].target = VBO_ATTRIB_EDGEFLAG; + la[nr].sz = attrsz[VBO_ATTRIB_EDGEFLAG]; + la[nr].func = edgeflag_attr1fv; + nr++; + } + + if (attrsz[VBO_ATTRIB_INDEX]) { + la[nr].target = VBO_ATTRIB_INDEX; + la[nr].sz = attrsz[VBO_ATTRIB_INDEX]; + la[nr].func = index_attr1fv; + nr++; + } + + /* XXX ARB vertex attribs */ + + for (i = 0 ; i < prim_count ; i++) { + if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) && + (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)) + { + loopback_weak_prim( ctx, &prim[i] ); + } + else + { + loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr ); + } + } +} -- cgit v1.2.3 From 99efde461d3b8615863bdb7308e05289e0db0422 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 30 Oct 2006 16:44:13 +0000 Subject: better handling of current attributes. Trivial dlist and varray tests work --- src/mesa/Makefile | 2 +- src/mesa/main/arrayobj.c | 9 --- src/mesa/main/enable.c | 2 +- src/mesa/main/mtypes.h | 10 +-- src/mesa/sources | 30 ++++----- src/mesa/tnl/t_context.c | 2 + src/mesa/vbo/vbo_context.c | 144 +++++++++++++++++++++++++++++++++++++++++- src/mesa/vbo/vbo_context.h | 7 ++ src/mesa/vbo/vbo_exec.c | 117 ---------------------------------- src/mesa/vbo/vbo_exec.h | 4 -- src/mesa/vbo/vbo_exec_array.c | 15 +++-- src/mesa/vbo/vbo_exec_draw.c | 38 +++++++++-- src/mesa/vbo/vbo_save_draw.c | 28 +++++++- 13 files changed, 235 insertions(+), 173 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/Makefile b/src/mesa/Makefile index 3f65ecf5cc9..e06607b0f83 100644 --- a/src/mesa/Makefile +++ b/src/mesa/Makefile @@ -142,7 +142,7 @@ depend: $(ALL_SOURCES) @ echo "running $(MKDEP)" @ touch depend @$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ - > /dev/null + > /dev/null 2>/dev/null subdirs: diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 852b9aaee98..d601ee461e6 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -114,40 +114,34 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->Vertex.StrideB = 0; obj->Vertex.Ptr = NULL; obj->Vertex.Enabled = GL_FALSE; - obj->Vertex.Flags = CA_CLIENT_DATA; obj->Normal.Type = GL_FLOAT; obj->Normal.Stride = 0; obj->Normal.StrideB = 0; obj->Normal.Ptr = NULL; obj->Normal.Enabled = GL_FALSE; - obj->Normal.Flags = CA_CLIENT_DATA; obj->Color.Size = 4; obj->Color.Type = GL_FLOAT; obj->Color.Stride = 0; obj->Color.StrideB = 0; obj->Color.Ptr = NULL; obj->Color.Enabled = GL_FALSE; - obj->Color.Flags = CA_CLIENT_DATA; obj->SecondaryColor.Size = 4; obj->SecondaryColor.Type = GL_FLOAT; obj->SecondaryColor.Stride = 0; obj->SecondaryColor.StrideB = 0; obj->SecondaryColor.Ptr = NULL; obj->SecondaryColor.Enabled = GL_FALSE; - obj->SecondaryColor.Flags = CA_CLIENT_DATA; obj->FogCoord.Size = 1; obj->FogCoord.Type = GL_FLOAT; obj->FogCoord.Stride = 0; obj->FogCoord.StrideB = 0; obj->FogCoord.Ptr = NULL; obj->FogCoord.Enabled = GL_FALSE; - obj->FogCoord.Flags = CA_CLIENT_DATA; obj->Index.Type = GL_FLOAT; obj->Index.Stride = 0; obj->Index.StrideB = 0; obj->Index.Ptr = NULL; obj->Index.Enabled = GL_FALSE; - obj->Index.Flags = CA_CLIENT_DATA; for (i = 0; i < MAX_TEXTURE_UNITS; i++) { obj->TexCoord[i].Size = 4; obj->TexCoord[i].Type = GL_FLOAT; @@ -155,13 +149,11 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->TexCoord[i].StrideB = 0; obj->TexCoord[i].Ptr = NULL; obj->TexCoord[i].Enabled = GL_FALSE; - obj->TexCoord[i].Flags = CA_CLIENT_DATA; } obj->EdgeFlag.Stride = 0; obj->EdgeFlag.StrideB = 0; obj->EdgeFlag.Ptr = NULL; obj->EdgeFlag.Enabled = GL_FALSE; - obj->EdgeFlag.Flags = CA_CLIENT_DATA; for (i = 0; i < VERT_ATTRIB_MAX; i++) { obj->VertexAttrib[i].Size = 4; obj->VertexAttrib[i].Type = GL_FLOAT; @@ -170,7 +162,6 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->VertexAttrib[i].Ptr = NULL; obj->VertexAttrib[i].Enabled = GL_FALSE; obj->VertexAttrib[i].Normalized = GL_FALSE; - obj->VertexAttrib[i].Flags = CA_CLIENT_DATA; } #if FEATURE_ARB_vertex_buffer_object diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index 91268b596d2..bf86e6db7d2 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -53,7 +53,7 @@ static void client_state( GLcontext *ctx, GLenum cap, GLboolean state ) { GLuint flag; - GLuint *var; + GLboolean *var; switch (cap) { case GL_VERTEX_ARRAY: diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 5a326ff0dc9..903779edae5 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1640,8 +1640,6 @@ struct gl_pixelstore_attrib }; -#define CA_CLIENT_DATA 0x1 /**< Data not allocated by mesa */ - /** * Client vertex array attributes @@ -1653,14 +1651,12 @@ struct gl_client_array GLsizei Stride; /**< user-specified stride */ GLsizei StrideB; /**< actual stride in bytes */ const GLubyte *Ptr; /**< Points to array data */ - GLbitfield Enabled; /**< one of the _NEW_ARRAY_ bits */ + GLboolean Enabled; /**< Enabled flag is a boolean */ GLboolean Normalized; /**< GL_ARB_vertex_program */ /**< GL_ARB_vertex_buffer_object */ struct gl_buffer_object *BufferObj; GLuint _MaxElement; - - GLbitfield Flags; }; @@ -1681,8 +1677,8 @@ struct gl_array_object struct gl_client_array SecondaryColor; struct gl_client_array FogCoord; struct gl_client_array Index; - struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS]; struct gl_client_array EdgeFlag; + struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS]; /*@}*/ /** Generic arrays for vertex programs/shaders */ @@ -2617,7 +2613,7 @@ struct matrix_stack #define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5 #define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6 #define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7 -#define _NEW_ARRAY_ATTRIB_0 0x10000 /* start at bit 16 */ +#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */ #define _NEW_ARRAY_ALL 0xffffffff diff --git a/src/mesa/sources b/src/mesa/sources index 09692c6f155..b589111a19b 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -78,10 +78,6 @@ MATH_SOURCES = \ math/m_vector.c \ math/m_xform.c -ARRAY_CACHE_SOURCES = \ - array_cache/ac_context.c \ - array_cache/ac_import.c - SWRAST_SOURCES = \ swrast/s_aaline.c \ swrast/s_aatriangle.c \ @@ -119,13 +115,9 @@ SWRAST_SETUP_SOURCES = \ swrast_setup/ss_triangle.c TNL_SOURCES = \ - tnl/t_array_api.c \ - tnl/t_array_import.c \ tnl/t_context.c \ tnl/t_pipeline.c \ - tnl/t_save_api.c \ - tnl/t_save_loopback.c \ - tnl/t_save_playback.c \ + tnl/t_draw.c \ tnl/t_vb_arbprogram.c \ tnl/t_vb_arbprogram_sse.c \ tnl/t_vb_arbshader.c\ @@ -142,13 +134,19 @@ TNL_SOURCES = \ tnl/t_vp_build.c \ tnl/t_vertex.c \ tnl/t_vertex_sse.c \ - tnl/t_vertex_generic.c \ - tnl/t_vtx_api.c \ - tnl/t_vtx_generic.c \ - tnl/t_vtx_x86.c \ - tnl/t_vtx_eval.c \ - tnl/t_vtx_exec.c + tnl/t_vertex_generic.c +VBO_SOURCES = \ + vbo/vbo_context.c \ + vbo/vbo_exec.c \ + vbo/vbo_exec_api.c \ + vbo/vbo_exec_array.c \ + vbo/vbo_exec_draw.c \ + vbo/vbo_exec_eval.c \ + vbo/vbo_save.c \ + vbo/vbo_save_api.c \ + vbo/vbo_save_draw.c \ + vbo/vbo_save_loopback.c SHADER_SOURCES = \ @@ -317,7 +315,7 @@ ALL_SOURCES = \ SOLO_SOURCES = \ $(MAIN_SOURCES) \ $(MATH_SOURCES) \ - $(ARRAY_CACHE_SOURCES) \ + $(VBO_SOURCES) \ $(TNL_SOURCES) \ $(SHADER_SOURCES) \ $(SWRAST_SOURCES) \ diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index ff05ac03181..851a0672d42 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -77,6 +77,8 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables; + tnl->nr_blocks = 0; + return GL_TRUE; } diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 5f28e6b0e07..29dfe09d997 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -40,6 +40,123 @@ extern void _tnl_draw_prims( GLcontext *ctx, GLuint min_index, GLuint max_index ); + + +#define NR_LEGACY_ATTRIBS 16 +#define NR_GENERIC_ATTRIBS 16 +#define NR_MAT_ATTRIBS 12 + +static void init_legacy_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->legacy_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_LEGACY_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + switch (i) { + case VBO_ATTRIB_EDGEFLAG: + cl->Type = GL_UNSIGNED_BYTE; + cl->Ptr = (const void *)&ctx->Current.EdgeFlag; + break; + case VBO_ATTRIB_INDEX: + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)&ctx->Current.Index; + break; + default: + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[i]; + break; + } + + /* This will have to be determined at runtime: + */ + cl->Size = 1; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_generic_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->generic_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + + for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* This will have to be determined at runtime: + */ + cl->Size = 1; + + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_mat_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->mat_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* Size is fixed for the material attributes, for others will + * be determined at runtime: + */ + switch (i - VERT_ATTRIB_GENERIC0) { + case MAT_ATTRIB_FRONT_SHININESS: + case MAT_ATTRIB_BACK_SHININESS: + cl->Size = 1; + break; + case MAT_ATTRIB_FRONT_INDEXES: + case MAT_ATTRIB_BACK_INDEXES: + cl->Size = 3; + break; + default: + cl->Size = 4; + break; + } + + if (i < MAT_ATTRIB_MAX) + cl->Ptr = (const void *)ctx->Light.Material.Attrib[i]; + else + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + + cl->Type = GL_FLOAT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + + GLboolean _vbo_CreateContext( GLcontext *ctx ) { struct vbo_context *vbo = CALLOC_STRUCT(vbo_context); @@ -60,6 +177,32 @@ GLboolean _vbo_CreateContext( GLcontext *ctx ) vbo_exec_init( ctx ); vbo_save_init( ctx ); + + init_legacy_currval( ctx ); + init_generic_currval( ctx ); + init_mat_currval( ctx ); + + /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type + * of vertex program active. + */ + { + GLuint i; + + /* When no vertex program, pull in the material attributes in + * the 16..32 generic range. + */ + for (i = 0; i < 16; i++) + vbo->map_vp_none[i] = i; + for (i = 0; i < 12; i++) + vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i; + for (i = 0; i < 4; i++) + vbo->map_vp_none[28+i] = i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + vbo->map_vp_arb[i] = i; + } + + /* By default: */ vbo->draw_prims = _tnl_draw_prims; @@ -82,5 +225,4 @@ void _vbo_DestroyContext( GLcontext *ctx ) FREE(vbo_context(ctx)); ctx->swtnl_im = NULL; - } diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 6b0f14d70ea..a20bfbd518b 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -60,6 +60,13 @@ void _vbo_DestroyContext( GLcontext *ctx ); struct vbo_context { + struct gl_client_array legacy_currval[16]; + struct gl_client_array generic_currval[16]; + struct gl_client_array mat_currval[16]; + + GLuint map_vp_none[32]; + GLuint map_vp_arb[32]; + struct vbo_exec_context exec; struct vbo_save_context save; diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c index 4499803b8c7..270e5201d35 100644 --- a/src/mesa/vbo/vbo_exec.c +++ b/src/mesa/vbo/vbo_exec.c @@ -38,119 +38,6 @@ #include "vbo_context.h" -#define NR_LEGACY_ATTRIBS 16 -#define NR_GENERIC_ATTRIBS 16 -#define NR_MAT_ATTRIBS 12 - -static void init_legacy_currval(GLcontext *ctx) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - struct gl_client_array *arrays = exec->legacy_currval; - GLuint i; - - memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS); - - /* Set up a constant (StrideB == 0) array for each current - * attribute: - */ - for (i = 0; i < NR_LEGACY_ATTRIBS; i++) { - struct gl_client_array *cl = &arrays[i]; - - switch (i) { - case VBO_ATTRIB_EDGEFLAG: - cl->Type = GL_UNSIGNED_BYTE; - cl->Ptr = (const void *)&ctx->Current.EdgeFlag; - break; - case VBO_ATTRIB_INDEX: - cl->Type = GL_FLOAT; - cl->Ptr = (const void *)&ctx->Current.Index; - break; - default: - cl->Type = GL_FLOAT; - cl->Ptr = (const void *)ctx->Current.Attrib[i]; - break; - } - - /* This will have to be determined at runtime: - */ - cl->Size = 1; - cl->Stride = 0; - cl->StrideB = 0; - cl->Enabled = 1; - cl->BufferObj = ctx->Array.NullBufferObj; - } -} - - -static void init_generic_currval(GLcontext *ctx) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - struct gl_client_array *arrays = exec->generic_currval; - GLuint i; - - memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); - - for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { - struct gl_client_array *cl = &arrays[i]; - - /* This will have to be determined at runtime: - */ - cl->Size = 1; - - cl->Type = GL_FLOAT; - cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; - cl->Stride = 0; - cl->StrideB = 0; - cl->Enabled = 1; - cl->BufferObj = ctx->Array.NullBufferObj; - } -} - - -static void init_mat_currval(GLcontext *ctx) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - struct gl_client_array *arrays = exec->mat_currval; - GLuint i; - - memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); - - /* Set up a constant (StrideB == 0) array for each current - * attribute: - */ - for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { - struct gl_client_array *cl = &arrays[i]; - - /* Size is fixed for the material attributes, for others will - * be determined at runtime: - */ - switch (i - VERT_ATTRIB_GENERIC0) { - case MAT_ATTRIB_FRONT_SHININESS: - case MAT_ATTRIB_BACK_SHININESS: - cl->Size = 1; - break; - case MAT_ATTRIB_FRONT_INDEXES: - case MAT_ATTRIB_BACK_INDEXES: - cl->Size = 3; - break; - default: - cl->Size = 4; - break; - } - - if (i < MAT_ATTRIB_MAX) - cl->Ptr = (const void *)ctx->Light.Material.Attrib[i]; - else - cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; - - cl->Type = GL_FLOAT; - cl->Stride = 0; - cl->StrideB = 0; - cl->Enabled = 1; - cl->BufferObj = ctx->Array.NullBufferObj; - } -} - void vbo_exec_init( GLcontext *ctx ) { @@ -167,10 +54,6 @@ void vbo_exec_init( GLcontext *ctx ) vbo_exec_vtx_init( exec ); vbo_exec_array_init( exec ); - init_legacy_currval( ctx ); - init_generic_currval( ctx ); - init_mat_currval( ctx ); - ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.FlushVertices = vbo_exec_FlushVertices; diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index 4542d2807cd..72855d267ed 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -75,10 +75,6 @@ struct vbo_exec_context GLcontext *ctx; GLvertexformat vtxfmt; - struct gl_client_array legacy_currval[16]; - struct gl_client_array generic_currval[16]; - struct gl_client_array mat_currval[16]; - struct { struct gl_buffer_object *bufferobj; GLubyte *buffer_map; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 5cfa7a01a96..b3650e26978 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -107,7 +107,8 @@ static void bind_array_obj( GLcontext *ctx ) static void recalculate_input_bindings( GLcontext *ctx ) { - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; const struct gl_client_array **inputs = &exec->array.inputs[0]; GLuint i; @@ -126,11 +127,11 @@ static void recalculate_input_bindings( GLcontext *ctx ) if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else - inputs[i] = &exec->legacy_currval[i]; + inputs[i] = &vbo->legacy_currval[i]; } for (i = 0; i < MAT_ATTRIB_MAX; i++) { - inputs[VERT_ATTRIB_GENERIC0 + i] = &exec->mat_currval[i]; + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; } break; case VP_NV: @@ -144,7 +145,7 @@ static void recalculate_input_bindings( GLcontext *ctx ) else if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else - inputs[i] = &exec->legacy_currval[i]; + inputs[i] = &vbo->legacy_currval[i]; } break; case VP_ARB: @@ -160,21 +161,21 @@ static void recalculate_input_bindings( GLcontext *ctx ) else if (exec->array.legacy_array[0]->Enabled) inputs[0] = exec->array.legacy_array[0]; else - inputs[0] = &exec->legacy_currval[0]; + inputs[0] = &vbo->legacy_currval[0]; for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else - inputs[i] = &exec->legacy_currval[i]; + inputs[i] = &vbo->legacy_currval[i]; } for (i = 0; i < 16; i++) { if (exec->array.generic_array[0]->Enabled) inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; else - inputs[VERT_ATTRIB_GENERIC0 + i] = &exec->generic_currval[i]; + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; } break; } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index f665c64c7ac..c1898aea497 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -132,25 +132,49 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) } + /* TODO: populate these as the vertex is defined: */ -static void vbo_exec_bind_arrays( struct vbo_exec_context *exec ) +static void vbo_exec_bind_arrays( GLcontext *ctx ) { + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *arrays = exec->vtx.arrays; GLuint count = exec->vtx.vert_count; GLubyte *data = exec->vtx.buffer_map; + const GLuint *map; GLuint attr; - memcpy(arrays, exec->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, exec->mat_currval, 16 * sizeof(arrays[0])); + /* Install the default (ie Current) attributes first, then overlay + * all active ones. + */ + switch (get_program_mode(exec->ctx)) { + case VP_NONE: + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, 16 * sizeof(arrays[0])); + 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. + */ + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + map = vbo->map_vp_arb; + break; + } /* Make all active attributes (including edgeflag) available as * arrays of floats. */ - for (attr = 0; attr < VBO_ATTRIB_MAX ; attr++) { - if (exec->vtx.attrsz[attr]) { + for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { + GLuint src = map[attr]; + + if (exec->vtx.attrsz[src]) { arrays[attr].Ptr = (void *)data; - arrays[attr].Size = exec->vtx.attrsz[attr]; + arrays[attr].Size = exec->vtx.attrsz[src]; arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; @@ -181,7 +205,7 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) if (exec->vtx.copied.nr != exec->vtx.vert_count) { GLcontext *ctx = exec->ctx; - vbo_exec_bind_arrays( exec ); + vbo_exec_bind_arrays( ctx ); vbo_context(ctx)->draw_prims( ctx, exec->vtx.inputs, diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 44e01712330..18c770a41cb 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -95,14 +95,36 @@ static void _playback_copy_to_current( GLcontext *ctx, /* Treat the vertex storage as a VBO, define vertex arrays pointing * into it: */ -static void vbo_bind_vertex_list( struct vbo_save_context *save, +static void vbo_bind_vertex_list( GLcontext *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 data = node->buffer_offset; + const GLuint *map; GLuint attr; - memset(arrays, 0, VBO_ATTRIB_MAX * sizeof(arrays[0])); + /* Install the default (ie Current) attributes first, then overlay + * all active ones. + */ + switch (get_program_mode(ctx)) { + case VP_NONE: + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, 16 * sizeof(arrays[0])); + 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. + */ + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + map = vbo->map_vp_arb; + break; + } for (attr = 0; attr <= VBO_ATTRIB_INDEX; attr++) { if (node->attrsz[attr]) { @@ -185,7 +207,7 @@ void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ) return; } - vbo_bind_vertex_list( save, node ); + vbo_bind_vertex_list( ctx, node ); vbo_context(ctx)->draw_prims( ctx, save->inputs, -- cgit v1.2.3 From 48f5deab94be832a782a440f55a7bc742d50a62f Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 30 Oct 2006 16:56:56 +0000 Subject: switch several dri drivers over --- src/mesa/drivers/dri/i810/i810context.c | 6 ++--- src/mesa/drivers/dri/i810/i810state.c | 4 ++-- src/mesa/drivers/dri/i915/i915_context.c | 5 ++-- src/mesa/drivers/dri/i915/intel_context.c | 8 +++---- src/mesa/drivers/dri/i965/brw_context.h | 1 - src/mesa/drivers/dri/i965/intel_context.c | 8 +++---- src/mesa/drivers/osmesa/osmesa.c | 3 ++- src/mesa/drivers/x11/xm_api.c | 2 +- src/mesa/drivers/x11/xm_dd.c | 1 + src/mesa/vbo/vbo.h | 40 +++++++++++++++++++++++++++++++ src/mesa/vbo/vbo_context.c | 3 ++- src/mesa/vbo/vbo_context.h | 3 --- 12 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 src/mesa/vbo/vbo.h (limited to 'src/mesa/vbo') diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c index c0f4efd7a31..db8f7a19a23 100644 --- a/src/mesa/drivers/dri/i810/i810context.c +++ b/src/mesa/drivers/dri/i810/i810context.c @@ -44,7 +44,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/t_pipeline.h" @@ -287,7 +287,7 @@ i810CreateContext( const __GLcontextModes *mesaVis, /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); - _ac_CreateContext( ctx ); + _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); @@ -350,7 +350,7 @@ i810DestroyContext(__DRIcontextPrivate *driContextPriv) release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1); _swsetup_DestroyContext( imesa->glCtx ); _tnl_DestroyContext( imesa->glCtx ); - _ac_DestroyContext( imesa->glCtx ); + _vbo_DestroyContext( imesa->glCtx ); _swrast_DestroyContext( imesa->glCtx ); i810FreeVB( imesa->glCtx ); diff --git a/src/mesa/drivers/dri/i810/i810state.c b/src/mesa/drivers/dri/i810/i810state.c index 6f9d4b5bd47..3ad25282d90 100644 --- a/src/mesa/drivers/dri/i810/i810state.c +++ b/src/mesa/drivers/dri/i810/i810state.c @@ -21,8 +21,8 @@ #include "i810ioctl.h" #include "swrast/swrast.h" -#include "array_cache/acache.h" #include "tnl/tnl.h" +#include "vbo/vbo.h" #include "swrast_setup/swrast_setup.h" #include "tnl/t_pipeline.h" @@ -953,7 +953,7 @@ static void i810InvalidateState( GLcontext *ctx, GLuint new_state ) { _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); I810_CONTEXT(ctx)->new_state |= new_state; } diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index 2f78fd60b21..6ec34e5bdef 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -36,7 +36,8 @@ #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" + #include "utils.h" #include "i915_reg.h" @@ -63,7 +64,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state ) { _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); _tnl_invalidate_vertex_state( ctx, new_state ); INTEL_CONTEXT(ctx)->NewGLState |= new_state; diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c index 4be95301c39..3d543b2485f 100644 --- a/src/mesa/drivers/dri/i915/intel_context.c +++ b/src/mesa/drivers/dri/i915/intel_context.c @@ -37,7 +37,7 @@ #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/t_pipeline.h" #include "tnl/t_vertex.h" @@ -228,7 +228,7 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state ) { _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); _tnl_invalidate_vertex_state( ctx, new_state ); INTEL_CONTEXT(ctx)->NewGLState |= new_state; @@ -305,7 +305,7 @@ GLboolean intelInitContext( intelContextPtr intel, /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); - _ac_CreateContext( ctx ); + _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); @@ -424,7 +424,7 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) release_texture_heaps = (intel->ctx.Shared->RefCount == 1); _swsetup_DestroyContext (&intel->ctx); _tnl_DestroyContext (&intel->ctx); - _ac_DestroyContext (&intel->ctx); + _vbo_DestroyContext (&intel->ctx); _swrast_DestroyContext (&intel->ctx); intel->Fallback = 0; /* don't call _swrast_Flush later */ diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 1137bfd2c76..e2279ca276b 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -36,7 +36,6 @@ #include "intel_context.h" #include "brw_structs.h" #include "imports.h" -#include "brw_attrib.h" /* Glossary: diff --git a/src/mesa/drivers/dri/i965/intel_context.c b/src/mesa/drivers/dri/i965/intel_context.c index 36edd7db7f5..c4c5488cbb1 100644 --- a/src/mesa/drivers/dri/i965/intel_context.c +++ b/src/mesa/drivers/dri/i965/intel_context.c @@ -37,7 +37,7 @@ #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/t_pipeline.h" #include "tnl/t_vertex.h" @@ -216,7 +216,7 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state ) _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); _tnl_invalidate_vertex_state( ctx, new_state ); @@ -322,7 +322,7 @@ GLboolean intelInitContext( struct intel_context *intel, /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); - _ac_CreateContext( ctx ); + _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); @@ -467,7 +467,7 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) release_texture_heaps = (intel->ctx.Shared->RefCount == 1); _swsetup_DestroyContext (&intel->ctx); _tnl_DestroyContext (&intel->ctx); - _ac_DestroyContext (&intel->ctx); + _vbo_DestroyContext (&intel->ctx); _swrast_DestroyContext (&intel->ctx); intel->Fallback = 0; /* don't call _swrast_Flush later */ diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index 42a1bb51233..c4fc8821e50 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -50,7 +50,7 @@ #include "tnl/t_context.h" #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" -#include "vbo/vbo_context.h" +#include "vbo/vbo.h" @@ -111,6 +111,7 @@ osmesa_update_state( GLcontext *ctx, GLuint new_state ) _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); } diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index 6fb0d9bbbd2..98a68dd4f4a 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -74,7 +74,7 @@ #include "renderbuffer.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" -#include "vbo/vbo_context.h" +#include "vbo/vbo.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index 39cec1dc9f8..87bd5e4a305 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -831,6 +831,7 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state ) */ _swrast_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); if (ctx->DrawBuffer->Name != 0) diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h new file mode 100644 index 00000000000..96b25f18ee6 --- /dev/null +++ b/src/mesa/vbo/vbo.h @@ -0,0 +1,40 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +#ifndef _VBO_H +#define _VBO_H + +GLboolean _vbo_CreateContext( GLcontext *ctx ); +void _vbo_DestroyContext( GLcontext *ctx ); +void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ); + + +#endif diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 29dfe09d997..5279b2e13c2 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -26,6 +26,7 @@ */ #include "mtypes.h" +#include "vbo.h" #include "vbo_context.h" #include "imports.h" #include "api_arrayelt.h" @@ -210,7 +211,7 @@ GLboolean _vbo_CreateContext( GLcontext *ctx ) return GL_TRUE; } -void vbo_save_invalidate_state( GLcontext *ctx, GLuint new_state ) +void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ) { _ae_invalidate_state(ctx, new_state); } diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index a20bfbd518b..982da004378 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -55,9 +55,6 @@ #include "vbo_save.h" #include "vbo_exec.h" -GLboolean _vbo_CreateContext( GLcontext *ctx ); -void _vbo_DestroyContext( GLcontext *ctx ); - struct vbo_context { struct gl_client_array legacy_currval[16]; -- cgit v1.2.3 From e8abd098b36c30d76b4c396970fd793ae58e0702 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 30 Oct 2006 17:12:05 +0000 Subject: Remove wakeup functions. This code is intended to be active all the time. --- src/mesa/vbo/vbo_context.c | 1 + src/mesa/vbo/vbo_exec.c | 23 +++++------------------ src/mesa/vbo/vbo_exec.h | 1 - src/mesa/vbo/vbo_save.c | 38 +++++++++++++------------------------- src/mesa/vbo/vbo_save.h | 2 -- 5 files changed, 19 insertions(+), 46 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 5279b2e13c2..291eb0bed3b 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -214,6 +214,7 @@ GLboolean _vbo_CreateContext( GLcontext *ctx ) void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ) { _ae_invalidate_state(ctx, new_state); + vbo_exec_invalidate_state(ctx, new_state); } diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c index 270e5201d35..7d958732479 100644 --- a/src/mesa/vbo/vbo_exec.c +++ b/src/mesa/vbo/vbo_exec.c @@ -37,8 +37,6 @@ #include "vbo_context.h" - - void vbo_exec_init( GLcontext *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; @@ -54,11 +52,15 @@ void vbo_exec_init( GLcontext *ctx ) vbo_exec_vtx_init( exec ); vbo_exec_array_init( exec ); + /* Hook our functions into exec and compile dispatch tables. + */ + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); + ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.FlushVertices = vbo_exec_FlushVertices; - exec->eval.recalculate_maps = 1; + vbo_exec_invalidate_state( ctx, ~0 ); } @@ -90,21 +92,6 @@ void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ) } -void vbo_exec_wakeup( GLcontext *ctx ) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - - ctx->Driver.FlushVertices = vbo_exec_FlushVertices; - ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; - - /* Hook our functions into exec and compile dispatch tables. - */ - _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); - - /* Assume we haven't been getting state updates either: - */ - vbo_exec_invalidate_state( ctx, ~0 ); -} diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index 72855d267ed..ef158de825a 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -146,7 +146,6 @@ void vbo_exec_init( GLcontext *ctx ); void vbo_exec_destroy( GLcontext *ctx ); void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ); void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ); -void vbo_exec_wakeup( GLcontext *ctx ); /* Internal functions: diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 0a5b7054005..3a97ea66a4f 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -35,6 +35,18 @@ +static void vbo_save_callback_init( GLcontext *ctx ) +{ + ctx->Driver.NewList = vbo_save_NewList; + ctx->Driver.EndList = vbo_save_EndList; + ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices; + ctx->Driver.BeginCallList = vbo_save_BeginCallList; + ctx->Driver.EndCallList = vbo_save_EndCallList; + ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; +} + + + void vbo_save_init( GLcontext *ctx ) { struct vbo_save_context *save = &vbo_context(ctx)->save; @@ -42,7 +54,7 @@ void vbo_save_init( GLcontext *ctx ) save->ctx = ctx; vbo_save_api_init( save ); - vbo_save_wakeup(ctx); + vbo_save_callback_init(ctx); ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; } @@ -68,27 +80,3 @@ void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ) } -/* I don't see any reason to swap this code out on fallbacks. It - * wouldn't really mean anything to do so anyway as the old lists are - * still around from pre-fallback. Instead, the above code ensures - * that vertices are routed back through immediate mode dispatch on - * fallback. - * - * The below can be moved into init or removed: - */ -void vbo_save_wakeup( GLcontext *ctx ) -{ - ctx->Driver.NewList = vbo_save_NewList; - ctx->Driver.EndList = vbo_save_EndList; - ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices; - ctx->Driver.BeginCallList = vbo_save_BeginCallList; - ctx->Driver.EndCallList = vbo_save_EndCallList; - ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; - - /* Assume we haven't been getting state updates either: - */ - vbo_save_invalidate_state( ctx, ~0 ); -} - - - diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index dbe5cafb999..5a644294112 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -150,8 +150,6 @@ struct vbo_save_context { void vbo_save_init( GLcontext *ctx ); void vbo_save_destroy( GLcontext *ctx ); -void vbo_save_wakeup( GLcontext *ctx ); -void vbo_save_invalidate_state( GLcontext *ctx, GLuint new_state ); void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ); /* save_loopback.c: -- cgit v1.2.3 From fd2756006a0baf63f60548d8f509de5b9a143608 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 30 Oct 2006 20:16:35 +0000 Subject: Move edgeflag into the VERT_ATTRIB_SEVEN slot. This means that our NV_vertex_program implementation has slightly incorrect aliasing behaviour. I think this is reasonable given the simplification and the fact that the mainstream ARB_vp continues to have the correct behaviour. --- src/mesa/main/api_noop.c | 2 +- src/mesa/main/context.c | 4 +-- src/mesa/main/get.c | 6 ++-- src/mesa/main/mtypes.h | 10 +++--- src/mesa/main/state.c | 4 +-- src/mesa/vbo/vbo_context.c | 57 +++++++++++++++++++-------------- src/mesa/vbo/vbo_context.h | 14 ++++++-- src/mesa/vbo/vbo_exec.h | 3 -- src/mesa/vbo/vbo_exec_api.c | 76 ++++++++++++++++++-------------------------- src/mesa/vbo/vbo_exec_draw.c | 2 +- src/mesa/vbo/vbo_save.c | 9 +++++- src/mesa/vbo/vbo_save_draw.c | 22 ++++++------- 12 files changed, 107 insertions(+), 102 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/main/api_noop.c b/src/mesa/main/api_noop.c index 33d44e43296..0c1a35361f1 100644 --- a/src/mesa/main/api_noop.c +++ b/src/mesa/main/api_noop.c @@ -45,7 +45,7 @@ static void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b ) { GET_CURRENT_CONTEXT(ctx); - ctx->Current.EdgeFlag = b; + ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] = (GLfloat)b; } static void GLAPIENTRY _mesa_noop_Indexf( GLfloat f ) diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index e0630c33d0b..15b69db5951 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -967,8 +967,8 @@ _mesa_init_current( GLcontext *ctx ) ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 ); ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 ); ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_FOG], 0.0, 0.0, 0.0, 0.0 ); - ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = 1.0; - ctx->Current.EdgeFlag = GL_TRUE; + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX], 1.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG], 1.0, 0.0, 0.0, 1.0 ); } diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 61a76d000b9..2a24b56974c 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -323,7 +323,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params ) case GL_EDGE_FLAG: { FLUSH_CURRENT(ctx, 0); - params[0] = ctx->Current.EdgeFlag; + params[0] = (ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F); } break; case GL_FEEDBACK_BUFFER_SIZE: @@ -2147,7 +2147,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params ) case GL_EDGE_FLAG: { FLUSH_CURRENT(ctx, 0); - params[0] = BOOLEAN_TO_FLOAT(ctx->Current.EdgeFlag); + params[0] = BOOLEAN_TO_FLOAT(ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F); } break; case GL_FEEDBACK_BUFFER_SIZE: @@ -3971,7 +3971,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params ) case GL_EDGE_FLAG: { FLUSH_CURRENT(ctx, 0); - params[0] = BOOLEAN_TO_INT(ctx->Current.EdgeFlag); + params[0] = BOOLEAN_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0F); } break; case GL_FEEDBACK_BUFFER_SIZE: diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 903779edae5..bc7c6b8026f 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -143,7 +143,7 @@ enum VERT_ATTRIB_COLOR1 = 4, VERT_ATTRIB_FOG = 5, VERT_ATTRIB_COLOR_INDEX = 6, - VERT_ATTRIB_SEVEN = 7, + VERT_ATTRIB_EDGEFLAG = 7, VERT_ATTRIB_TEX0 = 8, VERT_ATTRIB_TEX1 = 9, VERT_ATTRIB_TEX2 = 10, @@ -183,7 +183,7 @@ enum #define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1) #define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG) #define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX) -#define VERT_BIT_SEVEN (1 << VERT_ATTRIB_SEVEN) +#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG) #define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0) #define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1) #define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2) @@ -616,11 +616,11 @@ struct gl_current_attrib /** * \name Current vertex attributes. * \note Values are valid only after FLUSH_VERTICES has been called. + * \note Index and Edgeflag current values are stored as floats in the + * SIX and SEVEN attribute slots. */ /*@{*/ GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */ - GLfloat Index; /**< Current color index */ - GLboolean EdgeFlag; /**< Current edge flag */ /*@}*/ /** @@ -2604,7 +2604,7 @@ struct matrix_stack #define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1 #define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG #define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX -#define _NEW_ARRAY_EDGEFLAG VERT_BIT_SEVEN +#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG #define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0 #define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1 #define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2 diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 7dbcf8ad97d..d57217d9c4f 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -887,8 +887,8 @@ update_arrays( GLcontext *ctx ) /* 7 */ if (ctx->VertexProgram._Enabled - && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_SEVEN].Enabled) { - min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_SEVEN]._MaxElement); + && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { + min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement); } /* 8..15 */ diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 291eb0bed3b..165e32da8a8 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -61,27 +61,14 @@ static void init_legacy_currval(GLcontext *ctx) for (i = 0; i < NR_LEGACY_ATTRIBS; i++) { struct gl_client_array *cl = &arrays[i]; - switch (i) { - case VBO_ATTRIB_EDGEFLAG: - cl->Type = GL_UNSIGNED_BYTE; - cl->Ptr = (const void *)&ctx->Current.EdgeFlag; - break; - case VBO_ATTRIB_INDEX: - cl->Type = GL_FLOAT; - cl->Ptr = (const void *)&ctx->Current.Index; - break; - default: - cl->Type = GL_FLOAT; - cl->Ptr = (const void *)ctx->Current.Attrib[i]; - break; - } - - /* This will have to be determined at runtime: + /* Size will have to be determined at runtime: */ cl->Size = 1; cl->Stride = 0; cl->StrideB = 0; cl->Enabled = 1; + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[i]; cl->BufferObj = ctx->Array.NullBufferObj; } } @@ -118,12 +105,12 @@ static void init_mat_currval(GLcontext *ctx) struct gl_client_array *arrays = vbo->mat_currval; GLuint i; - memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS); /* Set up a constant (StrideB == 0) array for each current * attribute: */ - for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + for (i = 0; i < NR_MAT_ATTRIBS; i++) { struct gl_client_array *cl = &arrays[i]; /* Size is fixed for the material attributes, for others will @@ -156,7 +143,23 @@ static void init_mat_currval(GLcontext *ctx) } } +#if 0 +static void vbo_exec_current_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLint i; + + /* setup the pointers for the typical 16 vertex attributes */ + for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) + exec->vtx.current[i] = ctx->Current.Attrib[i]; + + /* setup pointers for the 12 material attributes */ + for (i = 0; i < MAT_ATTRIB_MAX; i++) + exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = + ctx->Light.Material.Attrib[i]; +} +#endif GLboolean _vbo_CreateContext( GLcontext *ctx ) { @@ -171,13 +174,11 @@ GLboolean _vbo_CreateContext( GLcontext *ctx ) return GL_FALSE; } - /* Hook our functions into exec and compile dispatch tables. These - * will pretty much be permanently installed, which means that the - * vtxfmt mechanism can be removed now. + /* TODO: remove these pointers. */ - vbo_exec_init( ctx ); - vbo_save_init( ctx ); - + vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS]; + vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0]; + vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT]; init_legacy_currval( ctx ); init_generic_currval( ctx ); @@ -207,6 +208,14 @@ GLboolean _vbo_CreateContext( GLcontext *ctx ) /* By default: */ vbo->draw_prims = _tnl_draw_prims; + + /* Hook our functions into exec and compile dispatch tables. These + * will pretty much be permanently installed, which means that the + * vtxfmt mechanism can be removed now. + */ + vbo_exec_init( ctx ); + vbo_save_init( ctx ); + return GL_TRUE; } diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 982da004378..cd024720232 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -57,13 +57,21 @@ struct vbo_context { - struct gl_client_array legacy_currval[16]; - struct gl_client_array generic_currval[16]; - struct gl_client_array mat_currval[16]; + struct gl_client_array currval[VBO_ATTRIB_MAX]; + + /* These point into the above. TODO: remove. + */ + struct gl_client_array *legacy_currval; + struct gl_client_array *generic_currval; + struct gl_client_array *mat_currval; GLuint map_vp_none[32]; GLuint map_vp_arb[32]; + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */ + GLfloat CurrentFloatEdgeFlag; + + struct vbo_exec_context exec; struct vbo_save_context save; diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index ef158de825a..e1fc7b27944 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -87,9 +87,6 @@ struct vbo_exec_context GLfloat *vbptr; /* cursor, points into buffer */ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */ - GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */ - GLfloat CurrentFloatEdgeFlag; - GLuint vert_count; GLuint max_vert; struct vbo_exec_copied_vtx copied; diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index c764c4d8b63..71fee8ca16e 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -130,17 +130,28 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) { GLcontext *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]) { + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + /* Note: the exec->vtx.current[i] pointers point into the * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. */ - COPY_CLEAN_4V(exec->vtx.current[i], + COPY_CLEAN_4V(current, exec->vtx.attrsz[i], exec->vtx.attrptr[i]); + + /* Given that we explicitly state size here, there is no need + * for the COPY_CLEAN above, could just copy 16 bytes and be + * done. The only problem is when Mesa accesses ctx->Current + * directly. + */ + vbo->currval[i].Size = exec->vtx.attrsz[i]; + /* This triggers rather too much recalculation of Mesa state * that doesn't get used (eg light positions). */ @@ -150,19 +161,6 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) } } - /* color index is special (it's not a float[4] so COPY_CLEAN_4V above - * will trash adjacent memory!) - */ - if (exec->vtx.attrsz[VBO_ATTRIB_INDEX]) { - ctx->Current.Index = exec->vtx.attrptr[VBO_ATTRIB_INDEX][0]; - } - - /* Edgeflag requires additional treatment: - */ - if (exec->vtx.attrsz[VBO_ATTRIB_EDGEFLAG]) { - ctx->Current.EdgeFlag = (exec->vtx.CurrentFloatEdgeFlag == 1.0); - } - /* Colormaterial -- this kindof sucks. */ if (ctx->Light.ColorMaterialEnabled && @@ -178,21 +176,19 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) { GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); GLint i; - /* Edgeflag requires additional treatment: - */ - exec->vtx.CurrentFloatEdgeFlag = - (GLfloat)ctx->Current.EdgeFlag; - - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; 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] = exec->vtx.current[i][3]; - case 3: exec->vtx.attrptr[i][2] = exec->vtx.current[i][2]; - case 2: exec->vtx.attrptr[i][1] = exec->vtx.current[i][1]; - case 1: exec->vtx.attrptr[i][0] = exec->vtx.current[i][0]; + 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; } + } ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; } @@ -205,6 +201,7 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, GLuint newsz ) { GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); GLint lastcount = exec->vtx.vert_count; GLfloat *tmp; GLuint oldsz; @@ -281,7 +278,8 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, data += oldsz; dest += newsz; } else { - COPY_SZ_4V( dest, newsz, exec->vtx.current[j] ); + const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; + COPY_SZ_4V( dest, newsz, current ); dest += newsz; } } @@ -627,27 +625,10 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) } -static void vbo_exec_current_init( struct vbo_exec_context *exec ) -{ - GLcontext *ctx = exec->ctx; - GLint i; - - /* setup the pointers for the typical 16 vertex attributes */ - for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) - exec->vtx.current[i] = ctx->Current.Attrib[i]; - - /* setup pointers for the 12 material attributes */ - for (i = 0; i < MAT_ATTRIB_MAX; i++) - exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = - ctx->Light.Material.Attrib[i]; - - exec->vtx.current[VBO_ATTRIB_INDEX] = &ctx->Current.Index; - exec->vtx.current[VBO_ATTRIB_EDGEFLAG] = &exec->vtx.CurrentFloatEdgeFlag; -} - void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); GLuint i; /* Allocate a buffer object. Will just reuse this object @@ -656,7 +637,6 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) exec->vtx.bufferobj = ctx->Array.NullBufferObj; exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); - vbo_exec_current_init( exec ); vbo_exec_vtxfmt_init( exec ); /* Hook our functions into the dispatch table. @@ -668,7 +648,13 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) exec->vtx.active_sz[i] = 0; exec->vtx.inputs[i] = &exec->vtx.arrays[i]; } - + + { + struct gl_client_array *arrays = exec->vtx.arrays; + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + } + exec->vtx.vertex_size = 0; } diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index c1898aea497..846d5dc196c 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -151,7 +151,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) switch (get_program_mode(exec->ctx)) { case VP_NONE: memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->mat_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); map = vbo->map_vp_none; break; case VP_NV: diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 3a97ea66a4f..e7f46879639 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -49,13 +49,20 @@ static void vbo_save_callback_init( GLcontext *ctx ) void vbo_save_init( GLcontext *ctx ) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_save_context *save = &vbo->save; save->ctx = ctx; vbo_save_api_init( save ); vbo_save_callback_init(ctx); + { + struct gl_client_array *arrays = save->arrays; + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + } + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 18c770a41cb..527e57d6bdb 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -41,7 +41,7 @@ static void _playback_copy_to_current( GLcontext *ctx, const struct vbo_save_vertex_list *node ) { - struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_context *vbo = vbo_context(ctx); GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex; GLuint i, offset; @@ -55,7 +55,14 @@ static void _playback_copy_to_current( GLcontext *ctx, for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; i++) { if (node->attrsz[i]) { - COPY_CLEAN_4V(save->current[i], node->attrsz[i], data); + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + + COPY_CLEAN_4V(current, + node->attrsz[i], + data); + + vbo->currval[i].Size = node->attrsz[i]; + data += node->attrsz[i]; if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && @@ -64,20 +71,11 @@ static void _playback_copy_to_current( GLcontext *ctx, } } - /* Edgeflag requires special treatment: - */ - if (node->attrsz[VBO_ATTRIB_EDGEFLAG]) { - ctx->Current.EdgeFlag = (data[0] == 1.0); - } - - -#if 1 /* Colormaterial -- this kindof sucks. */ if (ctx->Light.ColorMaterialEnabled) { _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); } -#endif /* CurrentExecPrimitive */ @@ -111,7 +109,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx, switch (get_program_mode(ctx)) { case VP_NONE: memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->mat_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); map = vbo->map_vp_none; break; case VP_NV: -- cgit v1.2.3 From 1f07439fe8c6803f70a27a1cdb9d76360ae40571 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 31 Oct 2006 11:39:57 +0000 Subject: move public structure definitions to vbo.h --- src/mesa/vbo/vbo.h | 28 ++++++++++++++++++++++++++++ src/mesa/vbo/vbo_attrib.h | 25 ------------------------- src/mesa/vbo/vbo_context.h | 1 + src/mesa/vbo/vbo_exec.h | 1 + src/mesa/vbo/vbo_save.h | 1 + 5 files changed, 31 insertions(+), 25 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 96b25f18ee6..80f7a3322bf 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -32,6 +32,34 @@ #ifndef _VBO_H #define _VBO_H +#include "mtypes.h" + +struct _mesa_prim { + GLuint mode:8; + GLuint indexed:1; + GLuint begin:1; + GLuint end:1; + GLuint weak:1; + GLuint pad:20; + + GLuint start; + GLuint count; +}; + +/* Would like to call this a "vbo_index_buffer", but this would be + * confusing as the indices are not neccessarily yet in a non-null + * buffer object. + */ +struct _mesa_index_buffer { + GLuint count; + GLenum type; + struct gl_buffer_object *obj; + const void *ptr; + GLuint rebase; +}; + + + GLboolean _vbo_CreateContext( GLcontext *ctx ); void _vbo_DestroyContext( GLcontext *ctx ); void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ); diff --git a/src/mesa/vbo/vbo_attrib.h b/src/mesa/vbo/vbo_attrib.h index caedbd5ea69..9de4fd06835 100644 --- a/src/mesa/vbo/vbo_attrib.h +++ b/src/mesa/vbo/vbo_attrib.h @@ -103,29 +103,4 @@ enum { #define VBO_MAX_COPIED_VERTS 3 -struct _mesa_prim { - GLuint mode:8; - GLuint indexed:1; - GLuint begin:1; - GLuint end:1; - GLuint weak:1; - GLuint pad:20; - - GLuint start; - GLuint count; -}; - -/* Would like to call this a "vbo_index_buffer", but this would be - * confusing as the indices are not neccessarily yet in a non-null - * buffer object. - */ -struct _mesa_index_buffer { - GLuint count; - GLenum type; - struct gl_buffer_object *obj; - const void *ptr; - GLuint rebase; -}; - - #endif diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index cd024720232..4c5ed96765b 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -51,6 +51,7 @@ #ifndef _VBO_CONTEXT_H #define _VBO_CONTEXT_H +#include "vbo.h" #include "vbo_attrib.h" #include "vbo_save.h" #include "vbo_exec.h" diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index e1fc7b27944..e28913b22af 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -35,6 +35,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define __VBO_EXEC_H__ #include "mtypes.h" +#include "vbo.h" #include "vbo_attrib.h" diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index 5a644294112..3051f5c59a1 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -35,6 +35,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define VBO_SAVE_H #include "mtypes.h" +#include "vbo.h" #include "vbo_attrib.h" -- cgit v1.2.3 From 18d52f96bb1f20b1887b67e87506835bca05d73a Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 2 Nov 2006 11:40:56 +0000 Subject: Fix typo in display list attrib binding. --- src/mesa/vbo/vbo_save_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 527e57d6bdb..ab3275ec94a 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -124,7 +124,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx, break; } - for (attr = 0; attr <= VBO_ATTRIB_INDEX; attr++) { + for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) { if (node->attrsz[attr]) { arrays[attr].Ptr = (const GLubyte *)data; arrays[attr].Size = node->attrsz[attr]; -- cgit v1.2.3 From 5a652f595716a82ebd79e33011f6082199c4b0d0 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 2 Nov 2006 18:00:43 +0000 Subject: Fill in missing input slots in the vertex-array + no-vertex-program path. --- src/mesa/vbo/vbo_exec_array.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index b3650e26978..481c4ee5469 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -81,7 +81,8 @@ static GLuint get_max_index( GLuint count, GLuint type, */ static void bind_array_obj( GLcontext *ctx ) { - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; GLuint i; /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array @@ -89,6 +90,7 @@ static void bind_array_obj( GLcontext *ctx ) * go away. */ exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex; + exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[i]; exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal; exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color; exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; @@ -133,6 +135,13 @@ static void recalculate_input_bindings( GLcontext *ctx ) for (i = 0; i < MAT_ATTRIB_MAX; i++) { inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; } + + /* Could use just about anything, just to fill in the empty + * slots: + */ + for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX; i++) + inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; + break; case VP_NV: /* NV_vertex_program - attribute arrays alias and override -- cgit v1.2.3 From 301acdf34ad01315f41c14638d92aa7fe0c2d2dc Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 2 Nov 2006 18:02:17 +0000 Subject: Similarly, fill in missing input slots in the vertex-array + NV_vertex_program path. --- src/mesa/vbo/vbo_exec_array.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 481c4ee5469..aab57486266 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -156,6 +156,13 @@ static void recalculate_input_bindings( GLcontext *ctx ) else inputs[i] = &vbo->legacy_currval[i]; } + + /* Could use just about anything, just to fill in the empty + * slots: + */ + for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) + inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; + break; case VP_ARB: /* ARB_vertex_program - Only the attribute zero (position) array -- cgit v1.2.3 From 01e238e5d51dabd28646356de825aa43a7290373 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 2 Nov 2006 19:02:04 +0000 Subject: Fix typo in last commit --- src/mesa/vbo/vbo_exec_array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index aab57486266..8f5c26920b9 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -90,7 +90,7 @@ static void bind_array_obj( GLcontext *ctx ) * go away. */ exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex; - exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[i]; + exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[VERT_ATTRIB_WEIGHT]; exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal; exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color; exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; -- cgit v1.2.3 From c3da1501b81a31e92f485ee9fbd99e60cc3a4337 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Fri, 3 Nov 2006 12:33:29 +0000 Subject: need to call bind_arrays() in vbo_exec_DrawRangeElements. --- src/mesa/vbo/vbo_exec_array.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 8f5c26920b9..803e58c1485 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -290,7 +290,9 @@ vbo_exec_DrawRangeElements(GLenum mode, if (ctx->NewState) _mesa_update_state( ctx ); - + + bind_arrays( ctx ); + ib.count = count; ib.type = type; ib.obj = ctx->Array.ElementArrayBufferObj; -- cgit v1.2.3 From dd60eaa6d9f61735141976db0e83d25176ac73c7 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 20 Nov 2006 11:49:58 +0000 Subject: Don't perform dangling attribute check on POS attribute. It can't by definition dangle (every vertex has a position). However save->currentsz isn't properly maintained for this attribute, as there is no current position value to track. Based on patch from Haihao Xiang. --- src/mesa/vbo/vbo_save_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 8ceba2b832b..efe018b09e2 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -527,7 +527,7 @@ static void _save_upgrade_vertex( GLcontext *ctx, /* Need to note this and fix up at runtime (or loopback): */ - if (save->currentsz[attr][0] == 0) { + if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { assert(oldsz == 0); save->dangling_attr_ref = GL_TRUE; } -- cgit v1.2.3 From a38cb37913b7cd2f9c3c7aa11dcbb9485d623924 Mon Sep 17 00:00:00 2001 From: keithw Date: Mon, 15 Jan 2007 11:52:58 +0000 Subject: New files to manage splitting drawing commands --- src/mesa/vbo/vbo_split.c | 161 ++++++++++++ src/mesa/vbo/vbo_split.h | 72 +++++ src/mesa/vbo/vbo_split_copy.c | 549 +++++++++++++++++++++++++++++++++++++++ src/mesa/vbo/vbo_split_inplace.c | 301 +++++++++++++++++++++ 4 files changed, 1083 insertions(+) create mode 100644 src/mesa/vbo/vbo_split.c create mode 100644 src/mesa/vbo/vbo_split.h create mode 100644 src/mesa/vbo/vbo_split_copy.c create mode 100644 src/mesa/vbo/vbo_split_inplace.c (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c new file mode 100644 index 00000000000..171859a18e0 --- /dev/null +++ b/src/mesa/vbo/vbo_split.c @@ -0,0 +1,161 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +/* Deal with hardware and/or swtnl maximums: + * - maximum number of vertices in buffer + * - maximum number of elements (maybe zero) + * + * The maximums may vary with opengl state (eg if a larger hardware + * vertex is required in this state, the maximum number of vertices + * may be smaller than in another state). + * + * We want buffer splitting to be a convenience function for the code + * actually drawing the primitives rather than a system-wide maximum, + * otherwise it is hard to avoid pessimism. + * + * For instance, if a driver has no hardware limits on vertex buffer + * dimensions, it would not ordinarily want to split vbos. But if + * there is an unexpected fallback, eg memory manager fails to upload + * textures, it will want to pass the drawing commands onto swtnl, + * which does have limitations. A convenience function allows swtnl + * to split the drawing and vbos internally without imposing its + * limitations on drivers which want to use it as a fallback path. + */ + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" + +#include "vbo_split.h" +#include "vbo.h" + +/* True if a primitive can be split without copying of vertices, false + * otherwise. + */ +GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr) +{ + switch (mode) { + case GL_POINTS: + *first = 1; + *incr = 1; + return GL_TRUE; + case GL_LINES: + *first = 2; + *incr = 2; + return GL_TRUE; + case GL_LINE_STRIP: + *first = 2; + *incr = 1; + return GL_TRUE; + case GL_TRIANGLES: + *first = 3; + *incr = 3; + return GL_TRUE; + case GL_TRIANGLE_STRIP: + *first = 3; + *incr = 1; + return GL_TRUE; + case GL_QUADS: + *first = 4; + *incr = 4; + return GL_TRUE; + case GL_QUAD_STRIP: + *first = 4; + *incr = 2; + return GL_TRUE; + default: + *first = 0; + *incr = 1; /* so that count % incr works */ + return GL_FALSE; + } +} + + + +void vbo_split_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + + if (ib) { + if (limits->max_indices == 0) { + /* Could traverse the indices, re-emitting vertices in turn. + * But it's hard to see why this case would be needed - for + * software tnl, it is better to convert to non-indexed + * rendering after transformation is complete, as is done in + * the t_dd_rendertmp.h templates. Are there any devices + * with hardware tnl that cannot do indexed rendering? + * + * For now, this path is disabled. + */ + assert(0); + } + else if (max_index - min_index > limits->max_verts) { + /* The vertex buffers are too large for hardware (or the + * swtnl module). Traverse the indices, re-emitting vertices + * in turn. Use a vertex cache to preserve some of the + * sharing from the original index list. + */ + vbo_split_copy(ctx, arrays, prim, nr_prims, ib, + draw, limits ); + } + else if (ib->count > limits->max_indices) { + /* The index buffer is too large for hardware. Try to split + * on whole-primitive boundaries, otherwise try to split the + * individual primitives. + */ + vbo_split_inplace(ctx, arrays, prim, nr_prims, ib, + min_index, max_index, draw, limits ); + } + else { + /* Why were we called? */ + assert(0); + } + } + else { + if (max_index - min_index >= limits->max_verts) { + /* The vertex buffer is too large for hardware (or the swtnl + * module). Try to split on whole-primitive boundaries, + * otherwise try to split the individual primitives. + */ + vbo_split_inplace(ctx, arrays, prim, nr_prims, ib, + min_index, max_index, draw, limits ); + } + else { + /* Why were we called? */ + assert(0); + } + } +} + diff --git a/src/mesa/vbo/vbo_split.h b/src/mesa/vbo/vbo_split.h new file mode 100644 index 00000000000..05888d048cb --- /dev/null +++ b/src/mesa/vbo/vbo_split.h @@ -0,0 +1,72 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +/** + * \mainpage The VBO splitter + * + * This is the private data used internally to the vbo_split_prims() + * helper function. Nobody outside the vbo_split* files needs to + * include or know about this structure. + */ + + +#ifndef _VBO_SPLIT_H +#define _VBO_SPLIT_H + +#include "vbo.h" + + +/* True if a primitive can be split without copying of vertices, false + * otherwise. + */ +GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr); + +void vbo_split_inplace( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ); + +/* Requires ib != NULL: + */ +void vbo_split_copy( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + vbo_draw_func draw, + const struct split_limits *limits ); + +#endif diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c new file mode 100644 index 00000000000..0adad71732f --- /dev/null +++ b/src/mesa/vbo/vbo_split_copy.c @@ -0,0 +1,549 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +/* Split indexed primitives with per-vertex copying. + */ + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "enums.h" +#include "mtypes.h" + +#include "vbo_split.h" +#include "vbo.h" + + +#define ELT_TABLE_SIZE 16 + +/* Used for vertex-level splitting of indexed buffers. Note that + * non-indexed primitives may be converted to indexed in some cases + * (eg loops, fans) in order to use this splitting path. + */ +struct copy_context { + + GLcontext *ctx; + const struct gl_client_array **array; + const struct _mesa_prim *prim; + GLuint nr_prims; + const struct _mesa_index_buffer *ib; + vbo_draw_func draw; + + const struct split_limits *limits; + + struct { + GLuint attr; + GLuint size; + const struct gl_client_array *array; + const GLubyte *src_ptr; + + struct gl_client_array dstarray; + + } varying[VERT_ATTRIB_MAX]; + GLuint nr_varying; + + const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX]; + struct _mesa_index_buffer dstib; + + GLuint *translated_elt_buf; + const GLuint *srcelt; + + /* A baby hash table to avoid re-emitting (some) duplicate + * vertices when splitting indexed primitives. + */ + struct { + GLuint in; + GLuint out; + } vert_cache[ELT_TABLE_SIZE]; + + + GLuint vertex_size; + GLubyte *dstbuf; + GLubyte *dstptr; /* dstptr == dstbuf + dstelt_max * vertsize */ + GLuint dstbuf_size; /* in vertices */ + GLuint dstbuf_nr; /* count of emitted vertices, also the + * largest value in dstelt. Our + * MaxIndex. + */ + + GLuint *dstelt; + GLuint dstelt_nr; + GLuint dstelt_size; + +#define MAX_PRIM 32 + struct _mesa_prim dstprim[MAX_PRIM]; + GLuint dstprim_nr; + +}; + + +static GLuint type_size( GLenum type ) +{ + switch(type) { + case GL_BYTE: return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + case GL_SHORT: return sizeof(GLshort); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_INT: return sizeof(GLint); + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_FLOAT: return sizeof(GLfloat); + case GL_DOUBLE: return sizeof(GLdouble); + default: return 0; + } +} + +static GLuint attr_size( const struct gl_client_array *array ) +{ + return array->Size * type_size(array->Type); +} + + +/* Starts returning true slightly before the buffer fills, to ensure + * that there is sufficient room for any remaining vertices to finish + * off the prim: + */ +static GLboolean check_flush( struct copy_context *copy ) +{ + if (copy->dstbuf_nr + 4 > copy->dstbuf_size) + return GL_TRUE; + + if (copy->dstelt_nr + 4 > copy->dstelt_size) + return GL_TRUE; + + return GL_FALSE; +} + +static void flush( struct copy_context *copy ) +{ + GLuint i; + + /* Set some counters: + */ + copy->dstib.count = copy->dstelt_nr; + + copy->draw( copy->ctx, + copy->dstarray_ptr, + copy->dstprim, + copy->dstprim_nr, + ©->dstib, + 0, + copy->dstbuf_nr ); + + /* Reset all pointers: + */ + copy->dstprim_nr = 0; + copy->dstelt_nr = 0; + copy->dstbuf_nr = 0; + copy->dstptr = copy->dstbuf; + + /* Clear the vertex cache: + */ + for (i = 0; i < ELT_TABLE_SIZE; i++) + copy->vert_cache[i].in = ~0; +} + + + +static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag ) +{ + struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; + + _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); + + prim->mode = mode; + prim->begin = begin_flag; +} + + +/* Use a hashtable to attempt to identify recently-emitted vertices + * and avoid re-emitting them. + */ +static GLuint elt(struct copy_context *copy, GLuint elt_idx) +{ + GLuint elt = copy->srcelt[elt_idx]; + GLuint slot = elt & (ELT_TABLE_SIZE-1); + + _mesa_printf("elt %d\n", elt); + + /* Look up the incoming element in the vertex cache. Re-emit if + * necessary. + */ + if (copy->vert_cache[slot].in != elt) { + GLubyte *csr = copy->dstptr; + GLuint i; + + _mesa_printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); + + for (i = 0; i < copy->nr_varying; i++) { + const struct gl_client_array *srcarray = copy->varying[i].array; + const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB; + + memcpy(csr, srcptr, copy->varying[i].size); + csr += copy->varying[i].size; + + { + const GLuint *f = (const GLuint *)srcptr; + GLuint j; + _mesa_printf(" varying %d: ", i); + for(j = 0; j < copy->varying[i].size / 4; j++) + _mesa_printf("%x ", f[j]); + _mesa_printf("\n"); + } + + } + + copy->vert_cache[slot].in = elt; + copy->vert_cache[slot].out = copy->dstbuf_nr++; + copy->dstptr += copy->vertex_size; + + assert(csr == copy->dstptr); + assert(copy->dstptr == (copy->dstbuf + + copy->dstbuf_nr * + copy->vertex_size)); + } + else + _mesa_printf(" --> reuse vertex\n"); + + _mesa_printf(" --> emit %d\n", copy->vert_cache[slot].out); + copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out; + return check_flush(copy); +} + +static void end( struct copy_context *copy, GLboolean end_flag ) +{ + struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; + + _mesa_printf("end (%d)\n", end_flag); + + prim->end = end_flag; + prim->count = copy->dstelt_nr - prim->start; + + if (++copy->dstprim_nr == MAX_PRIM || + check_flush(copy)) + flush(copy); +} + + + +static void replay_elts( struct copy_context *copy ) +{ + GLuint i, j, k; + GLboolean split; + + for (i = 0; i < copy->nr_prims; i++) { + const struct _mesa_prim *prim = ©->prim[i]; + const GLuint start = prim->start; + GLuint first, incr; + + switch (prim->mode) { + + case GL_LINE_LOOP: + /* Convert to linestrip and emit the final vertex explicitly, + * but only in the resultant strip that requires it. + */ + j = 0; + while (j != prim->count) { + begin(copy, GL_LINE_STRIP, prim->begin && j == 0); + + for (split = GL_FALSE; j != prim->count && !split; j++) + split = elt(copy, start + j); + + if (j == prim->count) { + /* Done, emit final line. Split doesn't matter as + * it is always raised a bit early so we can emit + * the last verts if necessary! + */ + if (prim->end) + (void)elt(copy, start + 0); + + end(copy, prim->end); + } + else { + /* Wrap + */ + assert(split); + end(copy, 0); + j--; + } + } + break; + + case GL_TRIANGLE_FAN: + case GL_POLYGON: + j = 2; + while (j != prim->count) { + begin(copy, prim->mode, prim->begin && j == 0); + + split = elt(copy, start+0); + assert(!split); + + split = elt(copy, start+j-1); + assert(!split); + + for (; j != prim->count && !split; j++) + split = elt(copy, start+j); + + end(copy, prim->end && j == prim->count); + + if (j != prim->count) { + /* Wrapped the primitive, need to repeat some vertices: + */ + j -= 1; + } + } + break; + + default: + (void)split_prim_inplace(prim->mode, &first, &incr); + + j = 0; + while (j != prim->count) { + + begin(copy, prim->mode, prim->begin && j == 0); + + split = 0; + for (k = 0; k < first; k++, j++) + split |= elt(copy, start+j); + + assert(!split); + + for (; j != prim->count && !split; ) + for (k = 0; k < incr; k++, j++) + split |= elt(copy, start+j); + + end(copy, prim->end && j == prim->count); + + if (j != prim->count) { + /* Wrapped the primitive, need to repeat some vertices: + */ + assert(j > first - incr); + j -= (first - incr); + } + } + break; + } + } + + if (copy->dstprim_nr) + flush(copy); +} + + +static void replay_init( struct copy_context *copy ) +{ + GLcontext *ctx = copy->ctx; + GLuint i; + GLuint offset; + + /* Make a list of varying attributes and their vbo's. Also + * calculate vertex size. + */ + copy->vertex_size = 0; + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + struct gl_buffer_object *vbo = copy->array[i]->BufferObj; + + if (copy->array[i]->StrideB == 0) { + copy->dstarray_ptr[i] = copy->array[i]; + } + else { + GLuint j = copy->nr_varying++; + + copy->varying[j].attr = i; + copy->varying[j].array = copy->array[i]; + copy->varying[j].size = attr_size(copy->array[i]); + copy->vertex_size += attr_size(copy->array[i]); + + if (vbo->Name && !vbo->Pointer) + ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, + GL_DYNAMIC_DRAW_ARB, /* XXX */ + vbo); + + copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, + copy->array[i]->Ptr); + + copy->dstarray_ptr[i] = ©->varying[j].dstarray; + } + } + + /* There must always be an index buffer. Currently require the + * caller convert non-indexed prims to indexed. Could alternately + * do it internally. + */ + if (copy->ib->obj->Name && !copy->ib->obj->Pointer) + ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* XXX */ + GL_DYNAMIC_DRAW_ARB, /* XXX */ + copy->ib->obj); + + switch (copy->ib->type) { + case GL_UNSIGNED_BYTE: + copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count); + copy->srcelt = copy->translated_elt_buf; + + for (i = 0; i < copy->ib->count; i++) + copy->translated_elt_buf[i] = ((const GLubyte *)copy->ib->ptr)[i]; + break; + + case GL_UNSIGNED_SHORT: + copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count); + copy->srcelt = copy->translated_elt_buf; + + for (i = 0; i < copy->ib->count; i++) + copy->translated_elt_buf[i] = ((const GLushort *)copy->ib->ptr)[i]; + break; + + case GL_UNSIGNED_INT: + copy->translated_elt_buf = NULL; + copy->srcelt = (const GLuint *)ADD_POINTERS(copy->ib->obj->Pointer, + copy->ib->ptr); + break; + } + + + /* Figure out the maximum allowed vertex buffer size: + */ + if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) { + copy->dstbuf_size = copy->limits->max_verts; + } + else { + copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size; + } + + /* Allocate an output vertex buffer: + * + * XXX: This should be a VBO! + */ + copy->dstbuf = _mesa_malloc(copy->dstbuf_size * + copy->vertex_size); + copy->dstptr = copy->dstbuf; + + /* Setup new vertex arrays to point into the output buffer: + */ + for (offset = 0, i = 0; i < copy->nr_varying; i++) { + const struct gl_client_array *src = copy->varying[i].array; + struct gl_client_array *dst = ©->varying[i].dstarray; + + dst->Size = src->Size; + dst->Type = src->Type; + dst->Stride = copy->vertex_size; + dst->StrideB = copy->vertex_size; + dst->Ptr = copy->dstbuf + offset; + dst->Enabled = GL_TRUE; + dst->Normalized = GL_TRUE; + dst->BufferObj = ctx->Array.NullBufferObj; + dst->_MaxElement = copy->dstbuf_size; /* may be less! */ + + offset += copy->varying[i].size; + } + + /* Allocate an output element list: + */ + copy->dstelt_size = MIN2(65536, + copy->ib->count * 2); + copy->dstelt_size = MIN2(copy->dstelt_size, + copy->limits->max_indices); + copy->dstelt = _mesa_malloc(copy->dstelt_size); + copy->dstelt_nr = 0; + + /* Setup the new index buffer to point to the allocated element + * list: + */ + copy->dstib.count = 0; /* duplicates dstelt_nr */ + copy->dstib.type = GL_UNSIGNED_INT; + copy->dstib.obj = ctx->Array.NullBufferObj; + copy->dstib.ptr = copy->dstelt; + copy->dstib.rebase = 0; +} + + +static void replay_finish( struct copy_context *copy ) +{ + GLcontext *ctx = copy->ctx; + GLuint i; + + /* Free our vertex and index buffers: + */ + _mesa_free(copy->translated_elt_buf); + _mesa_free(copy->dstbuf); + _mesa_free(copy->dstelt); + + /* Unmap VBO's + */ + for (i = 0; i < copy->nr_varying; i++) { + struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; + + if (vbo->Name && vbo->Pointer) + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vbo); + } + + /* Unmap index buffer: + */ + if (copy->ib->obj->Name && copy->ib->obj->Pointer) { + ctx->Driver.UnmapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* XXX */ + copy->ib->obj); + } +} + +void vbo_split_copy( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + struct copy_context copy; + GLuint i; + + memset(©, 0, sizeof(copy)); + + /* Require indexed primitives: + */ + assert(ib); + + copy.ctx = ctx; + copy.array = arrays; + copy.prim = prim; + copy.nr_prims = nr_prims; + copy.ib = ib; + copy.draw = draw; + copy.limits = limits; + + + /* Clear the vertex cache: + */ + for (i = 0; i < ELT_TABLE_SIZE; i++) + copy.vert_cache[i].in = ~0; + + + replay_init(©); + replay_elts(©); + replay_finish(©); +} diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c new file mode 100644 index 00000000000..66c94aceaa2 --- /dev/null +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -0,0 +1,301 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + + +#include "mtypes.h" +#include "macros.h" +#include "enums.h" +#include "vbo_split.h" + + +#define MAX_PRIM 32 + +/* Used for splitting without copying. + */ +struct split_context { + GLcontext *ctx; + const struct gl_client_array **array; + const struct _mesa_prim *prim; + GLuint nr_prims; + const struct _mesa_index_buffer *ib; + GLuint min_index; + GLuint max_index; + vbo_draw_func draw; + + const struct split_limits *limits; + +/* GLuint out_maxindex; */ +/* GLuint out_minindex; */ + + struct _mesa_prim dstprim[MAX_PRIM]; + GLuint dstprim_nr; +}; + + + + +static void flush_vertex( struct split_context *split ) +{ + GLint min_index, max_index; + + if (!split->dstprim_nr) + return; + + if (split->ib) { + /* This should basically be multipass rendering over the same + * unchanging set of VBO's. Would like the driver not to + * re-upload the data, or swtnl not to re-transform the + * vertices. + */ + assert(split->max_index - split->min_index < split->limits->max_verts); + min_index = split->min_index; + max_index = split->max_index; + } + else { + /* Non-indexed rendering. Cannot assume that the primitives are + * ordered by increasing vertex, because of entrypoints like + * MultiDrawArrays. + */ + GLuint i; + min_index = split->dstprim[0].start; + max_index = min_index + split->dstprim[0].count - 1; + + for (i = 1; i < split->dstprim_nr; i++) { + GLuint tmp_min = split->dstprim[i].start; + GLuint tmp_max = tmp_min + split->dstprim[i].count - 1; + + if (tmp_min < min_index) + min_index = tmp_min; + + if (tmp_max > max_index) + max_index = tmp_max; + } + } + + assert(max_index >= min_index); + + split->draw( split->ctx, + split->array, + split->dstprim, + split->dstprim_nr, + NULL, + min_index, + max_index); + + split->dstprim_nr = 0; +} + + +static struct _mesa_prim *next_outprim( struct split_context *split ) +{ + if (split->dstprim_nr == MAX_PRIM-1) { + flush_vertex(split); + } + + { + struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++]; + memset(prim, 0, sizeof(*prim)); + return prim; + } +} + +static int align(int value, int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + + + +/* Break large primitives into smaller ones. If not possible, convert + * the primitive to indexed and pass to split_elts(). + */ +static void split_prims( struct split_context *split) +{ + GLuint csr = 0; + GLuint i; + + for (i = 0; i < split->nr_prims; i++) { + const struct _mesa_prim *prim = &split->prim[i]; + GLuint first, incr; + GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr); + GLuint count; + + /* Always wrap on an even numbered vertex to avoid problems with + * triangle strips. + */ + GLuint available = align(split->limits->max_verts - csr - 1, 2); + assert(split->limits->max_verts >= csr); + + _mesa_printf("%s: prim %d: %s %d..%d\n", __FUNCTION__, + i, + _mesa_lookup_enum_by_nr(prim->mode), + prim->start, prim->count); + + _mesa_printf("a: available %d\n", available); + + if (prim->count < first) + continue; + + count = prim->count - (prim->count - first) % incr; + + + if ((available < count && !split_inplace) || + (available < first && split_inplace)) { + flush_vertex(split); + csr = 0; + available = align(split->limits->max_verts - csr - 1, 2); + } + + _mesa_printf("b: available %d\n", available); + + if (available >= count) { + struct _mesa_prim *outprim = next_outprim(split); + *outprim = *prim; + csr += prim->count; + available = align(split->limits->max_verts - csr - 1, 2); + } + else if (0 && split_inplace) { + GLuint j, nr; + + + for (j = 0 ; j < count ; ) { + GLuint remaining = count - j; + struct _mesa_prim *outprim = next_outprim(split); + + nr = MIN2( available, remaining ); + + nr -= (nr - first) % incr; + + outprim->mode = prim->mode; + outprim->begin = (j == 0 && prim->begin); + outprim->end = (nr == remaining && prim->end); + outprim->start = prim->start + j; + outprim->count = nr; + + if (nr == remaining) { + /* Finished. + */ + j += nr; + csr += nr; + available = align(split->limits->max_verts - csr - 1, 2); + } + else { + /* Wrapped the primitive: + */ + _mesa_printf("wrap %d %d\n", nr, first-incr); + + j += nr - (first - incr); + flush_vertex(split); + csr = 0; + available = align(split->limits->max_verts - csr - 1, 2); + } + } + } + else if (split->ib == NULL) { + /* XXX: could at least send the first max_verts off from the + * inplace buffers. + */ + + /* else convert to indexed primitive and pass to split_elts, + * which will do the necessary copying and turn it back into a + * vertex primitive for rendering... + */ + struct _mesa_index_buffer ib; + struct _mesa_prim tmpprim; + GLuint *elts = malloc(count * sizeof(GLuint)); + GLuint j; + + for (j = 0; j < count; j++) + elts[j] = prim->start + j; + + ib.count = count; + ib.type = GL_UNSIGNED_INT; + ib.obj = split->ctx->Array.NullBufferObj; + ib.ptr = elts; + ib.rebase = 0; /* ? */ + + tmpprim = *prim; + tmpprim.indexed = 1; + tmpprim.start = 0; + tmpprim.count = count; + + flush_vertex(split); + + vbo_split_copy(split->ctx, + split->array, + &tmpprim, 1, + &ib, + split->draw, + split->limits); + + free(elts); + } + else { + flush_vertex(split); + + vbo_split_copy(split->ctx, + split->array, + prim, 1, + split->ib, + split->draw, + split->limits); + } + } + + flush_vertex(split); +} + + +void vbo_split_inplace( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + struct split_context split; + + memset(&split, 0, sizeof(split)); + + split.ctx = ctx; + split.array = arrays; + split.prim = prim; + split.nr_prims = nr_prims; + split.ib = ib; + split.min_index = min_index; + split.max_index = max_index; + split.draw = draw; + split.limits = limits; + + split_prims( &split ); +} + + -- cgit v1.2.3 From 1b7c24c33c43e2c0db391735b2f2ca0026459cc9 Mon Sep 17 00:00:00 2001 From: keithw Date: Mon, 15 Jan 2007 11:58:06 +0000 Subject: Hook in split functionality --- src/mesa/vbo/vbo.h | 36 ++++++++++++++++++++++++++++++++++++ src/mesa/vbo/vbo_context.h | 8 +------- 2 files changed, 37 insertions(+), 7 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 80f7a3322bf..c81d83f9b61 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -65,4 +65,40 @@ void _vbo_DestroyContext( GLcontext *ctx ); void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ); +typedef void (*vbo_draw_func)( GLcontext *ctx, + const struct gl_client_array **arrays, + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index ); + + + + +/* Utility function to cope with various constraints on tnl modules or + * hardware. This can be used to split an incoming set of arrays and + * primitives against the following constraints: + * - Maximum number of indices in index buffer. + * - Maximum number of vertices referenced by index buffer. + * - Maximum hardware vertex buffer size. + */ +struct split_limits { + GLuint max_verts; + GLuint max_indices; + GLuint max_vb_size; /* bytes */ +}; + + +void vbo_split_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ); + + #endif diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h index 4c5ed96765b..0dc1019b39f 100644 --- a/src/mesa/vbo/vbo_context.h +++ b/src/mesa/vbo/vbo_context.h @@ -79,13 +79,7 @@ struct vbo_context { /* Callback into the driver. This must always succeed, the driver * is responsible for initiating any fallback actions required: */ - void (*draw_prims)( GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prims, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLuint min_index, - GLuint max_index ); + vbo_draw_func draw_prims; }; -- cgit v1.2.3 From 2421b25dd777ebfd614ae45907fd4af8c2713102 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 15 Jan 2007 13:40:38 +0000 Subject: Remove special-case handling for index and edgeflag This isn't required with the changes to core mesa and the new attribute layout. --- src/mesa/vbo/vbo_attrib_tmp.h | 5 +- src/mesa/vbo/vbo_exec_array.c | 6 +- src/mesa/vbo/vbo_save.h | 2 - src/mesa/vbo/vbo_save_api.c | 44 ++++-------- src/mesa/vbo/vbo_save_loopback.c | 148 ++------------------------------------- 5 files changed, 24 insertions(+), 181 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h index 72a8b04aca1..ff11c7d59a7 100644 --- a/src/mesa/vbo/vbo_attrib_tmp.h +++ b/src/mesa/vbo/vbo_attrib_tmp.h @@ -357,9 +357,10 @@ static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index, } -/* Although we don't export NV_vertex_program, these entrypoints are +/* In addition to supporting NV_vertex_program, these entrypoints are * used by the display list and other code specifically because of - * their property of aliasing with other attributes. + * their property of aliasing with other attributes. (See + * vbo_save_loopback.c) */ static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x ) { diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 803e58c1485..15fbdcf8a56 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -96,10 +96,10 @@ static void bind_array_obj( GLcontext *ctx ) exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord; exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index; - exec->array.legacy_array[VBO_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; + exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; for (i = 0; i < 8; i++) - exec->array.legacy_array[VBO_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; + exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; for (i = 0; i < VERT_ATTRIB_MAX; i++) exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i]; @@ -117,8 +117,6 @@ static void recalculate_input_bindings( GLcontext *ctx ) exec->array.program_mode = get_program_mode(ctx); exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; - /* TODO: Get rid of NV_program (please!). - */ switch (exec->array.program_mode) { case VP_NONE: /* When no vertex program is active, we put the material values diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index 3051f5c59a1..b81f275a602 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -142,8 +142,6 @@ struct vbo_save_context { struct vbo_save_copied_vtx copied; - GLfloat CurrentFloatEdgeFlag; - GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */ GLubyte *currentsz[VBO_ATTRIB_MAX]; }; diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index efe018b09e2..f339436f84c 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -415,26 +415,14 @@ static void _save_copy_to_current( GLcontext *ctx ) struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint i; - for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; 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->attrsz[i], + save->attrptr[i]); } } - - /* Edgeflag requires special treatment: - * - * TODO: change edgeflag to GLfloat in Mesa. - */ - if (save->attrsz[VBO_ATTRIB_EDGEFLAG]) { - ctx->ListState.ActiveEdgeFlag = 1; - save->CurrentFloatEdgeFlag = - save->attrptr[VBO_ATTRIB_EDGEFLAG][0]; - ctx->ListState.CurrentEdgeFlag = - (save->CurrentFloatEdgeFlag == 1.0); - } } @@ -443,7 +431,7 @@ static void _save_copy_from_current( GLcontext *ctx ) struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i; - for (i = VBO_ATTRIB_POS+1 ; i <= VBO_ATTRIB_INDEX ; 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]; @@ -451,12 +439,6 @@ static void _save_copy_from_current( GLcontext *ctx ) case 1: save->attrptr[i][0] = save->current[i][0]; case 0: break; } - - /* Edgeflag requires special treatment: - */ - if (save->attrsz[VBO_ATTRIB_EDGEFLAG]) { - save->CurrentFloatEdgeFlag = (GLfloat)ctx->ListState.CurrentEdgeFlag; - save->attrptr[VBO_ATTRIB_EDGEFLAG][0] = save->CurrentFloatEdgeFlag; } } @@ -616,6 +598,8 @@ do { \ if (save->active_sz[A] != N) \ save_fixup_vertex(ctx, A, N); \ \ + _mesa_printf("Attr %d, sz %d: %f %f %f %f\n", A, N, V0, V1, V2, V3 ); \ + \ { \ GLfloat *dest = save->attrptr[A]; \ if (N>0) dest[0] = V0; \ @@ -1106,23 +1090,19 @@ static void _save_current_init( GLcontext *ctx ) struct vbo_save_context *save = &vbo_context(ctx)->save; GLint i; - for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) { - save->currentsz[i] = &ctx->ListState.ActiveAttribSize[i]; - save->current[i] = ctx->ListState.CurrentAttrib[i]; + for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) { + const GLuint j = i - VBO_ATTRIB_POS; + ASSERT(j < VERT_ATTRIB_MAX); + save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j]; + save->current[i] = ctx->ListState.CurrentAttrib[j]; } - for (i = VBO_ATTRIB_FIRST_MATERIAL; i < VBO_ATTRIB_INDEX; i++) { + for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_MAT_FRONT_AMBIENT; i++) { const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL; ASSERT(j < MAT_ATTRIB_MAX); save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j]; save->current[i] = ctx->ListState.CurrentMaterial[j]; } - - save->currentsz[VBO_ATTRIB_INDEX] = &ctx->ListState.ActiveIndex; - save->current[VBO_ATTRIB_INDEX] = &ctx->ListState.CurrentIndex; - - save->currentsz[VBO_ATTRIB_EDGEFLAG] = &ctx->ListState.ActiveEdgeFlag; - save->current[VBO_ATTRIB_EDGEFLAG] = &save->CurrentFloatEdgeFlag; } /** diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c index 941c4beea94..2c28126cab2 100644 --- a/src/mesa/vbo/vbo_save_loopback.c +++ b/src/mesa/vbo/vbo_save_loopback.c @@ -44,7 +44,9 @@ typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); -/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */ +/* This file makes heavy use of the aliasing of NV vertex attributes + * with the legacy attributes. + */ static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) { CALL_VertexAttrib1fvNV(ctx->Exec, (target, v)); @@ -72,118 +74,6 @@ static attr_func vert_attrfunc[4] = { VertexAttrib4fvNV }; -#if 0 -static void VertexAttrib1fvARB(GLcontext *ctx, GLint target, const GLfloat *v) -{ - CALL_VertexAttrib1fvARB(ctx->Exec, (target, v)); -} - -static void VertexAttrib2fvARB(GLcontext *ctx, GLint target, const GLfloat *v) -{ - CALL_VertexAttrib2fvARB(ctx->Exec, (target, v)); -} - -static void VertexAttrib3fvARB(GLcontext *ctx, GLint target, const GLfloat *v) -{ - CALL_VertexAttrib3fvARB(ctx->Exec, (target, v)); -} - -static void VertexAttrib4fvARB(GLcontext *ctx, GLint target, const GLfloat *v) -{ - CALL_VertexAttrib4fvARB(ctx->Exec, (target, v)); -} - - -static attr_func vert_attrfunc_arb[4] = { - VertexAttrib1fvARB, - VertexAttrib2fvARB, - VertexAttrib3fvARB, - VertexAttrib4fvARB -}; -#endif - - - - - - -static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v ) -{ - switch (target) { - case VBO_ATTRIB_MAT_FRONT_SHININESS: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SHININESS, v )); - break; - case VBO_ATTRIB_MAT_BACK_SHININESS: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SHININESS, v )); - break; - } -} - - -static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v ) -{ - switch (target) { - case VBO_ATTRIB_MAT_FRONT_INDEXES: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_COLOR_INDEXES, v )); - break; - case VBO_ATTRIB_MAT_BACK_INDEXES: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_COLOR_INDEXES, v )); - break; - } -} - - -static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v ) -{ - switch (target) { - case VBO_ATTRIB_MAT_FRONT_EMISSION: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_EMISSION, v )); - break; - case VBO_ATTRIB_MAT_BACK_EMISSION: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_EMISSION, v )); - break; - case VBO_ATTRIB_MAT_FRONT_AMBIENT: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_AMBIENT, v )); - break; - case VBO_ATTRIB_MAT_BACK_AMBIENT: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_AMBIENT, v )); - break; - case VBO_ATTRIB_MAT_FRONT_DIFFUSE: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_DIFFUSE, v )); - break; - case VBO_ATTRIB_MAT_BACK_DIFFUSE: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_DIFFUSE, v )); - break; - case VBO_ATTRIB_MAT_FRONT_SPECULAR: - CALL_Materialfv(ctx->Exec, ( GL_FRONT, GL_SPECULAR, v )); - break; - case VBO_ATTRIB_MAT_BACK_SPECULAR: - CALL_Materialfv(ctx->Exec, ( GL_BACK, GL_SPECULAR, v )); - break; - } -} - - -static attr_func mat_attrfunc[4] = { - mat_attr1fv, - NULL, - mat_attr3fv, - mat_attr4fv -}; - - -static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) -{ - (void) target; - CALL_Indexf(ctx->Exec, (v[0])); -} - -static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) -{ - (void) target; - CALL_EdgeFlag(ctx->Exec, ((GLboolean)(v[0] == 1.0))); -} - struct loopback_attr { GLint target; GLint sz; @@ -277,7 +167,10 @@ void vbo_loopback_vertex_list( GLcontext *ctx, struct loopback_attr la[VBO_ATTRIB_MAX]; GLuint i, nr = 0; - for (i = 0 ; i <= VBO_ATTRIB_TEX7 ; i++) { + /* All Legacy, NV, ARB and Material attributes are routed through + * the NV attributes entrypoints: + */ + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { if (attrsz[i]) { la[nr].target = i; la[nr].sz = attrsz[i]; @@ -286,33 +179,6 @@ void vbo_loopback_vertex_list( GLcontext *ctx, } } - for (i = VBO_ATTRIB_MAT_FRONT_AMBIENT ; - i <= VBO_ATTRIB_MAT_BACK_INDEXES ; - i++) { - if (attrsz[i]) { - la[nr].target = i; - la[nr].sz = attrsz[i]; - la[nr].func = mat_attrfunc[attrsz[i]-1]; - nr++; - } - } - - if (attrsz[VBO_ATTRIB_EDGEFLAG]) { - la[nr].target = VBO_ATTRIB_EDGEFLAG; - la[nr].sz = attrsz[VBO_ATTRIB_EDGEFLAG]; - la[nr].func = edgeflag_attr1fv; - nr++; - } - - if (attrsz[VBO_ATTRIB_INDEX]) { - la[nr].target = VBO_ATTRIB_INDEX; - la[nr].sz = attrsz[VBO_ATTRIB_INDEX]; - la[nr].func = index_attr1fv; - nr++; - } - - /* XXX ARB vertex attribs */ - for (i = 0 ; i < prim_count ; i++) { if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) && (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)) -- cgit v1.2.3 From 82152a2a8e1afeb61710318e769b1379be6c02c6 Mon Sep 17 00:00:00 2001 From: keithw Date: Mon, 15 Jan 2007 14:10:42 +0000 Subject: Remove debug, reenable inplace splitting. --- src/mesa/tnl/t_draw.c | 16 +++++++++------- src/mesa/vbo/vbo_save_api.c | 2 -- src/mesa/vbo/vbo_save_loopback.c | 3 ++- src/mesa/vbo/vbo_split_inplace.c | 16 +--------------- 4 files changed, 12 insertions(+), 25 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 25b8708948e..0e7c2b6a689 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -375,7 +375,6 @@ void _tnl_draw_prims( GLcontext *ctx, TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLint max = VB->Size; - GLuint i; #ifdef TEST_SPLIT max = 8 + MAX_CLIPPED_VERTICES; @@ -387,12 +386,15 @@ void _tnl_draw_prims( GLcontext *ctx, VB->Elts = NULL; #if 0 - _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); - for (i = 0; i < nr_prims; i++) - _mesa_printf("prim %d: %s start %d count %d\n", i, - _mesa_lookup_enum_by_nr(prim[i].mode), - prim[i].start, - prim[i].count); + { + GLuint i; + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + for (i = 0; i < nr_prims; i++) + _mesa_printf("prim %d: %s start %d count %d\n", i, + _mesa_lookup_enum_by_nr(prim[i].mode), + prim[i].start, + prim[i].count); + } #endif /* The software TNL pipeline has a fixed amount of storage for diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index f339436f84c..ade48d220e6 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -598,8 +598,6 @@ do { \ if (save->active_sz[A] != N) \ save_fixup_vertex(ctx, A, N); \ \ - _mesa_printf("Attr %d, sz %d: %f %f %f %f\n", A, N, V0, V1, V2, V3 ); \ - \ { \ GLfloat *dest = save->attrptr[A]; \ if (N>0) dest[0] = V0; \ diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c index 2c28126cab2..430333b84dd 100644 --- a/src/mesa/vbo/vbo_save_loopback.c +++ b/src/mesa/vbo/vbo_save_loopback.c @@ -45,7 +45,8 @@ typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); /* This file makes heavy use of the aliasing of NV vertex attributes - * with the legacy attributes. + * with the legacy attributes, and also with ARB and Material + * attributes as currently implemented. */ static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) { diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c index 66c94aceaa2..d3649c59db3 100644 --- a/src/mesa/vbo/vbo_split_inplace.c +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -49,9 +49,6 @@ struct split_context { const struct split_limits *limits; -/* GLuint out_maxindex; */ -/* GLuint out_minindex; */ - struct _mesa_prim dstprim[MAX_PRIM]; GLuint dstprim_nr; }; @@ -151,13 +148,6 @@ static void split_prims( struct split_context *split) GLuint available = align(split->limits->max_verts - csr - 1, 2); assert(split->limits->max_verts >= csr); - _mesa_printf("%s: prim %d: %s %d..%d\n", __FUNCTION__, - i, - _mesa_lookup_enum_by_nr(prim->mode), - prim->start, prim->count); - - _mesa_printf("a: available %d\n", available); - if (prim->count < first) continue; @@ -171,15 +161,13 @@ static void split_prims( struct split_context *split) available = align(split->limits->max_verts - csr - 1, 2); } - _mesa_printf("b: available %d\n", available); - if (available >= count) { struct _mesa_prim *outprim = next_outprim(split); *outprim = *prim; csr += prim->count; available = align(split->limits->max_verts - csr - 1, 2); } - else if (0 && split_inplace) { + else if (split_inplace) { GLuint j, nr; @@ -207,8 +195,6 @@ static void split_prims( struct split_context *split) else { /* Wrapped the primitive: */ - _mesa_printf("wrap %d %d\n", nr, first-incr); - j += nr - (first - incr); flush_vertex(split); csr = 0; -- cgit v1.2.3 From 50f76b9d9b4b17940798b44233b9b5af2f932117 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 15 Jan 2007 14:20:21 +0000 Subject: Correctly initialize current attribute sizes. Some legacy attributes (eg color) have an initial value other than {0,0,0,1} which means that their initial size != 1 either. --- src/mesa/vbo/vbo_context.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c index 165e32da8a8..65998e7ff75 100644 --- a/src/mesa/vbo/vbo_context.c +++ b/src/mesa/vbo/vbo_context.c @@ -47,6 +47,14 @@ extern void _tnl_draw_prims( GLcontext *ctx, #define NR_GENERIC_ATTRIBS 16 #define NR_MAT_ATTRIBS 12 +static GLuint check_size( const GLfloat *attr ) +{ + if (attr[3] != 1.0) return 4; + if (attr[2] != 0.0) return 3; + if (attr[1] != 0.0) return 2; + return 1; +} + static void init_legacy_currval(GLcontext *ctx) { struct vbo_context *vbo = vbo_context(ctx); @@ -63,7 +71,7 @@ static void init_legacy_currval(GLcontext *ctx) /* Size will have to be determined at runtime: */ - cl->Size = 1; + cl->Size = check_size(ctx->Current.Attrib[i]); cl->Stride = 0; cl->StrideB = 0; cl->Enabled = 1; @@ -88,7 +96,6 @@ static void init_generic_currval(GLcontext *ctx) /* This will have to be determined at runtime: */ cl->Size = 1; - cl->Type = GL_FLOAT; cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; cl->Stride = 0; -- cgit v1.2.3 From 584def75ad8dd13add5b4ed7e364d13202539539 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 15 Jan 2007 16:57:01 +0000 Subject: Remove unused index buffer. --- src/mesa/vbo/vbo_exec.h | 3 --- src/mesa/vbo/vbo_exec_array.c | 8 +------- 2 files changed, 1 insertion(+), 10 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h index e28913b22af..a9b01e08e6a 100644 --- a/src/mesa/vbo/vbo_exec.h +++ b/src/mesa/vbo/vbo_exec.h @@ -130,9 +130,6 @@ struct vbo_exec_context * programs: */ const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; - - - struct gl_buffer_object *index_obj; } array; }; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 15fbdcf8a56..cec353cf43b 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -360,8 +360,6 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind void vbo_exec_array_init( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; - #if 1 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; exec->vtxfmt.DrawElements = vbo_exec_DrawElements; @@ -371,14 +369,10 @@ void vbo_exec_array_init( struct vbo_exec_context *exec ) exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; #endif - - exec->array.index_obj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); } void vbo_exec_array_destroy( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; - - ctx->Driver.DeleteBuffer(ctx, exec->array.index_obj); + /* nothing to do */ } -- cgit v1.2.3 From 2cb3594af9cd1434aa2c408cd6f8d51bcd12e8ea Mon Sep 17 00:00:00 2001 From: Aapo Tahkola Date: Thu, 18 Jan 2007 04:17:56 +0200 Subject: Fix invalid enums passed to MapBuffer --- src/mesa/vbo/vbo_exec_array.c | 2 +- src/mesa/vbo/vbo_save_api.c | 2 +- src/mesa/vbo/vbo_split_copy.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index cec353cf43b..e0a6240c2a6 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -334,7 +334,7 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind if (ctx->Array.ElementArrayBufferObj->Name) { const GLvoid *map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, - GL_DYNAMIC_READ_ARB, + GL_READ_ONLY, ctx->Array.ElementArrayBufferObj); max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index f718cdd91a7..c08fd1fe555 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -198,7 +198,7 @@ static GLfloat *map_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store * assert(!vertex_store->buffer); vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB, /* not used */ - GL_STATIC_DRAW_ARB, /* not used */ + GL_WRITE_ONLY, /* not used */ vertex_store->bufferobj); assert(vertex_store->buffer); diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index 08eae2db40f..fff733ccb53 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -382,7 +382,7 @@ static void replay_init( struct copy_context *copy ) if (vbo->Name && !vbo->Pointer) ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB, - GL_DYNAMIC_DRAW_ARB, /* XXX */ + GL_WRITE_ONLY, /* XXX */ vbo); copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, @@ -399,7 +399,7 @@ static void replay_init( struct copy_context *copy ) if (copy->ib->obj->Name && !copy->ib->obj->Pointer) ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB, /* XXX */ - GL_DYNAMIC_DRAW_ARB, /* XXX */ + GL_WRITE_ONLY, /* XXX */ copy->ib->obj); switch (copy->ib->type) { -- cgit v1.2.3 From a3b4b1173950599785e4f05278e868180a2bf387 Mon Sep 17 00:00:00 2001 From: Aapo Tahkola Date: Thu, 18 Jan 2007 04:46:04 +0200 Subject: Fix invalid enums passed to MapBuffer --- src/mesa/vbo/vbo_save_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index daa686072ef..a50d1cd9049 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -152,7 +152,7 @@ static void vbo_save_loopback_vertex_list( GLcontext *ctx, { const char *buffer = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB, - GL_DYNAMIC_READ_ARB, /* ? */ + GL_READ_ONLY, /* ? */ list->vertex_store->bufferobj); vbo_loopback_vertex_list( ctx, -- cgit v1.2.3 From feeed10dfd1495eb15924868fec3b795fb4b1ba3 Mon Sep 17 00:00:00 2001 From: Aapo Tahkola Date: Thu, 18 Jan 2007 05:30:20 +0200 Subject: typo fix. this case still fails. --- src/mesa/vbo/vbo_split.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c index 171859a18e0..ef205a3bb1f 100644 --- a/src/mesa/vbo/vbo_split.c +++ b/src/mesa/vbo/vbo_split.c @@ -121,7 +121,7 @@ void vbo_split_prims( GLcontext *ctx, */ assert(0); } - else if (max_index - min_index > limits->max_verts) { + else if (max_index - min_index >= limits->max_verts) { /* The vertex buffers are too large for hardware (or the * swtnl module). Traverse the indices, re-emitting vertices * in turn. Use a vertex cache to preserve some of the -- cgit v1.2.3 From 5970400476c5c0a1223a49e9ec2eb511ae94b246 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 25 Jan 2007 12:11:03 +0100 Subject: re-fix bug 9062 in vbo code --- src/mesa/vbo/vbo_exec_draw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 846d5dc196c..2b52d7a1fff 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -114,6 +114,11 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) return 2; } case GL_TRIANGLE_STRIP: + /* no parity issue, but need to make sure the tri is not drawn twice */ + if (nr & 1) { + exec->vtx.prim[exec->vtx.prim_count-1].count--; + } + /* fallthrough */ case GL_QUAD_STRIP: switch (nr) { case 0: ovf = 0; break; -- cgit v1.2.3 From db79d7dea03d5129a05d48af19049cb740799669 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 25 Jan 2007 14:32:06 +0100 Subject: fix dstelt memory allocation to avoid hash corruption --- src/mesa/vbo/vbo_split_copy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index fff733ccb53..df69e4ca28f 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -469,7 +469,7 @@ static void replay_init( struct copy_context *copy ) copy->ib->count * 2); copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices); - copy->dstelt = _mesa_malloc(copy->dstelt_size); + copy->dstelt = _mesa_malloc(sizeof(GLuint) * copy->dstelt_size); copy->dstelt_nr = 0; /* Setup the new index buffer to point to the allocated element -- cgit v1.2.3 From 78b64d911b4b50ab744f250522a88b3952859f98 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 25 Jan 2007 16:39:02 +0100 Subject: allocate larger minimum dstelt buffer increase the minimum dstelt buffer size to avoid triggering an assertion later because the split is triggered before the buffer is full. This fixes cases where the vbo_split_copy path is hit because of maximum index limit, where the dstelt buffer size needed could be very small (doom3 hit that assertion with a vertex count of just 3) --- src/mesa/vbo/vbo_split_copy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index df69e4ca28f..d9c58537821 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -466,7 +466,7 @@ static void replay_init( struct copy_context *copy ) /* Allocate an output element list: */ copy->dstelt_size = MIN2(65536, - copy->ib->count * 2); + copy->ib->count * 2 + 3); copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices); copy->dstelt = _mesa_malloc(sizeof(GLuint) * copy->dstelt_size); -- cgit v1.2.3 From 38e9f8b6f297bafba639ce192fc9926c8e890271 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 25 Jan 2007 18:52:40 +0100 Subject: do not rebase index buffers as it does not work currently (tested with r200 and sw mesa) --- src/mesa/vbo/vbo_exec_array.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index e0a6240c2a6..5a3a7488ede 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -302,11 +302,12 @@ vbo_exec_DrawRangeElements(GLenum mode, * worry about performance implications of start > 0. * * XXX: consider passing start as min_index to draw_prims instead. + * XXX: don't rebase because it didn't work. */ ib.rebase = 0; } else { - ib.rebase = start; + ib.rebase = /*start*/ 0; } prim[0].begin = 1; @@ -318,7 +319,7 @@ vbo_exec_DrawRangeElements(GLenum mode, prim[0].count = count; prim[0].indexed = 1; - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, ib.rebase, end+1 ); + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, /*ib.rebase*/ start, end+1 ); } -- cgit v1.2.3 From 240641de0c8532009fd21be7d4b0b84e471e91e8 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 30 Jan 2007 19:27:53 +0000 Subject: Helper for rebasing draw requests where min_index != 0. --- src/mesa/sources | 1 + src/mesa/vbo/vbo.h | 14 +++ src/mesa/vbo/vbo_rebase.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 src/mesa/vbo/vbo_rebase.c (limited to 'src/mesa/vbo') diff --git a/src/mesa/sources b/src/mesa/sources index fd6e8b40e59..6d6d22861c0 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -143,6 +143,7 @@ VBO_SOURCES = \ vbo/vbo_exec_array.c \ vbo/vbo_exec_draw.c \ vbo/vbo_exec_eval.c \ + vbo/vbo_rebase.c \ vbo/vbo_split.c \ vbo/vbo_split_copy.c \ vbo/vbo_split_inplace.c \ diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index c81d83f9b61..6a6fb28173e 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -101,4 +101,18 @@ void vbo_split_prims( GLcontext *ctx, const struct split_limits *limits ); +/* Helpers for dealing translating away non-zero min_index. + */ +GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] ); + +void vbo_rebase_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw ); + + #endif diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c new file mode 100644 index 00000000000..2a6f03797a1 --- /dev/null +++ b/src/mesa/vbo/vbo_rebase.c @@ -0,0 +1,221 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell + */ + +/* Helper for drivers which find themselves rendering a range of + * indices starting somewhere above zero. Typically the application + * is issuing multiple DrawArrays() or DrawElements() to draw + * successive primitives layed out linearly in the vertex arrays. + * Unless the vertex arrays are all in a VBO, the OpenGL semantics + * imply that we need to re-upload the vertex data on each draw call. + * In that case, we want to avoid starting the upload at zero, as it + * will mean every draw call uploads an increasing amount of not-used + * vertex data. Worse - in the software tnl module, all those + * vertices will be transformed and lit. + * + * If we just upload the new data, however, the indices will be + * incorrect as we tend to upload each set of vertex data to a new + * region. + * + * This file provides a helper to adjust the arrays, primitives and + * indices of a draw call so that it can be re-issued with a min_index + * of zero. + */ + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" + +#include "vbo.h" + + +#define REBASE(TYPE) \ +static void *rebase_##TYPE( const void *ptr, \ + GLuint count, \ + TYPE min_index ) \ +{ \ + const TYPE *in = (TYPE *)ptr; \ + TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \ + GLuint i; \ + \ + for (i = 0; i < count; i++) \ + tmp_indices[i] = in[i] - min_index; \ + \ + return (void *)tmp_indices; \ +} + + +REBASE(GLuint) +REBASE(GLushort) +REBASE(GLubyte) + +GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] ) +{ + GLuint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + if (arrays[i]->StrideB && + arrays[i]->BufferObj->Name == 0) + return GL_FALSE; + + return GL_TRUE; +} + +/* Adjust primitives, indices and vertex definitions so that min_index + * becomes zero. There are lots of reasons for wanting to do this, eg: + * + * Software tnl: + * - any time min_index != 0, otherwise unused vertices lower than + * min_index will be transformed. + * + * Hardware tnl: + * - if ib != NULL and min_index != 0, otherwise vertices lower than + * min_index will be uploaded. Requires adjusting index values. + * + * - if ib == NULL and min_index != 0, just for convenience so this doesn't + * have to be handled within the driver. + * + * Hardware tnl with VBO support: + * - as above, but only when vertices are not (all?) in VBO's. + * - can't save time by trying to upload half a vbo - typically it is + * all or nothing. + */ +void vbo_rebase_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw ) +{ + struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX]; + const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX]; + + struct _mesa_index_buffer tmp_ib; + struct _mesa_prim *tmp_prims = NULL; + void *tmp_indices = NULL; + GLuint i; + + assert(min_index != 0); + + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + + if (ib) { + /* Unfortunately need to adjust each index individually. + */ + GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + void *ptr; + + if (map_ib) + ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER, + GL_READ_ONLY_ARB, + ib->obj); + + + ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + + /* Some users might prefer it if we translated elements to + * GLuints here. Others wouldn't... + */ + switch (ib->type) { + case GL_UNSIGNED_INT: + tmp_indices = rebase_GLuint( ptr, ib->count, min_index ); + break; + case GL_UNSIGNED_SHORT: + tmp_indices = rebase_GLushort( ptr, ib->count, min_index ); + break; + case GL_UNSIGNED_BYTE: + tmp_indices = rebase_GLubyte( ptr, ib->count, min_index ); + break; + } + + if (map_ib) + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER, + ib->obj); + + tmp_ib.obj = ctx->Array.NullBufferObj; + tmp_ib.ptr = tmp_indices; + tmp_ib.count = ib->count; + tmp_ib.type = ib->type; + + ib = &tmp_ib; + } + else { + /* Otherwise the primitives need adjustment. + */ + tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims); + + for (i = 0; i < nr_prims; i++) { + /* If this fails, it could indicate an application error: + */ + assert(prim[i].start >= min_index); + + tmp_prims[i] = prim[i]; + tmp_prims[i].start -= min_index; + } + + prim = tmp_prims; + } + + /* Just need to adjust the pointer values on each incoming array. + * This works for VBO and non-vbo rendering and shouldn't pesimize + * VBO-based upload schemes. However this may still not be a fast + * path for hardware tnl for VBO based rendering as most machines + * will be happier if you just specify a starting vertex value in + * each primitive. + * + * For drivers with hardware tnl, you only want to do this if you + * are forced to, eg non-VBO indexed rendering with start != 0. + */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + tmp_arrays[i] = *arrays[i]; + tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB; + tmp_array_pointers[i] = &tmp_arrays[i]; + } + + /* Re-issue the draw call. + */ + draw( ctx, + tmp_array_pointers, + prim, + nr_prims, + ib, + 0, + max_index - min_index ); + + if (tmp_indices) + _mesa_free(tmp_indices); + + if (tmp_prims) + _mesa_free(tmp_prims); +} + + + -- cgit v1.2.3 From 893526b8a823fe1b88f2b46376155afb91c84016 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 30 Jan 2007 20:22:55 +0000 Subject: Use new rebase helper. Remove other rebase code. --- src/mesa/drivers/dri/i965/brw_draw.c | 53 +++++++++- src/mesa/drivers/dri/i965/brw_draw_upload.c | 105 ++++---------------- src/mesa/tnl/t_draw.c | 108 ++++++++------------ src/mesa/vbo/vbo.h | 1 - src/mesa/vbo/vbo_exec_array.c | 146 +++++++++++++++------------- src/mesa/vbo/vbo_rebase.c | 3 +- src/mesa/vbo/vbo_split_copy.c | 1 - src/mesa/vbo/vbo_split_inplace.c | 1 - 8 files changed, 185 insertions(+), 233 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 63cb079ec9a..7d8f837093a 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -198,7 +198,9 @@ static void brw_merge_inputs( struct brw_context *brw, brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING; } - +/* XXX: could split the primitive list to fallback only on the + * non-conformant primitives. + */ static GLboolean check_fallbacks( struct brw_context *brw, const struct _mesa_prim *prim, GLuint nr_prims ) @@ -251,7 +253,9 @@ static GLboolean check_fallbacks( struct brw_context *brw, return GL_FALSE; } - +/* May fail if out of video memory for texture or vbo upload, or on + * fallback conditions. + */ static GLboolean brw_try_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, @@ -376,6 +380,33 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx, return retval; } +static GLboolean brw_need_rebase( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_index_buffer *ib, + GLuint min_index ) +{ + if (min_index == 0) + return GL_FALSE; + + if (ib) { + if (!vbo_all_varyings_in_vbos(arrays)) + return GL_TRUE; + else + return GL_FALSE; + } + else { + /* Hmm. This isn't quite what I wanted. BRW can actually + * handle the mixed case well enough that we shouldn't need to + * rebase. However, it's probably not very common, nor hugely + * expensive to do it this way: + */ + if (!vbo_all_varyings_in_vbos(arrays)) + return GL_TRUE; + else + return GL_FALSE; + } +} + void brw_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], @@ -388,6 +419,21 @@ void brw_draw_prims( GLcontext *ctx, struct intel_context *intel = intel_context(ctx); GLboolean retval; + /* Decide if we want to rebase. If so we end up recursing once + * only into this function. + */ + if (brw_need_rebase( ctx, arrays, ib, min_index )) { + vbo_rebase_prims( ctx, arrays, + prim, nr_prims, + ib, min_index, max_index, + brw_draw_prims ); + + return; + } + + + /* Make a first attempt at drawing: + */ retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); @@ -440,14 +486,13 @@ void brw_draw_init( struct brw_context *brw ) for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) { brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); - /* XXX: Set these to no-backing-store + /* NOTE: These are set to no-backing-store. */ bmBufferSetInvalidateCB(&brw->intel, intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])), brw_invalidate_vbo_cb, &brw->intel, GL_TRUE); - } ctx->Driver.BufferData( ctx, diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c index 90637d16eae..6968d745c1c 100644 --- a/src/mesa/drivers/dri/i965/brw_draw_upload.c +++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c @@ -309,7 +309,6 @@ copy_array_to_vbo_array( struct brw_context *brw, GLuint i, const struct gl_client_array *array, GLuint element_size, - GLuint min_index, GLuint count) { GLcontext *ctx = &brw->intel.ctx; @@ -347,7 +346,7 @@ copy_array_to_vbo_array( struct brw_context *brw, map += offset; copy_strided_array( map, - array->Ptr + min_index * array->StrideB, + array->Ptr, element_size, array->StrideB, count); @@ -438,10 +437,8 @@ GLboolean brw_upload_vertices( struct brw_context *brw, } upload[nr_uploads++] = input; - input->vbo_rebase_offset = 0; + assert(min_index == 0); } - else - input->vbo_rebase_offset = min_index * input->glarray->StrideB; } /* Upload interleaved arrays if all uploads are interleaved @@ -454,7 +451,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw, input0->glarray = copy_array_to_vbo_array(brw, 0, input0->glarray, interleave, - min_index, input0->count); for (i = 1; i < nr_uploads; i++) { @@ -472,7 +468,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw, input->glarray = copy_array_to_vbo_array(brw, i, input->glarray, input->element_size, - min_index, input->count); } @@ -520,9 +515,9 @@ GLboolean brw_upload_vertices( struct brw_context *brw, vbp.vb[i].vb0.bits.pad = 0; vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA; vbp.vb[i].vb0.bits.vb_index = i; - vbp.vb[i].offset = (GLuint)input->glarray->Ptr + input->vbo_rebase_offset; + vbp.vb[i].offset = (GLuint)input->glarray->Ptr; vbp.vb[i].buffer = array_buffer(input->glarray); - vbp.vb[i].max_index = max_index - min_index; + vbp.vb[i].max_index = max_index; } @@ -563,94 +558,32 @@ static GLuint element_size( GLenum type ) - -static void rebase_indices_to_vbo_indices( struct brw_context *brw, - const struct _mesa_index_buffer *index_buffer, - struct gl_buffer_object **vbo_return, - GLuint *offset_return ) +void brw_upload_indices( struct brw_context *brw, + const struct _mesa_index_buffer *index_buffer ) { GLcontext *ctx = &brw->intel.ctx; - GLuint min_index = index_buffer->rebase; - const void *indices = index_buffer->ptr; - GLsizei count = index_buffer->count; - GLenum type = index_buffer->type; - GLuint size = element_size(type) * count; - struct gl_buffer_object *bufferobj; - GLuint offset; - GLuint i; - - get_space(brw, size, &bufferobj, &offset); + struct intel_context *intel = &brw->intel; + GLuint ib_size = get_size(index_buffer->type) * index_buffer->count; + struct gl_buffer_object *bufferobj = index_buffer->obj; + GLuint offset = (GLuint)index_buffer->ptr; - *vbo_return = bufferobj; - *offset_return = offset; + /* Turn into a proper VBO: + */ + if (!bufferobj->Name) { + + /* Get new bufferobj, offset: + */ + get_space(brw, ib_size, &bufferobj, &offset); - if (min_index == 0) { /* Straight upload */ ctx->Driver.BufferSubData( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, offset, - size, - indices, + ib_size, + index_buffer->ptr, bufferobj); } - else { - void *map = ctx->Driver.MapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - GL_DYNAMIC_DRAW_ARB, - bufferobj); - - map += offset; - - switch (type) { - case GL_UNSIGNED_INT: { - GLuint *ui_map = (GLuint *)map; - const GLuint *ui_indices = (const GLuint *)indices; - - for (i = 0; i < count; i++) - ui_map[i] = ui_indices[i] - min_index; - break; - } - case GL_UNSIGNED_SHORT: { - GLushort *us_map = (GLushort *)map; - const GLushort *us_indices = (const GLushort *)indices; - - for (i = 0; i < count; i++) - us_map[i] = us_indices[i] - min_index; - break; - } - case GL_UNSIGNED_BYTE: { - GLubyte *ub_map = (GLubyte *)map; - const GLubyte *ub_indices = (const GLubyte *)indices; - - for (i = 0; i < count; i++) - ub_map[i] = ub_indices[i] - min_index; - break; - } - } - - ctx->Driver.UnmapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - bufferobj); - - } -} - - - -void brw_upload_indices( struct brw_context *brw, - const struct _mesa_index_buffer *index_buffer) -{ - struct intel_context *intel = &brw->intel; - GLuint ib_size = get_size(index_buffer->type) * index_buffer->count; - struct gl_buffer_object *bufferobj = index_buffer->obj; - GLuint offset = (GLuint)index_buffer->ptr; - - /* Already turned into a proper VBO: - */ - if (!index_buffer->obj->Name) { - rebase_indices_to_vbo_indices(brw, index_buffer, &bufferobj, &offset ); - } /* Emit the indexbuffer packet: */ diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index 0e7c2b6a689..c97cf5f7b21 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -95,18 +95,14 @@ static void free_space(GLcontext *ctx) */ static void _tnl_import_array( GLcontext *ctx, GLuint attrib, - GLuint start, - GLuint end, + GLuint count, const struct gl_client_array *input, const GLubyte *ptr ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - const GLuint count = end - start; GLuint stride = input->StrideB; - ptr += start * stride; - if (input->Type != GL_FLOAT) { const GLuint sz = input->Size; GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); @@ -183,7 +179,7 @@ static GLboolean *_tnl_import_edgeflag( GLcontext *ctx, static void bind_inputs( GLcontext *ctx, const struct gl_client_array *inputs[], - GLint min_index, GLint max_index, + GLint count, struct gl_buffer_object **bo, GLuint *nr_bo ) { @@ -215,18 +211,17 @@ static void bind_inputs( GLcontext *ctx, ptr = inputs[i]->Ptr; /* Just make sure the array is floating point, otherwise convert to - * temporary storage. Rebase arrays so that 'min_index' becomes - * element zero. + * temporary storage. * * XXX: remove the GLvector4f type at some stage and just use * client arrays. */ - _tnl_import_array(ctx, i, min_index, max_index, inputs[i], ptr); + _tnl_import_array(ctx, i, count, inputs[i], ptr); } /* We process only the vertices between min & max index: */ - VB->Count = max_index - min_index; + VB->Count = count; /* Legacy pointers -- remove one day. @@ -264,7 +259,6 @@ static void bind_inputs( GLcontext *ctx, */ static void bind_indices( GLcontext *ctx, const struct _mesa_index_buffer *ib, - GLuint min_index, struct gl_buffer_object **bo, GLuint *nr_bo) { @@ -273,8 +267,10 @@ static void bind_indices( GLcontext *ctx, GLuint i; void *ptr; - if (!ib) + if (!ib) { + VB->Elts = NULL; return; + } if (ib->obj->Name && !ib->obj->Pointer) { bo[*nr_bo] = ib->obj; @@ -289,60 +285,34 @@ static void bind_indices( GLcontext *ctx, ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); - if (ib->type == GL_UNSIGNED_INT && min_index == 0) { + if (ib->type == GL_UNSIGNED_INT) { VB->Elts = (GLuint *) ptr; - VB->Elts += ib->rebase; } else { GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); VB->Elts = elts; - switch (ib->type) { - case GL_UNSIGNED_INT: { - const GLuint *in = ((GLuint *)ptr) + ib->rebase; - for (i = 0; i < ib->count; i++) - *elts++ = *in++ - min_index; - break; - } - case GL_UNSIGNED_SHORT: { - const GLushort *in = ((GLushort *)ptr) + ib->rebase; + if (ib->type == GL_UNSIGNED_SHORT) { + const GLushort *in = (GLushort *)ptr; for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++) - min_index; - break; + *elts++ = (GLuint)(*in++); } - case GL_UNSIGNED_BYTE: { - const GLubyte *in = ((GLubyte *)ptr) + ib->rebase; + else { + const GLubyte *in = (GLubyte *)ptr; for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++) - min_index; - break; + *elts++ = (GLuint)(*in++); } - } } } static void bind_prims( GLcontext *ctx, const struct _mesa_prim *prim, - GLuint nr_prims, - GLuint min_index ) + GLuint nr_prims ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint i; - - if (min_index != 0) { - struct _mesa_prim *tmp = (struct _mesa_prim *)get_space(ctx, nr_prims * sizeof(*prim)); - - for (i = 0; i < nr_prims; i++) { - tmp[i] = prim[i]; - tmp[i].start -= min_index; - } - - VB->Primitive = tmp; - } - else { - VB->Primitive = prim; - } + VB->Primitive = prim; VB->PrimitiveCount = nr_prims; } @@ -373,19 +343,10 @@ void _tnl_draw_prims( GLcontext *ctx, GLuint max_index) { TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLint max = VB->Size; - -#ifdef TEST_SPLIT - max = 8 + MAX_CLIPPED_VERTICES; -#endif - - assert(max_index > min_index); - assert(!(max_index & 0x80000000)); + const GLuint TEST_SPLIT = 0; + const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; - VB->Elts = NULL; - -#if 0 + if (0) { GLuint i; _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); @@ -395,15 +356,22 @@ void _tnl_draw_prims( GLcontext *ctx, prim[i].start, prim[i].count); } -#endif - /* The software TNL pipeline has a fixed amount of storage for - * vertices and it is necessary to split incoming drawing commands - * if they exceed that limit. - */ - if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) { + if (min_index) { + /* We always translate away calls with min_index != 0. + */ + vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, + min_index, max_index, + _tnl_draw_prims ); + return; + } + else if (max_index >= max) { + /* The software TNL pipeline has a fixed amount of storage for + * vertices and it is necessary to split incoming drawing commands + * if they exceed that limit. + */ struct split_limits limits; - limits.max_verts = max - MAX_CLIPPED_VERTICES; + limits.max_verts = max; limits.max_vb_size = ~0; limits.max_indices = ~0; @@ -411,7 +379,7 @@ void _tnl_draw_prims( GLcontext *ctx, * recursively call back into this function. */ vbo_split_prims( ctx, arrays, prim, nr_prims, ib, - min_index, max_index, + 0, max_index, _tnl_draw_prims, &limits ); } @@ -425,9 +393,9 @@ void _tnl_draw_prims( GLcontext *ctx, /* Binding inputs may imply mapping some vertex buffer objects. * They will need to be unmapped below. */ - bind_inputs(ctx, arrays, min_index, max_index+1, bo, &nr_bo); - bind_indices(ctx, ib, min_index, bo, &nr_bo); - bind_prims(ctx, prim, nr_prims, VB->Elts ? 0 : min_index ); + bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo); + bind_indices(ctx, ib, bo, &nr_bo); + bind_prims(ctx, prim, nr_prims ); TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h index 6a6fb28173e..874a5f9e0e2 100644 --- a/src/mesa/vbo/vbo.h +++ b/src/mesa/vbo/vbo.h @@ -55,7 +55,6 @@ struct _mesa_index_buffer { GLenum type; struct gl_buffer_object *obj; const void *ptr; - GLuint rebase; }; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 5a3a7488ede..f96df5f1643 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -34,45 +34,55 @@ #include "vbo_context.h" -static GLuint get_max_index( GLuint count, GLuint type, - const GLvoid *indices ) +/* Compute min and max elements for drawelements calls. + */ +static void get_minmax_index( GLuint count, GLuint type, + const GLvoid *indices, + GLuint *min_index, + GLuint *max_index) { GLint i; - /* Compute max element. This is only needed for upload of non-VBO, - * non-constant data elements. - * - * XXX: Postpone this calculation until it is known that it is - * needed. Otherwise could scan this pointlessly in the all-vbo - * case. - */ switch(type) { case GL_UNSIGNED_INT: { const GLuint *ui_indices = (const GLuint *)indices; - GLuint max_ui = 0; - for (i = 0; i < count; i++) - if (ui_indices[i] > max_ui) - max_ui = ui_indices[i]; - return max_ui; + GLuint max_ui = ui_indices[0]; + GLuint min_ui = ui_indices[0]; + for (i = 1; i < count; i++) { + if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; + if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; + } + *min_index = min_ui; + *max_index = max_ui; + break; } case GL_UNSIGNED_SHORT: { const GLushort *us_indices = (const GLushort *)indices; - GLuint max_us = 0; - for (i = 0; i < count; i++) - if (us_indices[i] > max_us) - max_us = us_indices[i]; - return max_us; + GLuint max_us = us_indices[0]; + GLuint min_us = us_indices[0]; + for (i = 1; i < count; i++) { + if (us_indices[i] > max_us) max_us = us_indices[i]; + if (us_indices[i] < min_us) min_us = us_indices[i]; + } + *min_index = min_us; + *max_index = max_us; + break; } case GL_UNSIGNED_BYTE: { const GLubyte *ub_indices = (const GLubyte *)indices; - GLuint max_ub = 0; - for (i = 0; i < count; i++) - if (ub_indices[i] > max_ub) - max_ub = ub_indices[i]; - return max_ub; + GLuint max_ub = ub_indices[0]; + GLuint min_ub = ub_indices[0]; + for (i = 1; i < count; i++) { + if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; + if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; + } + *min_index = min_ub; + *max_index = max_ub; + break; } default: - return 0; + assert(0); + break; } } @@ -241,31 +251,12 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) prim[0].end = 1; prim[0].weak = 0; prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = start; + prim[0].count = count; + prim[0].indexed = 0; - if (exec->array.inputs[0]->BufferObj->Name) { - /* Use vertex attribute as a hint to tell us if we expect all - * arrays to be in VBO's and if so, don't worry about avoiding - * the upload of elements < start. - */ - prim[0].mode = mode; - prim[0].start = start; - prim[0].count = count; - prim[0].indexed = 0; - - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count ); - } - else { - /* If not using VBO's, we don't want to upload any more elements - * than necessary from the arrays as they will not be valid next - * time the application tries to draw with them. - */ - prim[0].mode = mode; - prim[0].start = 0; - prim[0].count = count; - prim[0].indexed = 0; - - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count ); - } + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 ); } @@ -296,20 +287,6 @@ vbo_exec_DrawRangeElements(GLenum mode, ib.obj = ctx->Array.ElementArrayBufferObj; ib.ptr = indices; - if (ctx->Array.ElementArrayBufferObj->Name) { - /* Use the fact that indices are in a VBO as a hint that the - * program has put all the arrays in VBO's and we don't have to - * worry about performance implications of start > 0. - * - * XXX: consider passing start as min_index to draw_prims instead. - * XXX: don't rebase because it didn't work. - */ - ib.rebase = 0; - } - else { - ib.rebase = /*start*/ 0; - } - prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; @@ -319,15 +296,46 @@ vbo_exec_DrawRangeElements(GLenum mode, prim[0].count = count; prim[0].indexed = 1; - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, /*ib.rebase*/ start, end+1 ); -} + /* Need to give special consideration to rendering a range of + * indices starting somewhere above zero. Typically the + * application is issuing multiple DrawRangeElements() to draw + * successive primitives layed out linearly in the vertex arrays. + * Unless the vertex arrays are all in a VBO (or locked as with + * CVA), the OpenGL semantics imply that we need to re-read or + * re-upload the vertex data on each draw call. + * + * In the case of hardware tnl, we want to avoid starting the + * upload at zero, as it will mean every draw call uploads an + * increasing amount of not-used vertex data. Worse - in the + * software tnl module, all those vertices might be transformed and + * lit but never rendered. + * + * If we just upload or transform the vertices in start..end, + * however, the indices will be incorrect. + * + * At this level, we don't know exactly what the requirements of + * the backend are going to be, though it will likely boil down to + * either: + * + * 1) Do nothing, everything is in a VBO and is processed once + * only. + * + * 2) Adjust the indices and vertex arrays so that start becomes + * zero. + * + * Rather than doing anything here, I'll provide a helper function + * for the latter case elsewhere. + */ + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end ); +} static void GLAPIENTRY vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); - GLuint max_index; + GLuint min_index = 0; + GLuint max_index = 0; if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) return; @@ -338,17 +346,17 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind GL_READ_ONLY, ctx->Array.ElementArrayBufferObj); - max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); + get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index); ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ctx->Array.ElementArrayBufferObj); } else { - max_index = get_max_index(count, type, indices); + get_minmax_index(count, type, indices, &min_index, &max_index); } - vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices); + vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices); } diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c index 2a6f03797a1..bc4211d8529 100644 --- a/src/mesa/vbo/vbo_rebase.c +++ b/src/mesa/vbo/vbo_rebase.c @@ -123,7 +123,8 @@ void vbo_rebase_prims( GLcontext *ctx, assert(min_index != 0); - _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + if (0) + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); if (ib) { /* Unfortunately need to adjust each index individually. diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index d9c58537821..ef97acbce70 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -479,7 +479,6 @@ static void replay_init( struct copy_context *copy ) copy->dstib.type = GL_UNSIGNED_INT; copy->dstib.obj = ctx->Array.NullBufferObj; copy->dstib.ptr = copy->dstelt; - copy->dstib.rebase = 0; } diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c index d3649c59db3..ea62866e7c9 100644 --- a/src/mesa/vbo/vbo_split_inplace.c +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -223,7 +223,6 @@ static void split_prims( struct split_context *split) ib.type = GL_UNSIGNED_INT; ib.obj = split->ctx->Array.NullBufferObj; ib.ptr = elts; - ib.rebase = 0; /* ? */ tmpprim = *prim; tmpprim.indexed = 1; -- cgit v1.2.3 From 8ebda479d90b0c95df50f790316f451a32f4bd4e Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 1 Feb 2007 20:59:45 +0100 Subject: fix missing ADD_POINTERS, fixes crashes if the index elements are in a vbo. --- src/mesa/vbo/vbo_split_copy.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/mesa/vbo') diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index ef97acbce70..e142dde6803 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -360,6 +360,7 @@ static void replay_init( struct copy_context *copy ) GLcontext *ctx = copy->ctx; GLuint i; GLuint offset; + const GLvoid *srcptr; /* Make a list of varying attributes and their vbo's. Also * calculate vertex size. @@ -402,13 +403,15 @@ static void replay_init( struct copy_context *copy ) GL_WRITE_ONLY, /* XXX */ copy->ib->obj); + srcptr = (const GLubyte *)ADD_POINTERS(copy->ib->obj->Pointer, copy->ib->ptr); + switch (copy->ib->type) { case GL_UNSIGNED_BYTE: copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count); copy->srcelt = copy->translated_elt_buf; - + for (i = 0; i < copy->ib->count; i++) - copy->translated_elt_buf[i] = ((const GLubyte *)copy->ib->ptr)[i]; + copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i]; break; case GL_UNSIGNED_SHORT: @@ -416,13 +419,12 @@ static void replay_init( struct copy_context *copy ) copy->srcelt = copy->translated_elt_buf; for (i = 0; i < copy->ib->count; i++) - copy->translated_elt_buf[i] = ((const GLushort *)copy->ib->ptr)[i]; + copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i]; break; case GL_UNSIGNED_INT: copy->translated_elt_buf = NULL; - copy->srcelt = (const GLuint *)ADD_POINTERS(copy->ib->obj->Pointer, - copy->ib->ptr); + copy->srcelt = (const GLuint *)srcptr; break; } -- cgit v1.2.3