vbo_save_loopback.c revision 0846c88ec3a63ac5e4096aedcdc107cbe71f306b
1/**************************************************************************
2 *
3 * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "main/context.h"
29#include "main/glheader.h"
30#include "main/enums.h"
31#include "main/imports.h"
32#include "main/macros.h"
33#include "main/mtypes.h"
34#include "glapi/dispatch.h"
35#include "glapi/glapi.h"
36
37#include "vbo_context.h"
38
39
40
41typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
42
43
44/* This file makes heavy use of the aliasing of NV vertex attributes
45 * with the legacy attributes, and also with ARB and Material
46 * attributes as currently implemented.
47 */
48static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
49{
50   CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
51}
52
53static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
54{
55   CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
56}
57
58static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
59{
60   CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
61}
62
63static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
64{
65   CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
66}
67
68static attr_func vert_attrfunc[4] = {
69   VertexAttrib1fvNV,
70   VertexAttrib2fvNV,
71   VertexAttrib3fvNV,
72   VertexAttrib4fvNV
73};
74
75struct loopback_attr {
76   GLint target;
77   GLint sz;
78   attr_func func;
79};
80
81/* Don't emit ends and begins on wrapped primitives.  Don't replay
82 * wrapped vertices.  If we get here, it's probably because the the
83 * precalculated wrapping is wrong.
84 */
85static void loopback_prim( GLcontext *ctx,
86			   const GLfloat *buffer,
87			   const struct _mesa_prim *prim,
88			   GLuint wrap_count,
89			   GLuint vertex_size,
90			   const struct loopback_attr *la, GLuint nr )
91{
92   GLint start = prim->start;
93   GLint end = start + prim->count;
94   const GLfloat *data;
95   GLint j;
96   GLuint k;
97
98   if (0)
99      _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
100		   _mesa_lookup_prim_by_nr(prim->mode),
101		   prim->begin ? "begin" : "..",
102		   prim->end ? "end" : "..",
103		   start,
104		   end);
105
106   if (prim->begin) {
107      CALL_Begin(GET_DISPATCH(), ( prim->mode ));
108   }
109   else {
110      assert(start == 0);
111      start += wrap_count;
112   }
113
114   data = buffer + start * vertex_size;
115
116   for (j = start ; j < end ; j++) {
117      const GLfloat *tmp = data + la[0].sz;
118
119      for (k = 1 ; k < nr ; k++) {
120	 la[k].func( ctx, la[k].target, tmp );
121	 tmp += la[k].sz;
122      }
123
124      /* Fire the vertex
125       */
126      la[0].func( ctx, VBO_ATTRIB_POS, data );
127      data = tmp;
128   }
129
130   if (prim->end) {
131      CALL_End(GET_DISPATCH(), ());
132   }
133}
134
135/* Primitives generated by DrawArrays/DrawElements/Rectf may be
136 * caught here.  If there is no primitive in progress, execute them
137 * normally, otherwise need to track and discard the generated
138 * primitives.
139 */
140static void loopback_weak_prim( GLcontext *ctx,
141				const struct _mesa_prim *prim )
142{
143   /* Use the prim_weak flag to ensure that if this primitive
144    * wraps, we don't mistake future vertex_lists for part of the
145    * surrounding primitive.
146    *
147    * While this flag is set, we are simply disposing of data
148    * generated by an operation now known to be a noop.
149    */
150   if (prim->begin)
151      ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
152   if (prim->end)
153      ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
154}
155
156
157void vbo_loopback_vertex_list( GLcontext *ctx,
158			       const GLfloat *buffer,
159			       const GLubyte *attrsz,
160			       const struct _mesa_prim *prim,
161			       GLuint prim_count,
162			       GLuint wrap_count,
163			       GLuint vertex_size)
164{
165   struct loopback_attr la[VBO_ATTRIB_MAX];
166   GLuint i, nr = 0;
167
168   /* All Legacy, NV, ARB and Material attributes are routed through
169    * the NV attributes entrypoints:
170    */
171   for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
172      if (attrsz[i]) {
173	 la[nr].target = i;
174	 la[nr].sz = attrsz[i];
175	 la[nr].func = vert_attrfunc[attrsz[i]-1];
176	 nr++;
177      }
178   }
179
180   for (i = 0 ; i < prim_count ; i++) {
181      if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
182	  (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
183      {
184	 loopback_weak_prim( ctx, &prim[i] );
185      }
186      else
187      {
188	 loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
189      }
190   }
191}
192