1 /**************************************************************************
3 Copyright 2002 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>
40 #include "api_arrayelt.h"
44 #include "vbo_context.h"
46 static void reset_attrfv( struct vbo_exec_context
*exec
);
49 /* Close off the last primitive, execute the buffer, restart the
52 static void vbo_exec_wrap_buffers( struct vbo_exec_context
*exec
)
54 if (exec
->vtx
.prim_count
== 0) {
55 exec
->vtx
.copied
.nr
= 0;
56 exec
->vtx
.vert_count
= 0;
57 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
60 GLuint last_begin
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].begin
;
63 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
64 GLint i
= exec
->vtx
.prim_count
- 1;
66 exec
->vtx
.prim
[i
].count
= (exec
->vtx
.vert_count
-
67 exec
->vtx
.prim
[i
].start
);
70 last_count
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].count
;
72 /* Execute the buffer and save copied vertices.
74 if (exec
->vtx
.vert_count
)
75 vbo_exec_vtx_flush( exec
);
77 exec
->vtx
.prim_count
= 0;
78 exec
->vtx
.copied
.nr
= 0;
81 /* Emit a glBegin to start the new list.
83 assert(exec
->vtx
.prim_count
== 0);
85 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
86 exec
->vtx
.prim
[0].mode
= exec
->ctx
->Driver
.CurrentExecPrimitive
;
87 exec
->vtx
.prim
[0].start
= 0;
88 exec
->vtx
.prim
[0].count
= 0;
89 exec
->vtx
.prim_count
++;
91 if (exec
->vtx
.copied
.nr
== last_count
)
92 exec
->vtx
.prim
[0].begin
= last_begin
;
98 /* Deal with buffer wrapping where provoked by the vertex buffer
99 * filling up, as opposed to upgrade_vertex().
101 void vbo_exec_vtx_wrap( struct vbo_exec_context
*exec
)
103 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
106 /* Run pipeline on current vertices, copy wrapped vertices
107 * to exec->vtx.copied.
109 vbo_exec_wrap_buffers( exec
);
111 /* Copy stored stored vertices to start of new list.
113 assert(exec
->vtx
.max_vert
- exec
->vtx
.vert_count
> exec
->vtx
.copied
.nr
);
115 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
116 _mesa_memcpy( exec
->vtx
.vbptr
, data
,
117 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
118 exec
->vtx
.vbptr
+= exec
->vtx
.vertex_size
;
119 data
+= exec
->vtx
.vertex_size
;
120 exec
->vtx
.vert_count
++;
123 exec
->vtx
.copied
.nr
= 0;
128 * Copy the active vertex's values to the ctx->Current fields.
130 static void vbo_exec_copy_to_current( struct vbo_exec_context
*exec
)
132 GLcontext
*ctx
= exec
->ctx
;
133 struct vbo_context
*vbo
= vbo_context(ctx
);
136 for (i
= VBO_ATTRIB_POS
+1 ; i
< VBO_ATTRIB_MAX
; i
++) {
137 if (exec
->vtx
.attrsz
[i
]) {
138 GLfloat
*current
= (GLfloat
*)vbo
->currval
[i
].Ptr
;
140 /* Note: the exec->vtx.current[i] pointers point into the
141 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
143 COPY_CLEAN_4V(current
,
145 exec
->vtx
.attrptr
[i
]);
148 /* Given that we explicitly state size here, there is no need
149 * for the COPY_CLEAN above, could just copy 16 bytes and be
150 * done. The only problem is when Mesa accesses ctx->Current
153 vbo
->currval
[i
].Size
= exec
->vtx
.attrsz
[i
];
155 /* This triggers rather too much recalculation of Mesa state
156 * that doesn't get used (eg light positions).
158 if (i
>= VBO_ATTRIB_MAT_FRONT_AMBIENT
&&
159 i
<= VBO_ATTRIB_MAT_BACK_INDEXES
)
160 ctx
->NewState
|= _NEW_LIGHT
;
164 /* Colormaterial -- this kindof sucks.
166 if (ctx
->Light
.ColorMaterialEnabled
&&
167 exec
->vtx
.attrsz
[VBO_ATTRIB_COLOR0
]) {
168 _mesa_update_color_material(ctx
,
169 ctx
->Current
.Attrib
[VBO_ATTRIB_COLOR0
]);
172 ctx
->Driver
.NeedFlush
&= ~FLUSH_UPDATE_CURRENT
;
176 static void vbo_exec_copy_from_current( struct vbo_exec_context
*exec
)
178 GLcontext
*ctx
= exec
->ctx
;
179 struct vbo_context
*vbo
= vbo_context(ctx
);
182 for (i
= VBO_ATTRIB_POS
+1 ; i
< VBO_ATTRIB_MAX
; i
++) {
183 const GLfloat
*current
= (GLfloat
*)vbo
->currval
[i
].Ptr
;
184 switch (exec
->vtx
.attrsz
[i
]) {
185 case 4: exec
->vtx
.attrptr
[i
][3] = current
[3];
186 case 3: exec
->vtx
.attrptr
[i
][2] = current
[2];
187 case 2: exec
->vtx
.attrptr
[i
][1] = current
[1];
188 case 1: exec
->vtx
.attrptr
[i
][0] = current
[0];
193 ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
197 /* Flush existing data, set new attrib size, replay copied vertices.
199 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context
*exec
,
203 GLcontext
*ctx
= exec
->ctx
;
204 struct vbo_context
*vbo
= vbo_context(ctx
);
205 GLint lastcount
= exec
->vtx
.vert_count
;
210 /* Run pipeline on current vertices, copy wrapped vertices
211 * to exec->vtx.copied.
213 vbo_exec_wrap_buffers( exec
);
216 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
217 * when the attribute already exists in the vertex and is having
218 * its size increased.
220 vbo_exec_copy_to_current( exec
);
223 /* Heuristic: Attempt to isolate attributes received outside
224 * begin/end so that they don't bloat the vertices.
226 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
&&
227 exec
->vtx
.attrsz
[attr
] == 0 &&
229 exec
->vtx
.vertex_size
) {
230 reset_attrfv( exec
);
235 oldsz
= exec
->vtx
.attrsz
[attr
];
236 exec
->vtx
.attrsz
[attr
] = newsz
;
238 exec
->vtx
.vertex_size
+= newsz
- oldsz
;
239 exec
->vtx
.max_vert
= VBO_VERT_BUFFER_SIZE
/ exec
->vtx
.vertex_size
;
240 exec
->vtx
.vert_count
= 0;
241 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
244 /* Recalculate all the attrptr[] values
246 for (i
= 0, tmp
= exec
->vtx
.vertex
; i
< VBO_ATTRIB_MAX
; i
++) {
247 if (exec
->vtx
.attrsz
[i
]) {
248 exec
->vtx
.attrptr
[i
] = tmp
;
249 tmp
+= exec
->vtx
.attrsz
[i
];
252 exec
->vtx
.attrptr
[i
] = NULL
; /* will not be dereferenced */
255 /* Copy from current to repopulate the vertex with correct values.
257 vbo_exec_copy_from_current( exec
);
259 /* Replay stored vertices to translate them
260 * to new format here.
262 * -- No need to replay - just copy piecewise
264 if (exec
->vtx
.copied
.nr
)
266 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
267 GLfloat
*dest
= exec
->vtx
.vbptr
;
270 assert(exec
->vtx
.vbptr
== (GLfloat
*)exec
->vtx
.buffer_map
);
272 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
273 for (j
= 0 ; j
< VBO_ATTRIB_MAX
; j
++) {
274 if (exec
->vtx
.attrsz
[j
]) {
277 COPY_CLEAN_4V( dest
, oldsz
, data
);
281 const GLfloat
*current
= (const GLfloat
*)vbo
->currval
[j
].Ptr
;
282 COPY_SZ_4V( dest
, newsz
, current
);
287 GLuint sz
= exec
->vtx
.attrsz
[j
];
288 COPY_SZ_4V( dest
, sz
, data
);
296 exec
->vtx
.vbptr
= dest
;
297 exec
->vtx
.vert_count
+= exec
->vtx
.copied
.nr
;
298 exec
->vtx
.copied
.nr
= 0;
303 static void vbo_exec_fixup_vertex( GLcontext
*ctx
,
304 GLuint attr
, GLuint sz
)
306 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
309 if (sz
> exec
->vtx
.attrsz
[attr
]) {
310 /* New size is larger. Need to flush existing vertices and get
311 * an enlarged vertex format.
313 vbo_exec_wrap_upgrade_vertex( exec
, attr
, sz
);
315 else if (sz
< exec
->vtx
.active_sz
[attr
]) {
316 static const GLfloat id
[4] = { 0, 0, 0, 1 };
318 /* New size is smaller - just need to fill in some
319 * zeros. Don't need to flush or wrap.
321 for (i
= sz
; i
<= exec
->vtx
.attrsz
[attr
] ; i
++)
322 exec
->vtx
.attrptr
[attr
][i
-1] = id
[i
-1];
325 exec
->vtx
.active_sz
[attr
] = sz
;
327 /* Does setting NeedFlush belong here? Necessitates resetting
328 * vtxfmt on each flush (otherwise flags won't get reset
332 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
334 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
342 #define ATTR( A, N, V0, V1, V2, V3 ) \
344 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
346 if (exec->vtx.active_sz[A] != N) \
347 vbo_exec_fixup_vertex(ctx, A, N); \
350 GLfloat *dest = exec->vtx.attrptr[A]; \
351 if (N>0) dest[0] = V0; \
352 if (N>1) dest[1] = V1; \
353 if (N>2) dest[2] = V2; \
354 if (N>3) dest[3] = V3; \
360 for (i = 0; i < exec->vtx.vertex_size; i++) \
361 exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \
363 exec->vtx.vbptr += exec->vtx.vertex_size; \
364 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
366 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
367 vbo_exec_vtx_wrap( exec ); \
372 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
373 #define TAG(x) vbo_##x
375 #include "vbo_attrib_tmp.h"
383 static void GLAPIENTRY
vbo_exec_EvalCoord1f( GLfloat u
)
385 GET_CURRENT_CONTEXT( ctx
);
386 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
390 if (exec
->eval
.recalculate_maps
)
391 vbo_exec_eval_update( exec
);
393 for (i
= 0; i
<= VBO_ATTRIB_TEX7
; i
++) {
394 if (exec
->eval
.map1
[i
].map
)
395 if (exec
->vtx
.active_sz
[i
] != exec
->eval
.map1
[i
].sz
)
396 vbo_exec_fixup_vertex( ctx
, i
, exec
->eval
.map1
[i
].sz
);
401 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
402 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
404 vbo_exec_do_EvalCoord1f( exec
, u
);
406 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
407 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
410 static void GLAPIENTRY
vbo_exec_EvalCoord2f( GLfloat u
, GLfloat v
)
412 GET_CURRENT_CONTEXT( ctx
);
413 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
417 if (exec
->eval
.recalculate_maps
)
418 vbo_exec_eval_update( exec
);
420 for (i
= 0; i
<= VBO_ATTRIB_TEX7
; i
++) {
421 if (exec
->eval
.map2
[i
].map
)
422 if (exec
->vtx
.active_sz
[i
] != exec
->eval
.map2
[i
].sz
)
423 vbo_exec_fixup_vertex( ctx
, i
, exec
->eval
.map2
[i
].sz
);
426 if (ctx
->Eval
.AutoNormal
)
427 if (exec
->vtx
.active_sz
[VBO_ATTRIB_NORMAL
] != 3)
428 vbo_exec_fixup_vertex( ctx
, VBO_ATTRIB_NORMAL
, 3 );
431 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
432 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
434 vbo_exec_do_EvalCoord2f( exec
, u
, v
);
436 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
437 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
440 static void GLAPIENTRY
vbo_exec_EvalCoord1fv( const GLfloat
*u
)
442 vbo_exec_EvalCoord1f( u
[0] );
445 static void GLAPIENTRY
vbo_exec_EvalCoord2fv( const GLfloat
*u
)
447 vbo_exec_EvalCoord2f( u
[0], u
[1] );
450 static void GLAPIENTRY
vbo_exec_EvalPoint1( GLint i
)
452 GET_CURRENT_CONTEXT( ctx
);
453 GLfloat du
= ((ctx
->Eval
.MapGrid1u2
- ctx
->Eval
.MapGrid1u1
) /
454 (GLfloat
) ctx
->Eval
.MapGrid1un
);
455 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid1u1
;
457 vbo_exec_EvalCoord1f( u
);
461 static void GLAPIENTRY
vbo_exec_EvalPoint2( GLint i
, GLint j
)
463 GET_CURRENT_CONTEXT( ctx
);
464 GLfloat du
= ((ctx
->Eval
.MapGrid2u2
- ctx
->Eval
.MapGrid2u1
) /
465 (GLfloat
) ctx
->Eval
.MapGrid2un
);
466 GLfloat dv
= ((ctx
->Eval
.MapGrid2v2
- ctx
->Eval
.MapGrid2v1
) /
467 (GLfloat
) ctx
->Eval
.MapGrid2vn
);
468 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid2u1
;
469 GLfloat v
= j
* dv
+ ctx
->Eval
.MapGrid2v1
;
471 vbo_exec_EvalCoord2f( u
, v
);
475 /* Build a list of primitives on the fly. Keep
476 * ctx->Driver.CurrentExecPrimitive uptodate as well.
478 static void GLAPIENTRY
vbo_exec_Begin( GLenum mode
)
480 GET_CURRENT_CONTEXT( ctx
);
482 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
483 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
487 _mesa_update_state( ctx
);
489 /* XXX also need to check if shader enabled, but invalid */
490 if ((ctx
->VertexProgram
.Enabled
&& !ctx
->VertexProgram
._Enabled
) ||
491 (ctx
->FragmentProgram
.Enabled
&& !ctx
->FragmentProgram
._Enabled
)) {
492 _mesa_error(ctx
, GL_INVALID_OPERATION
,
493 "glBegin (invalid vertex/fragment program)");
497 CALL_Begin(ctx
->Exec
, (mode
));
501 /* Heuristic: attempt to isolate attributes occuring outside
504 if (exec
->vtx
.vertex_size
&& !exec
->vtx
.attrsz
[0])
505 vbo_exec_FlushVertices( ctx
, ~0 );
507 i
= exec
->vtx
.prim_count
++;
508 exec
->vtx
.prim
[i
].mode
= mode
;
509 exec
->vtx
.prim
[i
].begin
= 1;
510 exec
->vtx
.prim
[i
].end
= 0;
511 exec
->vtx
.prim
[i
].indexed
= 0;
512 exec
->vtx
.prim
[i
].weak
= 0;
513 exec
->vtx
.prim
[i
].pad
= 0;
514 exec
->vtx
.prim
[i
].start
= exec
->vtx
.vert_count
;
515 exec
->vtx
.prim
[i
].count
= 0;
517 ctx
->Driver
.CurrentExecPrimitive
= mode
;
520 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin" );
524 static void GLAPIENTRY
vbo_exec_End( void )
526 GET_CURRENT_CONTEXT( ctx
);
528 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
529 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
530 int idx
= exec
->vtx
.vert_count
;
531 int i
= exec
->vtx
.prim_count
- 1;
533 exec
->vtx
.prim
[i
].end
= 1;
534 exec
->vtx
.prim
[i
].count
= idx
- exec
->vtx
.prim
[i
].start
;
536 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
538 if (exec
->vtx
.prim_count
== VBO_MAX_PRIM
)
539 vbo_exec_vtx_flush( exec
);
542 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glEnd" );
546 static void vbo_exec_vtxfmt_init( struct vbo_exec_context
*exec
)
548 GLvertexformat
*vfmt
= &exec
->vtxfmt
;
550 vfmt
->ArrayElement
= _ae_loopback_array_elt
; /* generic helper */
551 vfmt
->Begin
= vbo_exec_Begin
;
552 vfmt
->CallList
= _mesa_CallList
;
553 vfmt
->CallLists
= _mesa_CallLists
;
554 vfmt
->End
= vbo_exec_End
;
555 vfmt
->EvalCoord1f
= vbo_exec_EvalCoord1f
;
556 vfmt
->EvalCoord1fv
= vbo_exec_EvalCoord1fv
;
557 vfmt
->EvalCoord2f
= vbo_exec_EvalCoord2f
;
558 vfmt
->EvalCoord2fv
= vbo_exec_EvalCoord2fv
;
559 vfmt
->EvalPoint1
= vbo_exec_EvalPoint1
;
560 vfmt
->EvalPoint2
= vbo_exec_EvalPoint2
;
562 vfmt
->Rectf
= _mesa_noop_Rectf
;
563 vfmt
->EvalMesh1
= _mesa_noop_EvalMesh1
;
564 vfmt
->EvalMesh2
= _mesa_noop_EvalMesh2
;
567 /* from attrib_tmp.h:
569 vfmt
->Color3f
= vbo_Color3f
;
570 vfmt
->Color3fv
= vbo_Color3fv
;
571 vfmt
->Color4f
= vbo_Color4f
;
572 vfmt
->Color4fv
= vbo_Color4fv
;
573 vfmt
->FogCoordfEXT
= vbo_FogCoordfEXT
;
574 vfmt
->FogCoordfvEXT
= vbo_FogCoordfvEXT
;
575 vfmt
->MultiTexCoord1fARB
= vbo_MultiTexCoord1f
;
576 vfmt
->MultiTexCoord1fvARB
= vbo_MultiTexCoord1fv
;
577 vfmt
->MultiTexCoord2fARB
= vbo_MultiTexCoord2f
;
578 vfmt
->MultiTexCoord2fvARB
= vbo_MultiTexCoord2fv
;
579 vfmt
->MultiTexCoord3fARB
= vbo_MultiTexCoord3f
;
580 vfmt
->MultiTexCoord3fvARB
= vbo_MultiTexCoord3fv
;
581 vfmt
->MultiTexCoord4fARB
= vbo_MultiTexCoord4f
;
582 vfmt
->MultiTexCoord4fvARB
= vbo_MultiTexCoord4fv
;
583 vfmt
->Normal3f
= vbo_Normal3f
;
584 vfmt
->Normal3fv
= vbo_Normal3fv
;
585 vfmt
->SecondaryColor3fEXT
= vbo_SecondaryColor3fEXT
;
586 vfmt
->SecondaryColor3fvEXT
= vbo_SecondaryColor3fvEXT
;
587 vfmt
->TexCoord1f
= vbo_TexCoord1f
;
588 vfmt
->TexCoord1fv
= vbo_TexCoord1fv
;
589 vfmt
->TexCoord2f
= vbo_TexCoord2f
;
590 vfmt
->TexCoord2fv
= vbo_TexCoord2fv
;
591 vfmt
->TexCoord3f
= vbo_TexCoord3f
;
592 vfmt
->TexCoord3fv
= vbo_TexCoord3fv
;
593 vfmt
->TexCoord4f
= vbo_TexCoord4f
;
594 vfmt
->TexCoord4fv
= vbo_TexCoord4fv
;
595 vfmt
->Vertex2f
= vbo_Vertex2f
;
596 vfmt
->Vertex2fv
= vbo_Vertex2fv
;
597 vfmt
->Vertex3f
= vbo_Vertex3f
;
598 vfmt
->Vertex3fv
= vbo_Vertex3fv
;
599 vfmt
->Vertex4f
= vbo_Vertex4f
;
600 vfmt
->Vertex4fv
= vbo_Vertex4fv
;
602 vfmt
->VertexAttrib1fARB
= vbo_VertexAttrib1fARB
;
603 vfmt
->VertexAttrib1fvARB
= vbo_VertexAttrib1fvARB
;
604 vfmt
->VertexAttrib2fARB
= vbo_VertexAttrib2fARB
;
605 vfmt
->VertexAttrib2fvARB
= vbo_VertexAttrib2fvARB
;
606 vfmt
->VertexAttrib3fARB
= vbo_VertexAttrib3fARB
;
607 vfmt
->VertexAttrib3fvARB
= vbo_VertexAttrib3fvARB
;
608 vfmt
->VertexAttrib4fARB
= vbo_VertexAttrib4fARB
;
609 vfmt
->VertexAttrib4fvARB
= vbo_VertexAttrib4fvARB
;
611 vfmt
->VertexAttrib1fNV
= vbo_VertexAttrib1fNV
;
612 vfmt
->VertexAttrib1fvNV
= vbo_VertexAttrib1fvNV
;
613 vfmt
->VertexAttrib2fNV
= vbo_VertexAttrib2fNV
;
614 vfmt
->VertexAttrib2fvNV
= vbo_VertexAttrib2fvNV
;
615 vfmt
->VertexAttrib3fNV
= vbo_VertexAttrib3fNV
;
616 vfmt
->VertexAttrib3fvNV
= vbo_VertexAttrib3fvNV
;
617 vfmt
->VertexAttrib4fNV
= vbo_VertexAttrib4fNV
;
618 vfmt
->VertexAttrib4fvNV
= vbo_VertexAttrib4fvNV
;
620 vfmt
->Materialfv
= vbo_Materialfv
;
622 vfmt
->EdgeFlag
= vbo_EdgeFlag
;
623 vfmt
->Indexf
= vbo_Indexf
;
624 vfmt
->Indexfv
= vbo_Indexfv
;
629 void vbo_exec_vtx_init( struct vbo_exec_context
*exec
)
631 GLcontext
*ctx
= exec
->ctx
;
632 struct vbo_context
*vbo
= vbo_context(ctx
);
635 /* Allocate a buffer object. Will just reuse this object
638 exec
->vtx
.bufferobj
= ctx
->Array
.NullBufferObj
;
639 exec
->vtx
.buffer_map
= ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE
* sizeof(GLfloat
), 64);
641 vbo_exec_vtxfmt_init( exec
);
643 /* Hook our functions into the dispatch table.
645 _mesa_install_exec_vtxfmt( exec
->ctx
, &exec
->vtxfmt
);
647 for (i
= 0 ; i
< VBO_ATTRIB_MAX
; i
++) {
648 exec
->vtx
.attrsz
[i
] = 0;
649 exec
->vtx
.active_sz
[i
] = 0;
650 exec
->vtx
.inputs
[i
] = &exec
->vtx
.arrays
[i
];
654 struct gl_client_array
*arrays
= exec
->vtx
.arrays
;
655 memcpy(arrays
, vbo
->legacy_currval
, 16 * sizeof(arrays
[0]));
656 memcpy(arrays
+ 16, vbo
->generic_currval
, 16 * sizeof(arrays
[0]));
659 exec
->vtx
.vertex_size
= 0;
663 void vbo_exec_vtx_destroy( struct vbo_exec_context
*exec
)
665 if (exec
->vtx
.buffer_map
) {
666 ALIGN_FREE(exec
->vtx
.buffer_map
);
667 exec
->vtx
.buffer_map
= NULL
;
672 void vbo_exec_FlushVertices( GLcontext
*ctx
, GLuint flags
)
674 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
676 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
)
679 if (exec
->vtx
.vert_count
) {
680 vbo_exec_vtx_flush( exec
);
683 if (exec
->vtx
.vertex_size
) {
684 vbo_exec_copy_to_current( exec
);
685 reset_attrfv( exec
);
688 exec
->ctx
->Driver
.NeedFlush
= 0;
692 static void reset_attrfv( struct vbo_exec_context
*exec
)
696 for (i
= 0 ; i
< VBO_ATTRIB_MAX
; i
++) {
697 exec
->vtx
.attrsz
[i
] = 0;
698 exec
->vtx
.active_sz
[i
] = 0;
701 exec
->vtx
.vertex_size
= 0;