1 /**************************************************************************
3 Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
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:
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
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.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
35 /* Display list compiler attempts to store lists of vertices with the
36 * same vertex layout. Additionally it attempts to minimize the need
37 * for execute-time fixup of these vertex lists, allowing them to be
40 * There are still some circumstances where this can be thwarted, for
41 * example by building a list that consists of one very long primitive
42 * (eg Begin(Triangles), 1000 vertices, End), and calling that list
43 * from inside a different begin/end object (Begin(Lines), CallList,
46 * In that case the code will have to replay the list as individual
47 * commands through the Exec dispatch table, or fix up the copied
48 * vertices at execute-time.
50 * The other case where fixup is required is when a vertex attribute
51 * is introduced in the middle of a primitive. Eg:
53 * TexCoord1f() Vertex2f()
54 * TexCoord1f() Color3f() Vertex2f()
57 * If the current value of Color isn't known at compile-time, this
58 * primitive will require fixup.
61 * The list compiler currently doesn't attempt to compile lists
62 * containing EvalCoord or EvalPoint commands. On encountering one of
63 * these, compilation falls back to opcodes.
65 * This could be improved to fallback only when a mix of EvalCoord and
66 * Vertex commands are issued within a single primitive.
70 #include "main/glheader.h"
71 #include "main/bufferobj.h"
72 #include "main/context.h"
73 #include "main/dlist.h"
74 #include "main/enums.h"
75 #include "main/eval.h"
76 #include "main/macros.h"
77 #include "main/mfeatures.h"
78 #include "main/api_validate.h"
79 #include "main/api_arrayelt.h"
80 #include "main/vtxfmt.h"
81 #include "main/dispatch.h"
83 #include "vbo_context.h"
94 /* An interesting VBO number/name to help with debugging */
95 #define VBO_BUF_ID 12345
99 * NOTE: Old 'parity' issue is gone, but copying can still be
100 * wrong-footed on replay.
103 _save_copy_vertices(struct gl_context
*ctx
,
104 const struct vbo_save_vertex_list
*node
,
105 const GLfloat
* src_buffer
)
107 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
108 const struct _mesa_prim
*prim
= &node
->prim
[node
->prim_count
- 1];
109 GLuint nr
= prim
->count
;
110 GLuint sz
= save
->vertex_size
;
111 const GLfloat
*src
= src_buffer
+ prim
->start
* sz
;
112 GLfloat
*dst
= save
->copied
.buffer
;
118 switch (prim
->mode
) {
123 for (i
= 0; i
< ovf
; i
++)
124 memcpy(dst
+ i
* sz
, src
+ (nr
- ovf
+ i
) * sz
,
125 sz
* sizeof(GLfloat
));
129 for (i
= 0; i
< ovf
; i
++)
130 memcpy(dst
+ i
* sz
, src
+ (nr
- ovf
+ i
) * sz
,
131 sz
* sizeof(GLfloat
));
135 for (i
= 0; i
< ovf
; i
++)
136 memcpy(dst
+ i
* sz
, src
+ (nr
- ovf
+ i
) * sz
,
137 sz
* sizeof(GLfloat
));
143 memcpy(dst
, src
+ (nr
- 1) * sz
, sz
* sizeof(GLfloat
));
147 case GL_TRIANGLE_FAN
:
152 memcpy(dst
, src
+ 0, sz
* sizeof(GLfloat
));
156 memcpy(dst
, src
+ 0, sz
* sizeof(GLfloat
));
157 memcpy(dst
+ sz
, src
+ (nr
- 1) * sz
, sz
* sizeof(GLfloat
));
160 case GL_TRIANGLE_STRIP
:
173 for (i
= 0; i
< ovf
; i
++)
174 memcpy(dst
+ i
* sz
, src
+ (nr
- ovf
+ i
) * sz
,
175 sz
* sizeof(GLfloat
));
184 static struct vbo_save_vertex_store
*
185 alloc_vertex_store(struct gl_context
*ctx
)
187 struct vbo_save_vertex_store
*vertex_store
=
188 CALLOC_STRUCT(vbo_save_vertex_store
);
190 /* obj->Name needs to be non-zero, but won't ever be examined more
191 * closely than that. In particular these buffers won't be entered
192 * into the hash and can never be confused with ones visible to the
193 * user. Perhaps there could be a special number for internal
196 vertex_store
->bufferobj
= ctx
->Driver
.NewBufferObject(ctx
,
198 GL_ARRAY_BUFFER_ARB
);
200 ctx
->Driver
.BufferData(ctx
,
202 VBO_SAVE_BUFFER_SIZE
* sizeof(GLfloat
),
203 NULL
, GL_STATIC_DRAW_ARB
, vertex_store
->bufferobj
);
205 vertex_store
->buffer
= NULL
;
206 vertex_store
->used
= 0;
207 vertex_store
->refcount
= 1;
214 free_vertex_store(struct gl_context
*ctx
,
215 struct vbo_save_vertex_store
*vertex_store
)
217 assert(!vertex_store
->buffer
);
219 if (vertex_store
->bufferobj
) {
220 _mesa_reference_buffer_object(ctx
, &vertex_store
->bufferobj
, NULL
);
228 map_vertex_store(struct gl_context
*ctx
,
229 struct vbo_save_vertex_store
*vertex_store
)
231 assert(vertex_store
->bufferobj
);
232 assert(!vertex_store
->buffer
);
233 vertex_store
->buffer
=
234 (GLfloat
*) ctx
->Driver
.MapBufferRange(ctx
, 0,
235 vertex_store
->bufferobj
->Size
,
236 GL_MAP_WRITE_BIT
, /* not used */
237 vertex_store
->bufferobj
);
239 assert(vertex_store
->buffer
);
240 return vertex_store
->buffer
+ vertex_store
->used
;
245 unmap_vertex_store(struct gl_context
*ctx
,
246 struct vbo_save_vertex_store
*vertex_store
)
248 ctx
->Driver
.UnmapBuffer(ctx
, vertex_store
->bufferobj
);
249 vertex_store
->buffer
= NULL
;
253 static struct vbo_save_primitive_store
*
254 alloc_prim_store(struct gl_context
*ctx
)
256 struct vbo_save_primitive_store
*store
=
257 CALLOC_STRUCT(vbo_save_primitive_store
);
266 _save_reset_counters(struct gl_context
*ctx
)
268 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
270 save
->prim
= save
->prim_store
->buffer
+ save
->prim_store
->used
;
271 save
->buffer
= save
->vertex_store
->buffer
+ save
->vertex_store
->used
;
273 assert(save
->buffer
== save
->buffer_ptr
);
275 if (save
->vertex_size
)
276 save
->max_vert
= ((VBO_SAVE_BUFFER_SIZE
- save
->vertex_store
->used
) /
281 save
->vert_count
= 0;
282 save
->prim_count
= 0;
283 save
->prim_max
= VBO_SAVE_PRIM_SIZE
- save
->prim_store
->used
;
284 save
->dangling_attr_ref
= 0;
289 * Insert the active immediate struct onto the display list currently
293 _save_compile_vertex_list(struct gl_context
*ctx
)
295 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
296 struct vbo_save_vertex_list
*node
;
298 /* Allocate space for this structure in the display list currently
301 node
= (struct vbo_save_vertex_list
*)
302 _mesa_dlist_alloc(ctx
, save
->opcode_vertex_list
, sizeof(*node
));
307 /* Duplicate our template, increment refcounts to the storage structs:
309 memcpy(node
->attrsz
, save
->attrsz
, sizeof(node
->attrsz
));
310 node
->vertex_size
= save
->vertex_size
;
311 node
->buffer_offset
=
312 (save
->buffer
- save
->vertex_store
->buffer
) * sizeof(GLfloat
);
313 node
->count
= save
->vert_count
;
314 node
->wrap_count
= save
->copied
.nr
;
315 node
->dangling_attr_ref
= save
->dangling_attr_ref
;
316 node
->prim
= save
->prim
;
317 node
->prim_count
= save
->prim_count
;
318 node
->vertex_store
= save
->vertex_store
;
319 node
->prim_store
= save
->prim_store
;
321 node
->vertex_store
->refcount
++;
322 node
->prim_store
->refcount
++;
324 if (node
->prim
[0].no_current_update
) {
325 node
->current_size
= 0;
326 node
->current_data
= NULL
;
329 node
->current_size
= node
->vertex_size
- node
->attrsz
[0];
330 node
->current_data
= NULL
;
332 if (node
->current_size
) {
333 /* If the malloc fails, we just pull the data out of the VBO
336 node
->current_data
= MALLOC(node
->current_size
* sizeof(GLfloat
));
337 if (node
->current_data
) {
338 const char *buffer
= (const char *) save
->vertex_store
->buffer
;
339 unsigned attr_offset
= node
->attrsz
[0] * sizeof(GLfloat
);
340 unsigned vertex_offset
= 0;
344 (node
->count
- 1) * node
->vertex_size
* sizeof(GLfloat
);
346 memcpy(node
->current_data
,
347 buffer
+ node
->buffer_offset
+ vertex_offset
+ attr_offset
,
348 node
->current_size
* sizeof(GLfloat
));
353 assert(node
->attrsz
[VBO_ATTRIB_POS
] != 0 || node
->count
== 0);
355 if (save
->dangling_attr_ref
)
356 ctx
->ListState
.CurrentList
->Flags
|= DLIST_DANGLING_REFS
;
358 save
->vertex_store
->used
+= save
->vertex_size
* node
->count
;
359 save
->prim_store
->used
+= node
->prim_count
;
361 /* Copy duplicated vertices
363 save
->copied
.nr
= _save_copy_vertices(ctx
, node
, save
->buffer
);
365 /* Deal with GL_COMPILE_AND_EXECUTE:
367 if (ctx
->ExecuteFlag
) {
368 struct _glapi_table
*dispatch
= GET_DISPATCH();
370 _glapi_set_dispatch(ctx
->Exec
);
372 vbo_loopback_vertex_list(ctx
,
373 (const GLfloat
*) ((const char *) save
->
374 vertex_store
->buffer
+
375 node
->buffer_offset
),
376 node
->attrsz
, node
->prim
, node
->prim_count
,
377 node
->wrap_count
, node
->vertex_size
);
379 _glapi_set_dispatch(dispatch
);
382 /* Decide whether the storage structs are full, or can be used for
383 * the next vertex lists as well.
385 if (save
->vertex_store
->used
>
386 VBO_SAVE_BUFFER_SIZE
- 16 * (save
->vertex_size
+ 4)) {
390 unmap_vertex_store(ctx
, save
->vertex_store
);
392 /* Release old reference:
394 save
->vertex_store
->refcount
--;
395 assert(save
->vertex_store
->refcount
!= 0);
396 save
->vertex_store
= NULL
;
398 /* Allocate and map new store:
400 save
->vertex_store
= alloc_vertex_store(ctx
);
401 save
->buffer_ptr
= map_vertex_store(ctx
, save
->vertex_store
);
404 if (save
->prim_store
->used
> VBO_SAVE_PRIM_SIZE
- 6) {
405 save
->prim_store
->refcount
--;
406 assert(save
->prim_store
->refcount
!= 0);
407 save
->prim_store
= alloc_prim_store(ctx
);
410 /* Reset our structures for the next run of vertices:
412 _save_reset_counters(ctx
);
417 * TODO -- If no new vertices have been stored, don't bother saving it.
420 _save_wrap_buffers(struct gl_context
*ctx
)
422 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
423 GLint i
= save
->prim_count
- 1;
426 GLboolean no_current_update
;
428 assert(i
< (GLint
) save
->prim_max
);
431 /* Close off in-progress primitive.
433 save
->prim
[i
].count
= (save
->vert_count
- save
->prim
[i
].start
);
434 mode
= save
->prim
[i
].mode
;
435 weak
= save
->prim
[i
].weak
;
436 no_current_update
= save
->prim
[i
].no_current_update
;
438 /* store the copied vertices, and allocate a new list.
440 _save_compile_vertex_list(ctx
);
442 /* Restart interrupted primitive
444 save
->prim
[0].mode
= mode
;
445 save
->prim
[0].weak
= weak
;
446 save
->prim
[0].no_current_update
= no_current_update
;
447 save
->prim
[0].begin
= 0;
448 save
->prim
[0].end
= 0;
449 save
->prim
[0].pad
= 0;
450 save
->prim
[0].start
= 0;
451 save
->prim
[0].count
= 0;
452 save
->prim
[0].num_instances
= 1;
453 save
->prim_count
= 1;
458 * Called only when buffers are wrapped as the result of filling the
459 * vertex_store struct.
462 _save_wrap_filled_vertex(struct gl_context
*ctx
)
464 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
465 GLfloat
*data
= save
->copied
.buffer
;
468 /* Emit a glEnd to close off the last vertex list.
470 _save_wrap_buffers(ctx
);
472 /* Copy stored stored vertices to start of new list.
474 assert(save
->max_vert
- save
->vert_count
> save
->copied
.nr
);
476 for (i
= 0; i
< save
->copied
.nr
; i
++) {
477 memcpy(save
->buffer_ptr
, data
, save
->vertex_size
* sizeof(GLfloat
));
478 data
+= save
->vertex_size
;
479 save
->buffer_ptr
+= save
->vertex_size
;
486 _save_copy_to_current(struct gl_context
*ctx
)
488 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
491 for (i
= VBO_ATTRIB_POS
+ 1; i
< VBO_ATTRIB_MAX
; i
++) {
492 if (save
->attrsz
[i
]) {
493 save
->currentsz
[i
][0] = save
->attrsz
[i
];
494 COPY_CLEAN_4V(save
->current
[i
], save
->attrsz
[i
], save
->attrptr
[i
]);
501 _save_copy_from_current(struct gl_context
*ctx
)
503 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
506 for (i
= VBO_ATTRIB_POS
+ 1; i
< VBO_ATTRIB_MAX
; i
++) {
507 switch (save
->attrsz
[i
]) {
509 save
->attrptr
[i
][3] = save
->current
[i
][3];
511 save
->attrptr
[i
][2] = save
->current
[i
][2];
513 save
->attrptr
[i
][1] = save
->current
[i
][1];
515 save
->attrptr
[i
][0] = save
->current
[i
][0];
523 /* Flush existing data, set new attrib size, replay copied vertices.
526 _save_upgrade_vertex(struct gl_context
*ctx
, GLuint attr
, GLuint newsz
)
528 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
533 /* Store the current run of vertices, and emit a GL_END. Emit a
534 * BEGIN in the new buffer.
536 if (save
->vert_count
)
537 _save_wrap_buffers(ctx
);
539 assert(save
->copied
.nr
== 0);
541 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
542 * when the attribute already exists in the vertex and is having
543 * its size increased.
545 _save_copy_to_current(ctx
);
549 oldsz
= save
->attrsz
[attr
];
550 save
->attrsz
[attr
] = newsz
;
552 save
->vertex_size
+= newsz
- oldsz
;
553 save
->max_vert
= ((VBO_SAVE_BUFFER_SIZE
- save
->vertex_store
->used
) /
555 save
->vert_count
= 0;
557 /* Recalculate all the attrptr[] values:
559 for (i
= 0, tmp
= save
->vertex
; i
< VBO_ATTRIB_MAX
; i
++) {
560 if (save
->attrsz
[i
]) {
561 save
->attrptr
[i
] = tmp
;
562 tmp
+= save
->attrsz
[i
];
565 save
->attrptr
[i
] = NULL
; /* will not be dereferenced. */
569 /* Copy from current to repopulate the vertex with correct values.
571 _save_copy_from_current(ctx
);
573 /* Replay stored vertices to translate them to new format here.
575 * If there are copied vertices and the new (upgraded) attribute
576 * has not been defined before, this list is somewhat degenerate,
577 * and will need fixup at runtime.
579 if (save
->copied
.nr
) {
580 GLfloat
*data
= save
->copied
.buffer
;
581 GLfloat
*dest
= save
->buffer
;
584 /* Need to note this and fix up at runtime (or loopback):
586 if (attr
!= VBO_ATTRIB_POS
&& save
->currentsz
[attr
][0] == 0) {
588 save
->dangling_attr_ref
= GL_TRUE
;
591 for (i
= 0; i
< save
->copied
.nr
; i
++) {
592 for (j
= 0; j
< VBO_ATTRIB_MAX
; j
++) {
593 if (save
->attrsz
[j
]) {
596 COPY_CLEAN_4V(dest
, oldsz
, data
);
601 COPY_SZ_4V(dest
, newsz
, save
->current
[attr
]);
606 GLint sz
= save
->attrsz
[j
];
607 COPY_SZ_4V(dest
, sz
, data
);
615 save
->buffer_ptr
= dest
;
616 save
->vert_count
+= save
->copied
.nr
;
622 save_fixup_vertex(struct gl_context
*ctx
, GLuint attr
, GLuint sz
)
624 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
626 if (sz
> save
->attrsz
[attr
]) {
627 /* New size is larger. Need to flush existing vertices and get
628 * an enlarged vertex format.
630 _save_upgrade_vertex(ctx
, attr
, sz
);
632 else if (sz
< save
->active_sz
[attr
]) {
633 static GLfloat id
[4] = { 0, 0, 0, 1 };
636 /* New size is equal or smaller - just need to fill in some
639 for (i
= sz
; i
<= save
->attrsz
[attr
]; i
++)
640 save
->attrptr
[attr
][i
- 1] = id
[i
- 1];
643 save
->active_sz
[attr
] = sz
;
648 _save_reset_vertex(struct gl_context
*ctx
)
650 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
653 for (i
= 0; i
< VBO_ATTRIB_MAX
; i
++) {
655 save
->active_sz
[i
] = 0;
658 save
->vertex_size
= 0;
663 #define ERROR(err) _mesa_compile_error(ctx, err, __FUNCTION__);
666 /* Only one size for each attribute may be active at once. Eg. if
667 * Color3f is installed/active, then Color4f may not be, even if the
668 * vertex actually contains 4 color coordinates. This is because the
669 * 3f version won't otherwise set color[3] to 1.0 -- this is the job
670 * of the chooser function when switching between Color4f and Color3f.
672 #define ATTR(A, N, V0, V1, V2, V3) \
674 struct vbo_save_context *save = &vbo_context(ctx)->save; \
676 if (save->active_sz[A] != N) \
677 save_fixup_vertex(ctx, A, N); \
680 GLfloat *dest = save->attrptr[A]; \
681 if (N>0) dest[0] = V0; \
682 if (N>1) dest[1] = V1; \
683 if (N>2) dest[2] = V2; \
684 if (N>3) dest[3] = V3; \
690 for (i = 0; i < save->vertex_size; i++) \
691 save->buffer_ptr[i] = save->vertex[i]; \
693 save->buffer_ptr += save->vertex_size; \
695 if (++save->vert_count >= save->max_vert) \
696 _save_wrap_filled_vertex(ctx); \
700 #define TAG(x) _save_##x
702 #include "vbo_attrib_tmp.h"
707 /* Cope with EvalCoord/CallList called within a begin/end object:
708 * -- Flush current buffer
709 * -- Fallback to opcodes for the rest of the begin/end object.
712 dlist_fallback(struct gl_context
*ctx
)
714 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
716 if (save
->vert_count
|| save
->prim_count
) {
717 if (save
->prim_count
> 0) {
718 /* Close off in-progress primitive. */
719 GLint i
= save
->prim_count
- 1;
720 save
->prim
[i
].count
= save
->vert_count
- save
->prim
[i
].start
;
723 /* Need to replay this display list with loopback,
724 * unfortunately, otherwise this primitive won't be handled
727 save
->dangling_attr_ref
= 1;
729 _save_compile_vertex_list(ctx
);
732 _save_copy_to_current(ctx
);
733 _save_reset_vertex(ctx
);
734 _save_reset_counters(ctx
);
735 _mesa_install_save_vtxfmt(ctx
, &ctx
->ListState
.ListVtxfmt
);
736 ctx
->Driver
.SaveNeedFlush
= 0;
740 static void GLAPIENTRY
741 _save_EvalCoord1f(GLfloat u
)
743 GET_CURRENT_CONTEXT(ctx
);
745 CALL_EvalCoord1f(ctx
->Save
, (u
));
748 static void GLAPIENTRY
749 _save_EvalCoord1fv(const GLfloat
* v
)
751 GET_CURRENT_CONTEXT(ctx
);
753 CALL_EvalCoord1fv(ctx
->Save
, (v
));
756 static void GLAPIENTRY
757 _save_EvalCoord2f(GLfloat u
, GLfloat v
)
759 GET_CURRENT_CONTEXT(ctx
);
761 CALL_EvalCoord2f(ctx
->Save
, (u
, v
));
764 static void GLAPIENTRY
765 _save_EvalCoord2fv(const GLfloat
* v
)
767 GET_CURRENT_CONTEXT(ctx
);
769 CALL_EvalCoord2fv(ctx
->Save
, (v
));
772 static void GLAPIENTRY
773 _save_EvalPoint1(GLint i
)
775 GET_CURRENT_CONTEXT(ctx
);
777 CALL_EvalPoint1(ctx
->Save
, (i
));
780 static void GLAPIENTRY
781 _save_EvalPoint2(GLint i
, GLint j
)
783 GET_CURRENT_CONTEXT(ctx
);
785 CALL_EvalPoint2(ctx
->Save
, (i
, j
));
788 static void GLAPIENTRY
789 _save_CallList(GLuint l
)
791 GET_CURRENT_CONTEXT(ctx
);
793 CALL_CallList(ctx
->Save
, (l
));
796 static void GLAPIENTRY
797 _save_CallLists(GLsizei n
, GLenum type
, const GLvoid
* v
)
799 GET_CURRENT_CONTEXT(ctx
);
801 CALL_CallLists(ctx
->Save
, (n
, type
, v
));
806 /* This begin is hooked into ... Updating of
807 * ctx->Driver.CurrentSavePrimitive is already taken care of.
810 vbo_save_NotifyBegin(struct gl_context
*ctx
, GLenum mode
)
812 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
814 GLuint i
= save
->prim_count
++;
816 assert(i
< save
->prim_max
);
817 save
->prim
[i
].mode
= mode
& VBO_SAVE_PRIM_MODE_MASK
;
818 save
->prim
[i
].begin
= 1;
819 save
->prim
[i
].end
= 0;
820 save
->prim
[i
].weak
= (mode
& VBO_SAVE_PRIM_WEAK
) ? 1 : 0;
821 save
->prim
[i
].no_current_update
=
822 (mode
& VBO_SAVE_PRIM_NO_CURRENT_UPDATE
) ? 1 : 0;
823 save
->prim
[i
].pad
= 0;
824 save
->prim
[i
].start
= save
->vert_count
;
825 save
->prim
[i
].count
= 0;
826 save
->prim
[i
].num_instances
= 1;
828 _mesa_install_save_vtxfmt(ctx
, &save
->vtxfmt
);
829 ctx
->Driver
.SaveNeedFlush
= 1;
834 static void GLAPIENTRY
837 GET_CURRENT_CONTEXT(ctx
);
838 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
839 GLint i
= save
->prim_count
- 1;
841 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
842 save
->prim
[i
].end
= 1;
843 save
->prim
[i
].count
= (save
->vert_count
- save
->prim
[i
].start
);
845 if (i
== (GLint
) save
->prim_max
- 1) {
846 _save_compile_vertex_list(ctx
);
847 assert(save
->copied
.nr
== 0);
850 /* Swap out this vertex format while outside begin/end. Any color,
851 * etc. received between here and the next begin will be compiled
854 _mesa_install_save_vtxfmt(ctx
, &ctx
->ListState
.ListVtxfmt
);
858 /* These are all errors as this vtxfmt is only installed inside
861 static void GLAPIENTRY
862 _save_DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
863 const GLvoid
* indices
)
865 GET_CURRENT_CONTEXT(ctx
);
870 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glDrawElements");
874 static void GLAPIENTRY
875 _save_DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
,
876 GLsizei count
, GLenum type
, const GLvoid
* indices
)
878 GET_CURRENT_CONTEXT(ctx
);
885 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glDrawRangeElements");
889 static void GLAPIENTRY
890 _save_DrawElementsBaseVertex(GLenum mode
, GLsizei count
, GLenum type
,
891 const GLvoid
* indices
, GLint basevertex
)
893 GET_CURRENT_CONTEXT(ctx
);
899 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glDrawElements");
903 static void GLAPIENTRY
904 _save_DrawRangeElementsBaseVertex(GLenum mode
,
909 const GLvoid
* indices
, GLint basevertex
)
911 GET_CURRENT_CONTEXT(ctx
);
919 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glDrawRangeElements");
923 static void GLAPIENTRY
924 _save_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
926 GET_CURRENT_CONTEXT(ctx
);
930 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glDrawArrays");
934 static void GLAPIENTRY
935 _save_MultiDrawElements(GLenum mode
, const GLsizei
*count
, GLenum type
,
936 const GLvoid
**indices
, GLsizei primcount
)
938 GET_CURRENT_CONTEXT(ctx
);
944 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glMultiDrawElements");
948 static void GLAPIENTRY
949 _save_MultiDrawElementsBaseVertex(GLenum mode
, const GLsizei
*count
,
950 GLenum type
, const GLvoid
**indices
,
951 GLsizei primcount
, const GLint
*basevertex
)
953 GET_CURRENT_CONTEXT(ctx
);
960 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
,
961 "glMultiDrawElementsBaseVertex");
965 static void GLAPIENTRY
966 _save_Rectf(GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
968 GET_CURRENT_CONTEXT(ctx
);
973 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glRectf");
977 static void GLAPIENTRY
978 _save_EvalMesh1(GLenum mode
, GLint i1
, GLint i2
)
980 GET_CURRENT_CONTEXT(ctx
);
984 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glEvalMesh1");
988 static void GLAPIENTRY
989 _save_EvalMesh2(GLenum mode
, GLint i1
, GLint i2
, GLint j1
, GLint j2
)
991 GET_CURRENT_CONTEXT(ctx
);
997 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "glEvalMesh2");
1001 static void GLAPIENTRY
1002 _save_Begin(GLenum mode
)
1004 GET_CURRENT_CONTEXT(ctx
);
1006 _mesa_compile_error(ctx
, GL_INVALID_OPERATION
, "Recursive glBegin");
1010 static void GLAPIENTRY
1011 _save_PrimitiveRestartNV(void)
1014 GET_CURRENT_CONTEXT(ctx
);
1016 curPrim
= ctx
->Driver
.CurrentSavePrimitive
;
1019 _save_Begin(curPrim
);
1023 /* Unlike the functions above, these are to be hooked into the vtxfmt
1024 * maintained in ctx->ListState, active when the list is known or
1025 * suspected to be outside any begin/end primitive.
1026 * Note: OBE = Outside Begin/End
1028 static void GLAPIENTRY
1029 _save_OBE_Rectf(GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1031 GET_CURRENT_CONTEXT(ctx
);
1032 vbo_save_NotifyBegin(ctx
, GL_QUADS
| VBO_SAVE_PRIM_WEAK
);
1033 CALL_Vertex2f(GET_DISPATCH(), (x1
, y1
));
1034 CALL_Vertex2f(GET_DISPATCH(), (x2
, y1
));
1035 CALL_Vertex2f(GET_DISPATCH(), (x2
, y2
));
1036 CALL_Vertex2f(GET_DISPATCH(), (x1
, y2
));
1037 CALL_End(GET_DISPATCH(), ());
1041 static void GLAPIENTRY
1042 _save_OBE_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
1044 GET_CURRENT_CONTEXT(ctx
);
1047 if (!_mesa_validate_DrawArrays(ctx
, mode
, start
, count
))
1052 vbo_save_NotifyBegin(ctx
, (mode
| VBO_SAVE_PRIM_WEAK
1053 | VBO_SAVE_PRIM_NO_CURRENT_UPDATE
));
1055 for (i
= 0; i
< count
; i
++)
1056 CALL_ArrayElement(GET_DISPATCH(), (start
+ i
));
1057 CALL_End(GET_DISPATCH(), ());
1059 _ae_unmap_vbos(ctx
);
1063 /* Could do better by copying the arrays and element list intact and
1064 * then emitting an indexed prim at runtime.
1066 static void GLAPIENTRY
1067 _save_OBE_DrawElements(GLenum mode
, GLsizei count
, GLenum type
,
1068 const GLvoid
* indices
)
1070 GET_CURRENT_CONTEXT(ctx
);
1073 if (!_mesa_validate_DrawElements(ctx
, mode
, count
, type
, indices
, 0))
1078 if (_mesa_is_bufferobj(ctx
->Array
.ElementArrayBufferObj
))
1080 ADD_POINTERS(ctx
->Array
.ElementArrayBufferObj
->Pointer
, indices
);
1082 vbo_save_NotifyBegin(ctx
, (mode
| VBO_SAVE_PRIM_WEAK
|
1083 VBO_SAVE_PRIM_NO_CURRENT_UPDATE
));
1086 case GL_UNSIGNED_BYTE
:
1087 for (i
= 0; i
< count
; i
++)
1088 CALL_ArrayElement(GET_DISPATCH(), (((GLubyte
*) indices
)[i
]));
1090 case GL_UNSIGNED_SHORT
:
1091 for (i
= 0; i
< count
; i
++)
1092 CALL_ArrayElement(GET_DISPATCH(), (((GLushort
*) indices
)[i
]));
1094 case GL_UNSIGNED_INT
:
1095 for (i
= 0; i
< count
; i
++)
1096 CALL_ArrayElement(GET_DISPATCH(), (((GLuint
*) indices
)[i
]));
1099 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawElements(type)");
1103 CALL_End(GET_DISPATCH(), ());
1105 _ae_unmap_vbos(ctx
);
1109 static void GLAPIENTRY
1110 _save_OBE_DrawRangeElements(GLenum mode
, GLuint start
, GLuint end
,
1111 GLsizei count
, GLenum type
,
1112 const GLvoid
* indices
)
1114 GET_CURRENT_CONTEXT(ctx
);
1115 if (_mesa_validate_DrawRangeElements(ctx
, mode
,
1116 start
, end
, count
, type
, indices
, 0)) {
1117 _save_OBE_DrawElements(mode
, count
, type
, indices
);
1122 static void GLAPIENTRY
1123 _save_OBE_MultiDrawElements(GLenum mode
, const GLsizei
*count
, GLenum type
,
1124 const GLvoid
**indices
, GLsizei primcount
)
1128 for (i
= 0; i
< primcount
; i
++) {
1130 CALL_DrawElements(GET_DISPATCH(), (mode
, count
[i
], type
, indices
[i
]));
1136 static void GLAPIENTRY
1137 _save_OBE_MultiDrawElementsBaseVertex(GLenum mode
, const GLsizei
*count
,
1139 const GLvoid
**indices
,
1141 const GLint
*basevertex
)
1145 for (i
= 0; i
< primcount
; i
++) {
1147 CALL_DrawElementsBaseVertex(GET_DISPATCH(), (mode
, count
[i
], type
,
1156 _save_vtxfmt_init(struct gl_context
*ctx
)
1158 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1159 GLvertexformat
*vfmt
= &save
->vtxfmt
;
1161 _MESA_INIT_ARRAYELT_VTXFMT(vfmt
, _ae_
);
1163 vfmt
->Begin
= _save_Begin
;
1164 vfmt
->Color3f
= _save_Color3f
;
1165 vfmt
->Color3fv
= _save_Color3fv
;
1166 vfmt
->Color4f
= _save_Color4f
;
1167 vfmt
->Color4fv
= _save_Color4fv
;
1168 vfmt
->EdgeFlag
= _save_EdgeFlag
;
1169 vfmt
->End
= _save_End
;
1170 vfmt
->PrimitiveRestartNV
= _save_PrimitiveRestartNV
;
1171 vfmt
->FogCoordfEXT
= _save_FogCoordfEXT
;
1172 vfmt
->FogCoordfvEXT
= _save_FogCoordfvEXT
;
1173 vfmt
->Indexf
= _save_Indexf
;
1174 vfmt
->Indexfv
= _save_Indexfv
;
1175 vfmt
->Materialfv
= _save_Materialfv
;
1176 vfmt
->MultiTexCoord1fARB
= _save_MultiTexCoord1f
;
1177 vfmt
->MultiTexCoord1fvARB
= _save_MultiTexCoord1fv
;
1178 vfmt
->MultiTexCoord2fARB
= _save_MultiTexCoord2f
;
1179 vfmt
->MultiTexCoord2fvARB
= _save_MultiTexCoord2fv
;
1180 vfmt
->MultiTexCoord3fARB
= _save_MultiTexCoord3f
;
1181 vfmt
->MultiTexCoord3fvARB
= _save_MultiTexCoord3fv
;
1182 vfmt
->MultiTexCoord4fARB
= _save_MultiTexCoord4f
;
1183 vfmt
->MultiTexCoord4fvARB
= _save_MultiTexCoord4fv
;
1184 vfmt
->Normal3f
= _save_Normal3f
;
1185 vfmt
->Normal3fv
= _save_Normal3fv
;
1186 vfmt
->SecondaryColor3fEXT
= _save_SecondaryColor3fEXT
;
1187 vfmt
->SecondaryColor3fvEXT
= _save_SecondaryColor3fvEXT
;
1188 vfmt
->TexCoord1f
= _save_TexCoord1f
;
1189 vfmt
->TexCoord1fv
= _save_TexCoord1fv
;
1190 vfmt
->TexCoord2f
= _save_TexCoord2f
;
1191 vfmt
->TexCoord2fv
= _save_TexCoord2fv
;
1192 vfmt
->TexCoord3f
= _save_TexCoord3f
;
1193 vfmt
->TexCoord3fv
= _save_TexCoord3fv
;
1194 vfmt
->TexCoord4f
= _save_TexCoord4f
;
1195 vfmt
->TexCoord4fv
= _save_TexCoord4fv
;
1196 vfmt
->Vertex2f
= _save_Vertex2f
;
1197 vfmt
->Vertex2fv
= _save_Vertex2fv
;
1198 vfmt
->Vertex3f
= _save_Vertex3f
;
1199 vfmt
->Vertex3fv
= _save_Vertex3fv
;
1200 vfmt
->Vertex4f
= _save_Vertex4f
;
1201 vfmt
->Vertex4fv
= _save_Vertex4fv
;
1202 vfmt
->VertexAttrib1fARB
= _save_VertexAttrib1fARB
;
1203 vfmt
->VertexAttrib1fvARB
= _save_VertexAttrib1fvARB
;
1204 vfmt
->VertexAttrib2fARB
= _save_VertexAttrib2fARB
;
1205 vfmt
->VertexAttrib2fvARB
= _save_VertexAttrib2fvARB
;
1206 vfmt
->VertexAttrib3fARB
= _save_VertexAttrib3fARB
;
1207 vfmt
->VertexAttrib3fvARB
= _save_VertexAttrib3fvARB
;
1208 vfmt
->VertexAttrib4fARB
= _save_VertexAttrib4fARB
;
1209 vfmt
->VertexAttrib4fvARB
= _save_VertexAttrib4fvARB
;
1211 vfmt
->VertexAttrib1fNV
= _save_VertexAttrib1fNV
;
1212 vfmt
->VertexAttrib1fvNV
= _save_VertexAttrib1fvNV
;
1213 vfmt
->VertexAttrib2fNV
= _save_VertexAttrib2fNV
;
1214 vfmt
->VertexAttrib2fvNV
= _save_VertexAttrib2fvNV
;
1215 vfmt
->VertexAttrib3fNV
= _save_VertexAttrib3fNV
;
1216 vfmt
->VertexAttrib3fvNV
= _save_VertexAttrib3fvNV
;
1217 vfmt
->VertexAttrib4fNV
= _save_VertexAttrib4fNV
;
1218 vfmt
->VertexAttrib4fvNV
= _save_VertexAttrib4fvNV
;
1220 /* integer-valued */
1221 vfmt
->VertexAttribI1i
= _save_VertexAttribI1i
;
1222 vfmt
->VertexAttribI2i
= _save_VertexAttribI2i
;
1223 vfmt
->VertexAttribI3i
= _save_VertexAttribI3i
;
1224 vfmt
->VertexAttribI4i
= _save_VertexAttribI4i
;
1225 vfmt
->VertexAttribI2iv
= _save_VertexAttribI2iv
;
1226 vfmt
->VertexAttribI3iv
= _save_VertexAttribI3iv
;
1227 vfmt
->VertexAttribI4iv
= _save_VertexAttribI4iv
;
1229 /* unsigned integer-valued */
1230 vfmt
->VertexAttribI1ui
= _save_VertexAttribI1ui
;
1231 vfmt
->VertexAttribI2ui
= _save_VertexAttribI2ui
;
1232 vfmt
->VertexAttribI3ui
= _save_VertexAttribI3ui
;
1233 vfmt
->VertexAttribI4ui
= _save_VertexAttribI4ui
;
1234 vfmt
->VertexAttribI2uiv
= _save_VertexAttribI2uiv
;
1235 vfmt
->VertexAttribI3uiv
= _save_VertexAttribI3uiv
;
1236 vfmt
->VertexAttribI4uiv
= _save_VertexAttribI4uiv
;
1238 vfmt
->VertexP2ui
= _save_VertexP2ui
;
1239 vfmt
->VertexP3ui
= _save_VertexP3ui
;
1240 vfmt
->VertexP4ui
= _save_VertexP4ui
;
1241 vfmt
->VertexP2uiv
= _save_VertexP2uiv
;
1242 vfmt
->VertexP3uiv
= _save_VertexP3uiv
;
1243 vfmt
->VertexP4uiv
= _save_VertexP4uiv
;
1245 vfmt
->TexCoordP1ui
= _save_TexCoordP1ui
;
1246 vfmt
->TexCoordP2ui
= _save_TexCoordP2ui
;
1247 vfmt
->TexCoordP3ui
= _save_TexCoordP3ui
;
1248 vfmt
->TexCoordP4ui
= _save_TexCoordP4ui
;
1249 vfmt
->TexCoordP1uiv
= _save_TexCoordP1uiv
;
1250 vfmt
->TexCoordP2uiv
= _save_TexCoordP2uiv
;
1251 vfmt
->TexCoordP3uiv
= _save_TexCoordP3uiv
;
1252 vfmt
->TexCoordP4uiv
= _save_TexCoordP4uiv
;
1254 vfmt
->MultiTexCoordP1ui
= _save_MultiTexCoordP1ui
;
1255 vfmt
->MultiTexCoordP2ui
= _save_MultiTexCoordP2ui
;
1256 vfmt
->MultiTexCoordP3ui
= _save_MultiTexCoordP3ui
;
1257 vfmt
->MultiTexCoordP4ui
= _save_MultiTexCoordP4ui
;
1258 vfmt
->MultiTexCoordP1uiv
= _save_MultiTexCoordP1uiv
;
1259 vfmt
->MultiTexCoordP2uiv
= _save_MultiTexCoordP2uiv
;
1260 vfmt
->MultiTexCoordP3uiv
= _save_MultiTexCoordP3uiv
;
1261 vfmt
->MultiTexCoordP4uiv
= _save_MultiTexCoordP4uiv
;
1263 vfmt
->NormalP3ui
= _save_NormalP3ui
;
1264 vfmt
->NormalP3uiv
= _save_NormalP3uiv
;
1266 vfmt
->ColorP3ui
= _save_ColorP3ui
;
1267 vfmt
->ColorP4ui
= _save_ColorP4ui
;
1268 vfmt
->ColorP3uiv
= _save_ColorP3uiv
;
1269 vfmt
->ColorP4uiv
= _save_ColorP4uiv
;
1271 vfmt
->SecondaryColorP3ui
= _save_SecondaryColorP3ui
;
1272 vfmt
->SecondaryColorP3uiv
= _save_SecondaryColorP3uiv
;
1274 vfmt
->VertexAttribP1ui
= _save_VertexAttribP1ui
;
1275 vfmt
->VertexAttribP2ui
= _save_VertexAttribP2ui
;
1276 vfmt
->VertexAttribP3ui
= _save_VertexAttribP3ui
;
1277 vfmt
->VertexAttribP4ui
= _save_VertexAttribP4ui
;
1279 vfmt
->VertexAttribP1uiv
= _save_VertexAttribP1uiv
;
1280 vfmt
->VertexAttribP2uiv
= _save_VertexAttribP2uiv
;
1281 vfmt
->VertexAttribP3uiv
= _save_VertexAttribP3uiv
;
1282 vfmt
->VertexAttribP4uiv
= _save_VertexAttribP4uiv
;
1284 /* This will all require us to fallback to saving the list as opcodes:
1286 _MESA_INIT_DLIST_VTXFMT(vfmt
, _save_
); /* inside begin/end */
1288 _MESA_INIT_EVAL_VTXFMT(vfmt
, _save_
);
1290 /* These calls all generate GL_INVALID_OPERATION since this vtxfmt is
1291 * only used when we're inside a glBegin/End pair.
1293 vfmt
->Begin
= _save_Begin
;
1294 vfmt
->Rectf
= _save_Rectf
;
1295 vfmt
->DrawArrays
= _save_DrawArrays
;
1296 vfmt
->DrawElements
= _save_DrawElements
;
1297 vfmt
->DrawRangeElements
= _save_DrawRangeElements
;
1298 vfmt
->DrawElementsBaseVertex
= _save_DrawElementsBaseVertex
;
1299 vfmt
->DrawRangeElementsBaseVertex
= _save_DrawRangeElementsBaseVertex
;
1300 vfmt
->MultiDrawElementsEXT
= _save_MultiDrawElements
;
1301 vfmt
->MultiDrawElementsBaseVertex
= _save_MultiDrawElementsBaseVertex
;
1306 vbo_save_SaveFlushVertices(struct gl_context
*ctx
)
1308 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1310 /* Noop when we are actually active:
1312 if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_INSIDE_UNKNOWN_PRIM
||
1313 ctx
->Driver
.CurrentSavePrimitive
<= GL_POLYGON
)
1316 if (save
->vert_count
|| save
->prim_count
)
1317 _save_compile_vertex_list(ctx
);
1319 _save_copy_to_current(ctx
);
1320 _save_reset_vertex(ctx
);
1321 _save_reset_counters(ctx
);
1322 ctx
->Driver
.SaveNeedFlush
= 0;
1327 vbo_save_NewList(struct gl_context
*ctx
, GLuint list
, GLenum mode
)
1329 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1334 if (!save
->prim_store
)
1335 save
->prim_store
= alloc_prim_store(ctx
);
1337 if (!save
->vertex_store
)
1338 save
->vertex_store
= alloc_vertex_store(ctx
);
1340 save
->buffer_ptr
= map_vertex_store(ctx
, save
->vertex_store
);
1342 _save_reset_vertex(ctx
);
1343 _save_reset_counters(ctx
);
1344 ctx
->Driver
.SaveNeedFlush
= 0;
1349 vbo_save_EndList(struct gl_context
*ctx
)
1351 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1353 /* EndList called inside a (saved) Begin/End pair?
1355 if (ctx
->Driver
.CurrentSavePrimitive
!= PRIM_OUTSIDE_BEGIN_END
) {
1357 if (save
->prim_count
> 0) {
1358 GLint i
= save
->prim_count
- 1;
1359 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
1360 save
->prim
[i
].end
= 0;
1361 save
->prim
[i
].count
= (save
->vert_count
- save
->prim
[i
].start
);
1364 /* Make sure this vertex list gets replayed by the "loopback"
1367 save
->dangling_attr_ref
= 1;
1368 vbo_save_SaveFlushVertices(ctx
);
1370 /* Swap out this vertex format while outside begin/end. Any color,
1371 * etc. received between here and the next begin will be compiled
1374 _mesa_install_save_vtxfmt(ctx
, &ctx
->ListState
.ListVtxfmt
);
1377 unmap_vertex_store(ctx
, save
->vertex_store
);
1379 assert(save
->vertex_size
== 0);
1384 vbo_save_BeginCallList(struct gl_context
*ctx
, struct gl_display_list
*dlist
)
1386 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1387 save
->replay_flags
|= dlist
->Flags
;
1392 vbo_save_EndCallList(struct gl_context
*ctx
)
1394 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1396 if (ctx
->ListState
.CallDepth
== 1) {
1397 /* This is correct: want to keep only the VBO_SAVE_FALLBACK
1398 * flag, if it is set:
1400 save
->replay_flags
&= VBO_SAVE_FALLBACK
;
1406 vbo_destroy_vertex_list(struct gl_context
*ctx
, void *data
)
1408 struct vbo_save_vertex_list
*node
= (struct vbo_save_vertex_list
*) data
;
1411 if (--node
->vertex_store
->refcount
== 0)
1412 free_vertex_store(ctx
, node
->vertex_store
);
1414 if (--node
->prim_store
->refcount
== 0)
1415 FREE(node
->prim_store
);
1417 if (node
->current_data
) {
1418 FREE(node
->current_data
);
1419 node
->current_data
= NULL
;
1425 vbo_print_vertex_list(struct gl_context
*ctx
, void *data
)
1427 struct vbo_save_vertex_list
*node
= (struct vbo_save_vertex_list
*) data
;
1431 printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
1432 node
->count
, node
->prim_count
, node
->vertex_size
);
1434 for (i
= 0; i
< node
->prim_count
; i
++) {
1435 struct _mesa_prim
*prim
= &node
->prim
[i
];
1436 _mesa_debug(NULL
, " prim %d: %s%s %d..%d %s %s\n",
1438 _mesa_lookup_prim_by_nr(prim
->mode
),
1439 prim
->weak
? " (weak)" : "",
1441 prim
->start
+ prim
->count
,
1442 (prim
->begin
) ? "BEGIN" : "(wrap)",
1443 (prim
->end
) ? "END" : "(wrap)");
1449 _save_current_init(struct gl_context
*ctx
)
1451 struct vbo_save_context
*save
= &vbo_context(ctx
)->save
;
1454 for (i
= VBO_ATTRIB_POS
; i
<= VBO_ATTRIB_GENERIC15
; i
++) {
1455 const GLuint j
= i
- VBO_ATTRIB_POS
;
1456 ASSERT(j
< VERT_ATTRIB_MAX
);
1457 save
->currentsz
[i
] = &ctx
->ListState
.ActiveAttribSize
[j
];
1458 save
->current
[i
] = ctx
->ListState
.CurrentAttrib
[j
];
1461 for (i
= VBO_ATTRIB_FIRST_MATERIAL
; i
<= VBO_ATTRIB_LAST_MATERIAL
; i
++) {
1462 const GLuint j
= i
- VBO_ATTRIB_FIRST_MATERIAL
;
1463 ASSERT(j
< MAT_ATTRIB_MAX
);
1464 save
->currentsz
[i
] = &ctx
->ListState
.ActiveMaterialSize
[j
];
1465 save
->current
[i
] = ctx
->ListState
.CurrentMaterial
[j
];
1471 * Initialize the display list compiler
1474 vbo_save_api_init(struct vbo_save_context
*save
)
1476 struct gl_context
*ctx
= save
->ctx
;
1479 save
->opcode_vertex_list
=
1480 _mesa_dlist_alloc_opcode(ctx
,
1481 sizeof(struct vbo_save_vertex_list
),
1482 vbo_save_playback_vertex_list
,
1483 vbo_destroy_vertex_list
,
1484 vbo_print_vertex_list
);
1486 ctx
->Driver
.NotifySaveBegin
= vbo_save_NotifyBegin
;
1488 _save_vtxfmt_init(ctx
);
1489 _save_current_init(ctx
);
1491 /* These will actually get set again when binding/drawing */
1492 for (i
= 0; i
< VBO_ATTRIB_MAX
; i
++)
1493 save
->inputs
[i
] = &save
->arrays
[i
];
1495 /* Hook our array functions into the outside-begin-end vtxfmt in
1498 ctx
->ListState
.ListVtxfmt
.Rectf
= _save_OBE_Rectf
;
1499 ctx
->ListState
.ListVtxfmt
.DrawArrays
= _save_OBE_DrawArrays
;
1500 ctx
->ListState
.ListVtxfmt
.DrawElements
= _save_OBE_DrawElements
;
1501 ctx
->ListState
.ListVtxfmt
.DrawRangeElements
= _save_OBE_DrawRangeElements
;
1502 ctx
->ListState
.ListVtxfmt
.MultiDrawElementsEXT
= _save_OBE_MultiDrawElements
;
1503 ctx
->ListState
.ListVtxfmt
.MultiDrawElementsBaseVertex
= _save_OBE_MultiDrawElementsBaseVertex
;
1504 _mesa_install_save_vtxfmt(ctx
, &ctx
->ListState
.ListVtxfmt
);
1508 #endif /* FEATURE_dlist */