Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /************************************************************************** |
2 | |||
3 | Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas. |
||
4 | |||
5 | All Rights Reserved. |
||
6 | |||
7 | Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | copy of this software and associated documentation files (the "Software"), |
||
9 | to deal in the Software without restriction, including without limitation |
||
10 | on the rights to use, copy, modify, merge, publish, distribute, sub |
||
11 | license, and/or sell copies of the Software, and to permit persons to whom |
||
12 | the Software is furnished to do so, subject to the following conditions: |
||
13 | |||
14 | The above copyright notice and this permission notice (including the next |
||
15 | paragraph) shall be included in all copies or substantial portions of the |
||
16 | Software. |
||
17 | |||
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
20 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
21 | TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
22 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
23 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
24 | USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | |||
26 | **************************************************************************/ |
||
27 | |||
28 | /* |
||
29 | * Authors: |
||
30 | * Keith Whitwell |
||
31 | */ |
||
32 | |||
33 | #include "main/glheader.h" |
||
34 | #include "main/bufferobj.h" |
||
35 | #include "main/context.h" |
||
36 | #include "main/macros.h" |
||
37 | #include "main/vtxfmt.h" |
||
38 | #include "main/dlist.h" |
||
39 | #include "main/eval.h" |
||
40 | #include "main/state.h" |
||
41 | #include "main/light.h" |
||
42 | #include "main/api_arrayelt.h" |
||
43 | #include "main/api_noop.h" |
||
44 | #include "main/dispatch.h" |
||
45 | |||
46 | #include "vbo_context.h" |
||
47 | |||
48 | #ifdef ERROR |
||
49 | #undef ERROR |
||
50 | #endif |
||
51 | |||
52 | |||
53 | /** ID/name for immediate-mode VBO */ |
||
54 | #define IMM_BUFFER_NAME 0xaabbccdd |
||
55 | |||
56 | |||
57 | static void reset_attrfv( struct vbo_exec_context *exec ); |
||
58 | |||
59 | |||
60 | /** |
||
61 | * Close off the last primitive, execute the buffer, restart the |
||
62 | * primitive. |
||
63 | */ |
||
64 | static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) |
||
65 | { |
||
66 | if (exec->vtx.prim_count == 0) { |
||
67 | exec->vtx.copied.nr = 0; |
||
68 | exec->vtx.vert_count = 0; |
||
69 | exec->vtx.buffer_ptr = exec->vtx.buffer_map; |
||
70 | } |
||
71 | else { |
||
72 | GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; |
||
73 | GLuint last_count; |
||
74 | |||
75 | if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { |
||
76 | GLint i = exec->vtx.prim_count - 1; |
||
77 | assert(i >= 0); |
||
78 | exec->vtx.prim[i].count = (exec->vtx.vert_count - |
||
79 | exec->vtx.prim[i].start); |
||
80 | } |
||
81 | |||
82 | last_count = exec->vtx.prim[exec->vtx.prim_count-1].count; |
||
83 | |||
84 | /* Execute the buffer and save copied vertices. |
||
85 | */ |
||
86 | if (exec->vtx.vert_count) |
||
87 | vbo_exec_vtx_flush( exec, GL_FALSE ); |
||
88 | else { |
||
89 | exec->vtx.prim_count = 0; |
||
90 | exec->vtx.copied.nr = 0; |
||
91 | } |
||
92 | |||
93 | /* Emit a glBegin to start the new list. |
||
94 | */ |
||
95 | assert(exec->vtx.prim_count == 0); |
||
96 | |||
97 | if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { |
||
98 | exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; |
||
99 | exec->vtx.prim[0].start = 0; |
||
100 | exec->vtx.prim[0].count = 0; |
||
101 | exec->vtx.prim_count++; |
||
102 | |||
103 | if (exec->vtx.copied.nr == last_count) |
||
104 | exec->vtx.prim[0].begin = last_begin; |
||
105 | } |
||
106 | } |
||
107 | } |
||
108 | |||
109 | |||
110 | /** |
||
111 | * Deal with buffer wrapping where provoked by the vertex buffer |
||
112 | * filling up, as opposed to upgrade_vertex(). |
||
113 | */ |
||
114 | void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) |
||
115 | { |
||
116 | GLfloat *data = exec->vtx.copied.buffer; |
||
117 | GLuint i; |
||
118 | |||
119 | /* Run pipeline on current vertices, copy wrapped vertices |
||
120 | * to exec->vtx.copied. |
||
121 | */ |
||
122 | vbo_exec_wrap_buffers( exec ); |
||
123 | |||
124 | /* Copy stored stored vertices to start of new list. |
||
125 | */ |
||
126 | assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); |
||
127 | |||
128 | for (i = 0 ; i < exec->vtx.copied.nr ; i++) { |
||
129 | memcpy( exec->vtx.buffer_ptr, data, |
||
130 | exec->vtx.vertex_size * sizeof(GLfloat)); |
||
131 | exec->vtx.buffer_ptr += exec->vtx.vertex_size; |
||
132 | data += exec->vtx.vertex_size; |
||
133 | exec->vtx.vert_count++; |
||
134 | } |
||
135 | |||
136 | exec->vtx.copied.nr = 0; |
||
137 | } |
||
138 | |||
139 | |||
140 | /** |
||
141 | * Copy the active vertex's values to the ctx->Current fields. |
||
142 | */ |
||
143 | static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) |
||
144 | { |
||
145 | struct gl_context *ctx = exec->ctx; |
||
146 | struct vbo_context *vbo = vbo_context(ctx); |
||
147 | GLuint i; |
||
148 | |||
149 | for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { |
||
150 | if (exec->vtx.attrsz[i]) { |
||
151 | /* Note: the exec->vtx.current[i] pointers point into the |
||
152 | * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. |
||
153 | */ |
||
154 | GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; |
||
155 | GLfloat tmp[4]; |
||
156 | |||
157 | COPY_CLEAN_4V(tmp, |
||
158 | exec->vtx.attrsz[i], |
||
159 | exec->vtx.attrptr[i]); |
||
160 | |||
161 | if (memcmp(current, tmp, sizeof(tmp)) != 0) |
||
162 | { |
||
163 | memcpy(current, tmp, sizeof(tmp)); |
||
164 | |||
165 | /* Given that we explicitly state size here, there is no need |
||
166 | * for the COPY_CLEAN above, could just copy 16 bytes and be |
||
167 | * done. The only problem is when Mesa accesses ctx->Current |
||
168 | * directly. |
||
169 | */ |
||
170 | vbo->currval[i].Size = exec->vtx.attrsz[i]; |
||
171 | |||
172 | /* This triggers rather too much recalculation of Mesa state |
||
173 | * that doesn't get used (eg light positions). |
||
174 | */ |
||
175 | if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && |
||
176 | i <= VBO_ATTRIB_MAT_BACK_INDEXES) |
||
177 | ctx->NewState |= _NEW_LIGHT; |
||
178 | |||
179 | ctx->NewState |= _NEW_CURRENT_ATTRIB; |
||
180 | } |
||
181 | } |
||
182 | } |
||
183 | |||
184 | /* Colormaterial -- this kindof sucks. |
||
185 | */ |
||
186 | if (ctx->Light.ColorMaterialEnabled && |
||
187 | exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) { |
||
188 | _mesa_update_color_material(ctx, |
||
189 | ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | |||
194 | static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) |
||
195 | { |
||
196 | struct gl_context *ctx = exec->ctx; |
||
197 | struct vbo_context *vbo = vbo_context(ctx); |
||
198 | GLint i; |
||
199 | |||
200 | for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { |
||
201 | const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; |
||
202 | switch (exec->vtx.attrsz[i]) { |
||
203 | case 4: exec->vtx.attrptr[i][3] = current[3]; |
||
204 | case 3: exec->vtx.attrptr[i][2] = current[2]; |
||
205 | case 2: exec->vtx.attrptr[i][1] = current[1]; |
||
206 | case 1: exec->vtx.attrptr[i][0] = current[0]; |
||
207 | break; |
||
208 | } |
||
209 | } |
||
210 | } |
||
211 | |||
212 | |||
213 | /** |
||
214 | * Flush existing data, set new attrib size, replay copied vertices. |
||
215 | */ |
||
216 | static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, |
||
217 | GLuint attr, |
||
218 | GLuint newsz ) |
||
219 | { |
||
220 | struct gl_context *ctx = exec->ctx; |
||
221 | struct vbo_context *vbo = vbo_context(ctx); |
||
222 | GLint lastcount = exec->vtx.vert_count; |
||
223 | GLfloat *old_attrptr[VBO_ATTRIB_MAX]; |
||
224 | GLuint old_vtx_size = exec->vtx.vertex_size; |
||
225 | GLuint oldsz = exec->vtx.attrsz[attr]; |
||
226 | GLuint i; |
||
227 | |||
228 | /* Run pipeline on current vertices, copy wrapped vertices |
||
229 | * to exec->vtx.copied. |
||
230 | */ |
||
231 | vbo_exec_wrap_buffers( exec ); |
||
232 | |||
233 | if (unlikely(exec->vtx.copied.nr)) { |
||
234 | /* We're in the middle of a primitive, keep the old vertex |
||
235 | * format around to be able to translate the copied vertices to |
||
236 | * the new format. |
||
237 | */ |
||
238 | memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); |
||
239 | } |
||
240 | |||
241 | if (unlikely(oldsz)) { |
||
242 | /* Do a COPY_TO_CURRENT to ensure back-copying works for the |
||
243 | * case when the attribute already exists in the vertex and is |
||
244 | * having its size increased. |
||
245 | */ |
||
246 | vbo_exec_copy_to_current( exec ); |
||
247 | } |
||
248 | |||
249 | /* Heuristic: Attempt to isolate attributes received outside |
||
250 | * begin/end so that they don't bloat the vertices. |
||
251 | */ |
||
252 | if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && |
||
253 | !oldsz && lastcount > 8 && exec->vtx.vertex_size) { |
||
254 | vbo_exec_copy_to_current( exec ); |
||
255 | reset_attrfv( exec ); |
||
256 | } |
||
257 | |||
258 | /* Fix up sizes: |
||
259 | */ |
||
260 | exec->vtx.attrsz[attr] = newsz; |
||
261 | exec->vtx.vertex_size += newsz - oldsz; |
||
262 | exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / |
||
263 | (exec->vtx.vertex_size * sizeof(GLfloat))); |
||
264 | exec->vtx.vert_count = 0; |
||
265 | exec->vtx.buffer_ptr = exec->vtx.buffer_map; |
||
266 | |||
267 | if (unlikely(oldsz)) { |
||
268 | /* Size changed, recalculate all the attrptr[] values |
||
269 | */ |
||
270 | GLfloat *tmp = exec->vtx.vertex; |
||
271 | |||
272 | for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { |
||
273 | if (exec->vtx.attrsz[i]) { |
||
274 | exec->vtx.attrptr[i] = tmp; |
||
275 | tmp += exec->vtx.attrsz[i]; |
||
276 | } |
||
277 | else |
||
278 | exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ |
||
279 | } |
||
280 | |||
281 | /* Copy from current to repopulate the vertex with correct |
||
282 | * values. |
||
283 | */ |
||
284 | vbo_exec_copy_from_current( exec ); |
||
285 | |||
286 | } else { |
||
287 | /* Just have to append the new attribute at the end */ |
||
288 | exec->vtx.attrptr[attr] = exec->vtx.vertex + |
||
289 | exec->vtx.vertex_size - newsz; |
||
290 | } |
||
291 | |||
292 | /* Replay stored vertices to translate them |
||
293 | * to new format here. |
||
294 | * |
||
295 | * -- No need to replay - just copy piecewise |
||
296 | */ |
||
297 | if (unlikely(exec->vtx.copied.nr)) { |
||
298 | GLfloat *data = exec->vtx.copied.buffer; |
||
299 | GLfloat *dest = exec->vtx.buffer_ptr; |
||
300 | GLuint j; |
||
301 | |||
302 | assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); |
||
303 | |||
304 | for (i = 0 ; i < exec->vtx.copied.nr ; i++) { |
||
305 | for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { |
||
306 | GLuint sz = exec->vtx.attrsz[j]; |
||
307 | |||
308 | if (sz) { |
||
309 | GLint old_offset = old_attrptr[j] - exec->vtx.vertex; |
||
310 | GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; |
||
311 | |||
312 | if (j == attr) { |
||
313 | if (oldsz) { |
||
314 | GLfloat tmp[4]; |
||
315 | COPY_CLEAN_4V(tmp, oldsz, data + old_offset); |
||
316 | COPY_SZ_4V(dest + new_offset, newsz, tmp); |
||
317 | } else { |
||
318 | GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; |
||
319 | COPY_SZ_4V(dest + new_offset, sz, current); |
||
320 | } |
||
321 | } |
||
322 | else { |
||
323 | COPY_SZ_4V(dest + new_offset, sz, data + old_offset); |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | |||
328 | data += old_vtx_size; |
||
329 | dest += exec->vtx.vertex_size; |
||
330 | } |
||
331 | |||
332 | exec->vtx.buffer_ptr = dest; |
||
333 | exec->vtx.vert_count += exec->vtx.copied.nr; |
||
334 | exec->vtx.copied.nr = 0; |
||
335 | } |
||
336 | } |
||
337 | |||
338 | |||
339 | static void vbo_exec_fixup_vertex( struct gl_context *ctx, |
||
340 | GLuint attr, GLuint sz ) |
||
341 | { |
||
342 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
343 | int i; |
||
344 | |||
345 | if (sz > exec->vtx.attrsz[attr]) { |
||
346 | /* New size is larger. Need to flush existing vertices and get |
||
347 | * an enlarged vertex format. |
||
348 | */ |
||
349 | vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); |
||
350 | } |
||
351 | else if (sz < exec->vtx.active_sz[attr]) { |
||
352 | static const GLfloat id[4] = { 0, 0, 0, 1 }; |
||
353 | |||
354 | /* New size is smaller - just need to fill in some |
||
355 | * zeros. Don't need to flush or wrap. |
||
356 | */ |
||
357 | for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) |
||
358 | exec->vtx.attrptr[attr][i-1] = id[i-1]; |
||
359 | } |
||
360 | |||
361 | exec->vtx.active_sz[attr] = sz; |
||
362 | |||
363 | /* Does setting NeedFlush belong here? Necessitates resetting |
||
364 | * vtxfmt on each flush (otherwise flags won't get reset |
||
365 | * afterwards). |
||
366 | */ |
||
367 | if (attr == 0) |
||
368 | exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
||
369 | } |
||
370 | |||
371 | |||
372 | /* |
||
373 | */ |
||
374 | #define ATTR( A, N, V0, V1, V2, V3 ) \ |
||
375 | do { \ |
||
376 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ |
||
377 | \ |
||
378 | if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ |
||
379 | ctx->Driver.BeginVertices( ctx ); \ |
||
380 | if (unlikely(exec->vtx.active_sz[A] != N)) \ |
||
381 | vbo_exec_fixup_vertex(ctx, A, N); \ |
||
382 | \ |
||
383 | { \ |
||
384 | GLfloat *dest = exec->vtx.attrptr[A]; \ |
||
385 | if (N>0) dest[0] = V0; \ |
||
386 | if (N>1) dest[1] = V1; \ |
||
387 | if (N>2) dest[2] = V2; \ |
||
388 | if (N>3) dest[3] = V3; \ |
||
389 | } \ |
||
390 | \ |
||
391 | if ((A) == 0) { \ |
||
392 | GLuint i; \ |
||
393 | \ |
||
394 | for (i = 0; i < exec->vtx.vertex_size; i++) \ |
||
395 | exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ |
||
396 | \ |
||
397 | exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ |
||
398 | exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ |
||
399 | \ |
||
400 | if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ |
||
401 | vbo_exec_vtx_wrap( exec ); \ |
||
402 | } \ |
||
403 | } while (0) |
||
404 | |||
405 | |||
406 | #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ) |
||
407 | #define TAG(x) vbo_##x |
||
408 | |||
409 | #include "vbo_attrib_tmp.h" |
||
410 | |||
411 | |||
412 | #if FEATURE_beginend |
||
413 | |||
414 | |||
415 | #if FEATURE_evaluators |
||
416 | |||
417 | static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) |
||
418 | { |
||
419 | GET_CURRENT_CONTEXT( ctx ); |
||
420 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
421 | |||
422 | { |
||
423 | GLint i; |
||
424 | if (exec->eval.recalculate_maps) |
||
425 | vbo_exec_eval_update( exec ); |
||
426 | |||
427 | for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { |
||
428 | if (exec->eval.map1[i].map) |
||
429 | if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) |
||
430 | vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz ); |
||
431 | } |
||
432 | } |
||
433 | |||
434 | |||
435 | memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, |
||
436 | exec->vtx.vertex_size * sizeof(GLfloat)); |
||
437 | |||
438 | vbo_exec_do_EvalCoord1f( exec, u ); |
||
439 | |||
440 | memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, |
||
441 | exec->vtx.vertex_size * sizeof(GLfloat)); |
||
442 | } |
||
443 | |||
444 | static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) |
||
445 | { |
||
446 | GET_CURRENT_CONTEXT( ctx ); |
||
447 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
448 | |||
449 | { |
||
450 | GLint i; |
||
451 | if (exec->eval.recalculate_maps) |
||
452 | vbo_exec_eval_update( exec ); |
||
453 | |||
454 | for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { |
||
455 | if (exec->eval.map2[i].map) |
||
456 | if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) |
||
457 | vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz ); |
||
458 | } |
||
459 | |||
460 | if (ctx->Eval.AutoNormal) |
||
461 | if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) |
||
462 | vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); |
||
463 | } |
||
464 | |||
465 | memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, |
||
466 | exec->vtx.vertex_size * sizeof(GLfloat)); |
||
467 | |||
468 | vbo_exec_do_EvalCoord2f( exec, u, v ); |
||
469 | |||
470 | memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, |
||
471 | exec->vtx.vertex_size * sizeof(GLfloat)); |
||
472 | } |
||
473 | |||
474 | static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u ) |
||
475 | { |
||
476 | vbo_exec_EvalCoord1f( u[0] ); |
||
477 | } |
||
478 | |||
479 | static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u ) |
||
480 | { |
||
481 | vbo_exec_EvalCoord2f( u[0], u[1] ); |
||
482 | } |
||
483 | |||
484 | static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i ) |
||
485 | { |
||
486 | GET_CURRENT_CONTEXT( ctx ); |
||
487 | GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / |
||
488 | (GLfloat) ctx->Eval.MapGrid1un); |
||
489 | GLfloat u = i * du + ctx->Eval.MapGrid1u1; |
||
490 | |||
491 | vbo_exec_EvalCoord1f( u ); |
||
492 | } |
||
493 | |||
494 | |||
495 | static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) |
||
496 | { |
||
497 | GET_CURRENT_CONTEXT( ctx ); |
||
498 | GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / |
||
499 | (GLfloat) ctx->Eval.MapGrid2un); |
||
500 | GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / |
||
501 | (GLfloat) ctx->Eval.MapGrid2vn); |
||
502 | GLfloat u = i * du + ctx->Eval.MapGrid2u1; |
||
503 | GLfloat v = j * dv + ctx->Eval.MapGrid2v1; |
||
504 | |||
505 | vbo_exec_EvalCoord2f( u, v ); |
||
506 | } |
||
507 | |||
508 | /* use noop eval mesh */ |
||
509 | #define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1 |
||
510 | #define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2 |
||
511 | |||
512 | #endif /* FEATURE_evaluators */ |
||
513 | |||
514 | |||
515 | /** |
||
516 | * Called via glBegin. |
||
517 | */ |
||
518 | static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) |
||
519 | { |
||
520 | GET_CURRENT_CONTEXT( ctx ); |
||
521 | |||
522 | if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) { |
||
523 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
524 | int i; |
||
525 | |||
526 | if (ctx->NewState) { |
||
527 | _mesa_update_state( ctx ); |
||
528 | |||
529 | CALL_Begin(ctx->Exec, (mode)); |
||
530 | return; |
||
531 | } |
||
532 | |||
533 | if (!_mesa_valid_to_render(ctx, "glBegin")) { |
||
534 | return; |
||
535 | } |
||
536 | |||
537 | /* Heuristic: attempt to isolate attributes occuring outside |
||
538 | * begin/end pairs. |
||
539 | */ |
||
540 | if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) |
||
541 | vbo_exec_FlushVertices_internal( ctx, GL_FALSE ); |
||
542 | |||
543 | i = exec->vtx.prim_count++; |
||
544 | exec->vtx.prim[i].mode = mode; |
||
545 | exec->vtx.prim[i].begin = 1; |
||
546 | exec->vtx.prim[i].end = 0; |
||
547 | exec->vtx.prim[i].indexed = 0; |
||
548 | exec->vtx.prim[i].weak = 0; |
||
549 | exec->vtx.prim[i].pad = 0; |
||
550 | exec->vtx.prim[i].start = exec->vtx.vert_count; |
||
551 | exec->vtx.prim[i].count = 0; |
||
552 | exec->vtx.prim[i].num_instances = 1; |
||
553 | |||
554 | ctx->Driver.CurrentExecPrimitive = mode; |
||
555 | } |
||
556 | else |
||
557 | _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); |
||
558 | |||
559 | } |
||
560 | |||
561 | |||
562 | /** |
||
563 | * Called via glEnd. |
||
564 | */ |
||
565 | static void GLAPIENTRY vbo_exec_End( void ) |
||
566 | { |
||
567 | GET_CURRENT_CONTEXT( ctx ); |
||
568 | |||
569 | if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { |
||
570 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
571 | int idx = exec->vtx.vert_count; |
||
572 | int i = exec->vtx.prim_count - 1; |
||
573 | |||
574 | exec->vtx.prim[i].end = 1; |
||
575 | exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; |
||
576 | |||
577 | ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; |
||
578 | |||
579 | if (exec->vtx.prim_count == VBO_MAX_PRIM) |
||
580 | vbo_exec_vtx_flush( exec, GL_FALSE ); |
||
581 | } |
||
582 | else |
||
583 | _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); |
||
584 | } |
||
585 | |||
586 | |||
587 | /** |
||
588 | * Called via glPrimitiveRestartNV() |
||
589 | */ |
||
590 | static void GLAPIENTRY |
||
591 | vbo_exec_PrimitiveRestartNV(void) |
||
592 | { |
||
593 | GLenum curPrim; |
||
594 | GET_CURRENT_CONTEXT( ctx ); |
||
595 | |||
596 | curPrim = ctx->Driver.CurrentExecPrimitive; |
||
597 | |||
598 | if (curPrim == PRIM_OUTSIDE_BEGIN_END) { |
||
599 | _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" ); |
||
600 | } |
||
601 | else { |
||
602 | vbo_exec_End(); |
||
603 | vbo_exec_Begin(curPrim); |
||
604 | } |
||
605 | } |
||
606 | |||
607 | |||
608 | |||
609 | static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) |
||
610 | { |
||
611 | GLvertexformat *vfmt = &exec->vtxfmt; |
||
612 | |||
613 | _MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_); |
||
614 | |||
615 | vfmt->Begin = vbo_exec_Begin; |
||
616 | vfmt->End = vbo_exec_End; |
||
617 | vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV; |
||
618 | |||
619 | _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_); |
||
620 | _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_); |
||
621 | |||
622 | vfmt->Rectf = _mesa_noop_Rectf; |
||
623 | |||
624 | /* from attrib_tmp.h: |
||
625 | */ |
||
626 | vfmt->Color3f = vbo_Color3f; |
||
627 | vfmt->Color3fv = vbo_Color3fv; |
||
628 | vfmt->Color4f = vbo_Color4f; |
||
629 | vfmt->Color4fv = vbo_Color4fv; |
||
630 | vfmt->FogCoordfEXT = vbo_FogCoordfEXT; |
||
631 | vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT; |
||
632 | vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f; |
||
633 | vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv; |
||
634 | vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f; |
||
635 | vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv; |
||
636 | vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f; |
||
637 | vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv; |
||
638 | vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f; |
||
639 | vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv; |
||
640 | vfmt->Normal3f = vbo_Normal3f; |
||
641 | vfmt->Normal3fv = vbo_Normal3fv; |
||
642 | vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT; |
||
643 | vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT; |
||
644 | vfmt->TexCoord1f = vbo_TexCoord1f; |
||
645 | vfmt->TexCoord1fv = vbo_TexCoord1fv; |
||
646 | vfmt->TexCoord2f = vbo_TexCoord2f; |
||
647 | vfmt->TexCoord2fv = vbo_TexCoord2fv; |
||
648 | vfmt->TexCoord3f = vbo_TexCoord3f; |
||
649 | vfmt->TexCoord3fv = vbo_TexCoord3fv; |
||
650 | vfmt->TexCoord4f = vbo_TexCoord4f; |
||
651 | vfmt->TexCoord4fv = vbo_TexCoord4fv; |
||
652 | vfmt->Vertex2f = vbo_Vertex2f; |
||
653 | vfmt->Vertex2fv = vbo_Vertex2fv; |
||
654 | vfmt->Vertex3f = vbo_Vertex3f; |
||
655 | vfmt->Vertex3fv = vbo_Vertex3fv; |
||
656 | vfmt->Vertex4f = vbo_Vertex4f; |
||
657 | vfmt->Vertex4fv = vbo_Vertex4fv; |
||
658 | |||
659 | vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB; |
||
660 | vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB; |
||
661 | vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB; |
||
662 | vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB; |
||
663 | vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB; |
||
664 | vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB; |
||
665 | vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB; |
||
666 | vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB; |
||
667 | |||
668 | vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV; |
||
669 | vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV; |
||
670 | vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV; |
||
671 | vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV; |
||
672 | vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV; |
||
673 | vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV; |
||
674 | vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; |
||
675 | vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; |
||
676 | |||
677 | /* integer-valued */ |
||
678 | vfmt->VertexAttribI1i = vbo_VertexAttribI1i; |
||
679 | vfmt->VertexAttribI2i = vbo_VertexAttribI2i; |
||
680 | vfmt->VertexAttribI3i = vbo_VertexAttribI3i; |
||
681 | vfmt->VertexAttribI4i = vbo_VertexAttribI4i; |
||
682 | vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv; |
||
683 | vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv; |
||
684 | vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv; |
||
685 | |||
686 | /* unsigned integer-valued */ |
||
687 | vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui; |
||
688 | vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui; |
||
689 | vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui; |
||
690 | vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui; |
||
691 | vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv; |
||
692 | vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv; |
||
693 | vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv; |
||
694 | |||
695 | vfmt->Materialfv = vbo_Materialfv; |
||
696 | |||
697 | vfmt->EdgeFlag = vbo_EdgeFlag; |
||
698 | vfmt->Indexf = vbo_Indexf; |
||
699 | vfmt->Indexfv = vbo_Indexfv; |
||
700 | |||
701 | } |
||
702 | |||
703 | |||
704 | #else /* FEATURE_beginend */ |
||
705 | |||
706 | |||
707 | static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) |
||
708 | { |
||
709 | /* silence warnings */ |
||
710 | (void) vbo_Color3f; |
||
711 | (void) vbo_Color3fv; |
||
712 | (void) vbo_Color4f; |
||
713 | (void) vbo_Color4fv; |
||
714 | (void) vbo_FogCoordfEXT; |
||
715 | (void) vbo_FogCoordfvEXT; |
||
716 | (void) vbo_MultiTexCoord1f; |
||
717 | (void) vbo_MultiTexCoord1fv; |
||
718 | (void) vbo_MultiTexCoord2f; |
||
719 | (void) vbo_MultiTexCoord2fv; |
||
720 | (void) vbo_MultiTexCoord3f; |
||
721 | (void) vbo_MultiTexCoord3fv; |
||
722 | (void) vbo_MultiTexCoord4f; |
||
723 | (void) vbo_MultiTexCoord4fv; |
||
724 | (void) vbo_Normal3f; |
||
725 | (void) vbo_Normal3fv; |
||
726 | (void) vbo_SecondaryColor3fEXT; |
||
727 | (void) vbo_SecondaryColor3fvEXT; |
||
728 | (void) vbo_TexCoord1f; |
||
729 | (void) vbo_TexCoord1fv; |
||
730 | (void) vbo_TexCoord2f; |
||
731 | (void) vbo_TexCoord2fv; |
||
732 | (void) vbo_TexCoord3f; |
||
733 | (void) vbo_TexCoord3fv; |
||
734 | (void) vbo_TexCoord4f; |
||
735 | (void) vbo_TexCoord4fv; |
||
736 | (void) vbo_Vertex2f; |
||
737 | (void) vbo_Vertex2fv; |
||
738 | (void) vbo_Vertex3f; |
||
739 | (void) vbo_Vertex3fv; |
||
740 | (void) vbo_Vertex4f; |
||
741 | (void) vbo_Vertex4fv; |
||
742 | |||
743 | (void) vbo_VertexAttrib1fARB; |
||
744 | (void) vbo_VertexAttrib1fvARB; |
||
745 | (void) vbo_VertexAttrib2fARB; |
||
746 | (void) vbo_VertexAttrib2fvARB; |
||
747 | (void) vbo_VertexAttrib3fARB; |
||
748 | (void) vbo_VertexAttrib3fvARB; |
||
749 | (void) vbo_VertexAttrib4fARB; |
||
750 | (void) vbo_VertexAttrib4fvARB; |
||
751 | |||
752 | (void) vbo_VertexAttrib1fNV; |
||
753 | (void) vbo_VertexAttrib1fvNV; |
||
754 | (void) vbo_VertexAttrib2fNV; |
||
755 | (void) vbo_VertexAttrib2fvNV; |
||
756 | (void) vbo_VertexAttrib3fNV; |
||
757 | (void) vbo_VertexAttrib3fvNV; |
||
758 | (void) vbo_VertexAttrib4fNV; |
||
759 | (void) vbo_VertexAttrib4fvNV; |
||
760 | |||
761 | (void) vbo_Materialfv; |
||
762 | |||
763 | (void) vbo_EdgeFlag; |
||
764 | (void) vbo_Indexf; |
||
765 | (void) vbo_Indexfv; |
||
766 | } |
||
767 | |||
768 | |||
769 | #endif /* FEATURE_beginend */ |
||
770 | |||
771 | |||
772 | /** |
||
773 | * Tell the VBO module to use a real OpenGL vertex buffer object to |
||
774 | * store accumulated immediate-mode vertex data. |
||
775 | * This replaces the malloced buffer which was created in |
||
776 | * vb_exec_vtx_init() below. |
||
777 | */ |
||
778 | void vbo_use_buffer_objects(struct gl_context *ctx) |
||
779 | { |
||
780 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
781 | /* Any buffer name but 0 can be used here since this bufferobj won't |
||
782 | * go into the bufferobj hashtable. |
||
783 | */ |
||
784 | GLuint bufName = IMM_BUFFER_NAME; |
||
785 | GLenum target = GL_ARRAY_BUFFER_ARB; |
||
786 | GLenum usage = GL_STREAM_DRAW_ARB; |
||
787 | GLsizei size = VBO_VERT_BUFFER_SIZE; |
||
788 | |||
789 | /* Make sure this func is only used once */ |
||
790 | assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); |
||
791 | if (exec->vtx.buffer_map) { |
||
792 | _mesa_align_free(exec->vtx.buffer_map); |
||
793 | exec->vtx.buffer_map = NULL; |
||
794 | exec->vtx.buffer_ptr = NULL; |
||
795 | } |
||
796 | |||
797 | /* Allocate a real buffer object now */ |
||
798 | _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); |
||
799 | exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); |
||
800 | ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); |
||
801 | } |
||
802 | |||
803 | |||
804 | |||
805 | void vbo_exec_vtx_init( struct vbo_exec_context *exec ) |
||
806 | { |
||
807 | struct gl_context *ctx = exec->ctx; |
||
808 | struct vbo_context *vbo = vbo_context(ctx); |
||
809 | GLuint i; |
||
810 | |||
811 | /* Allocate a buffer object. Will just reuse this object |
||
812 | * continuously, unless vbo_use_buffer_objects() is called to enable |
||
813 | * use of real VBOs. |
||
814 | */ |
||
815 | _mesa_reference_buffer_object(ctx, |
||
816 | &exec->vtx.bufferobj, |
||
817 | ctx->Shared->NullBufferObj); |
||
818 | |||
819 | ASSERT(!exec->vtx.buffer_map); |
||
820 | exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); |
||
821 | exec->vtx.buffer_ptr = exec->vtx.buffer_map; |
||
822 | |||
823 | vbo_exec_vtxfmt_init( exec ); |
||
824 | |||
825 | /* Hook our functions into the dispatch table. |
||
826 | */ |
||
827 | _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); |
||
828 | |||
829 | for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { |
||
830 | ASSERT(i < Elements(exec->vtx.attrsz)); |
||
831 | exec->vtx.attrsz[i] = 0; |
||
832 | ASSERT(i < Elements(exec->vtx.active_sz)); |
||
833 | exec->vtx.active_sz[i] = 0; |
||
834 | } |
||
835 | for (i = 0 ; i < VERT_ATTRIB_MAX; i++) { |
||
836 | ASSERT(i < Elements(exec->vtx.inputs)); |
||
837 | ASSERT(i < Elements(exec->vtx.arrays)); |
||
838 | exec->vtx.inputs[i] = &exec->vtx.arrays[i]; |
||
839 | } |
||
840 | |||
841 | { |
||
842 | struct gl_client_array *arrays = exec->vtx.arrays; |
||
843 | unsigned i; |
||
844 | |||
845 | memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); |
||
846 | memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); |
||
847 | |||
848 | for (i = 0; i < 16; ++i) { |
||
849 | arrays[i ].BufferObj = NULL; |
||
850 | arrays[i + 16].BufferObj = NULL; |
||
851 | _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj, |
||
852 | vbo->legacy_currval[i].BufferObj); |
||
853 | _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj, |
||
854 | vbo->generic_currval[i].BufferObj); |
||
855 | } |
||
856 | } |
||
857 | |||
858 | exec->vtx.vertex_size = 0; |
||
859 | } |
||
860 | |||
861 | |||
862 | void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) |
||
863 | { |
||
864 | /* using a real VBO for vertex data */ |
||
865 | struct gl_context *ctx = exec->ctx; |
||
866 | unsigned i; |
||
867 | |||
868 | /* True VBOs should already be unmapped |
||
869 | */ |
||
870 | if (exec->vtx.buffer_map) { |
||
871 | ASSERT(exec->vtx.bufferobj->Name == 0 || |
||
872 | exec->vtx.bufferobj->Name == IMM_BUFFER_NAME); |
||
873 | if (exec->vtx.bufferobj->Name == 0) { |
||
874 | _mesa_align_free(exec->vtx.buffer_map); |
||
875 | exec->vtx.buffer_map = NULL; |
||
876 | exec->vtx.buffer_ptr = NULL; |
||
877 | } |
||
878 | } |
||
879 | |||
880 | /* Drop any outstanding reference to the vertex buffer |
||
881 | */ |
||
882 | for (i = 0; i < Elements(exec->vtx.arrays); i++) { |
||
883 | _mesa_reference_buffer_object(ctx, |
||
884 | &exec->vtx.arrays[i].BufferObj, |
||
885 | NULL); |
||
886 | } |
||
887 | |||
888 | /* Free the vertex buffer. Unmap first if needed. |
||
889 | */ |
||
890 | if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) { |
||
891 | ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj); |
||
892 | } |
||
893 | _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); |
||
894 | } |
||
895 | |||
896 | void vbo_exec_BeginVertices( struct gl_context *ctx ) |
||
897 | { |
||
898 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
899 | if (0) printf("%s\n", __FUNCTION__); |
||
900 | vbo_exec_vtx_map( exec ); |
||
901 | |||
902 | assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); |
||
903 | exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; |
||
904 | } |
||
905 | |||
906 | void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap ) |
||
907 | { |
||
908 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
909 | |||
910 | if (exec->vtx.vert_count || unmap) { |
||
911 | vbo_exec_vtx_flush( exec, unmap ); |
||
912 | } |
||
913 | |||
914 | if (exec->vtx.vertex_size) { |
||
915 | vbo_exec_copy_to_current( exec ); |
||
916 | reset_attrfv( exec ); |
||
917 | } |
||
918 | } |
||
919 | |||
920 | |||
921 | /** |
||
922 | * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT |
||
923 | */ |
||
924 | void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) |
||
925 | { |
||
926 | struct vbo_exec_context *exec = &vbo_context(ctx)->exec; |
||
927 | |||
928 | #ifdef DEBUG |
||
929 | /* debug check: make sure we don't get called recursively */ |
||
930 | exec->flush_call_depth++; |
||
931 | assert(exec->flush_call_depth == 1); |
||
932 | #endif |
||
933 | |||
934 | if (0) printf("%s\n", __FUNCTION__); |
||
935 | |||
936 | if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { |
||
937 | if (0) printf("%s - inside begin/end\n", __FUNCTION__); |
||
938 | #ifdef DEBUG |
||
939 | exec->flush_call_depth--; |
||
940 | assert(exec->flush_call_depth == 0); |
||
941 | #endif |
||
942 | return; |
||
943 | } |
||
944 | |||
945 | vbo_exec_FlushVertices_internal( ctx, GL_TRUE ); |
||
946 | |||
947 | /* Need to do this to ensure BeginVertices gets called again: |
||
948 | */ |
||
949 | if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) |
||
950 | exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; |
||
951 | |||
952 | exec->ctx->Driver.NeedFlush &= ~flags; |
||
953 | |||
954 | #ifdef DEBUG |
||
955 | exec->flush_call_depth--; |
||
956 | assert(exec->flush_call_depth == 0); |
||
957 | #endif |
||
958 | } |
||
959 | |||
960 | |||
961 | static void reset_attrfv( struct vbo_exec_context *exec ) |
||
962 | { |
||
963 | GLuint i; |
||
964 | |||
965 | for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { |
||
966 | exec->vtx.attrsz[i] = 0; |
||
967 | exec->vtx.active_sz[i] = 0; |
||
968 | } |
||
969 | |||
970 | exec->vtx.vertex_size = 0; |
||
971 | } |
||
972 | |||
973 | |||
974 | void GLAPIENTRY |
||
975 | _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) |
||
976 | { |
||
977 | vbo_Color4f(r, g, b, a); |
||
978 | } |
||
979 | |||
980 | |||
981 | void GLAPIENTRY |
||
982 | _es_Normal3f(GLfloat x, GLfloat y, GLfloat z) |
||
983 | { |
||
984 | vbo_Normal3f(x, y, z); |
||
985 | } |
||
986 | |||
987 | |||
988 | void GLAPIENTRY |
||
989 | _es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) |
||
990 | { |
||
991 | vbo_MultiTexCoord4f(target, s, t, r, q); |
||
992 | } |
||
993 | |||
994 | |||
995 | void GLAPIENTRY |
||
996 | _es_Materialfv(GLenum face, GLenum pname, const GLfloat *params) |
||
997 | { |
||
998 | vbo_Materialfv(face, pname, params); |
||
999 | } |
||
1000 | |||
1001 | |||
1002 | void GLAPIENTRY |
||
1003 | _es_Materialf(GLenum face, GLenum pname, GLfloat param) |
||
1004 | { |
||
1005 | GLfloat p[4]; |
||
1006 | p[0] = param; |
||
1007 | p[1] = p[2] = p[3] = 0.0F; |
||
1008 | vbo_Materialfv(face, pname, p); |
||
1009 | } |
||
1010 | |||
1011 | |||
1012 | /** |
||
1013 | * A special version of glVertexAttrib4f that does not treat index 0 as |
||
1014 | * VBO_ATTRIB_POS. |
||
1015 | */ |
||
1016 | static void |
||
1017 | VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
||
1018 | { |
||
1019 | GET_CURRENT_CONTEXT(ctx); |
||
1020 | if (index < MAX_VERTEX_GENERIC_ATTRIBS) |
||
1021 | ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w); |
||
1022 | else |
||
1023 | ERROR(); |
||
1024 | } |
||
1025 | |||
1026 | void GLAPIENTRY |
||
1027 | _es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) |
||
1028 | { |
||
1029 | VertexAttrib4f_nopos(index, x, y, z, w); |
||
1030 | } |
||
1031 | |||
1032 | |||
1033 | void GLAPIENTRY |
||
1034 | _es_VertexAttrib1f(GLuint indx, GLfloat x) |
||
1035 | { |
||
1036 | VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f); |
||
1037 | } |
||
1038 | |||
1039 | |||
1040 | void GLAPIENTRY |
||
1041 | _es_VertexAttrib1fv(GLuint indx, const GLfloat* values) |
||
1042 | { |
||
1043 | VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f); |
||
1044 | } |
||
1045 | |||
1046 | |||
1047 | void GLAPIENTRY |
||
1048 | _es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) |
||
1049 | { |
||
1050 | VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f); |
||
1051 | } |
||
1052 | |||
1053 | |||
1054 | void GLAPIENTRY |
||
1055 | _es_VertexAttrib2fv(GLuint indx, const GLfloat* values) |
||
1056 | { |
||
1057 | VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f); |
||
1058 | } |
||
1059 | |||
1060 | |||
1061 | void GLAPIENTRY |
||
1062 | _es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) |
||
1063 | { |
||
1064 | VertexAttrib4f_nopos(indx, x, y, z, 1.0f); |
||
1065 | } |
||
1066 | |||
1067 | |||
1068 | void GLAPIENTRY |
||
1069 | _es_VertexAttrib3fv(GLuint indx, const GLfloat* values) |
||
1070 | { |
||
1071 | VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f); |
||
1072 | } |
||
1073 | |||
1074 | |||
1075 | void GLAPIENTRY |
||
1076 | _es_VertexAttrib4fv(GLuint indx, const GLfloat* values) |
||
1077 | { |
||
1078 | VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]); |
||
1079 | }>>>>>>>>>>=>=>>=>>>>>>=>>> |