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>
33 #include "main/glheader.h"
34 #include "main/context.h"
35 #include "main/macros.h"
36 #include "main/vtxfmt.h"
37 #include "main/dlist.h"
38 #include "main/state.h"
39 #include "main/light.h"
40 #include "main/api_arrayelt.h"
41 #include "main/api_noop.h"
42 #include "glapi/dispatch.h"
44 #include "vbo_context.h"
51 static void reset_attrfv( struct vbo_exec_context
*exec
);
54 /* Close off the last primitive, execute the buffer, restart the
57 static void vbo_exec_wrap_buffers( struct vbo_exec_context
*exec
)
59 if (exec
->vtx
.prim_count
== 0) {
60 exec
->vtx
.copied
.nr
= 0;
61 exec
->vtx
.vert_count
= 0;
62 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
65 GLuint last_begin
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].begin
;
68 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
69 GLint i
= exec
->vtx
.prim_count
- 1;
71 exec
->vtx
.prim
[i
].count
= (exec
->vtx
.vert_count
-
72 exec
->vtx
.prim
[i
].start
);
75 last_count
= exec
->vtx
.prim
[exec
->vtx
.prim_count
-1].count
;
77 /* Execute the buffer and save copied vertices.
79 if (exec
->vtx
.vert_count
)
80 vbo_exec_vtx_flush( exec
);
82 exec
->vtx
.prim_count
= 0;
83 exec
->vtx
.copied
.nr
= 0;
86 /* Emit a glBegin to start the new list.
88 assert(exec
->vtx
.prim_count
== 0);
90 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
91 exec
->vtx
.prim
[0].mode
= exec
->ctx
->Driver
.CurrentExecPrimitive
;
92 exec
->vtx
.prim
[0].start
= 0;
93 exec
->vtx
.prim
[0].count
= 0;
94 exec
->vtx
.prim_count
++;
96 if (exec
->vtx
.copied
.nr
== last_count
)
97 exec
->vtx
.prim
[0].begin
= last_begin
;
103 /* Deal with buffer wrapping where provoked by the vertex buffer
104 * filling up, as opposed to upgrade_vertex().
106 void vbo_exec_vtx_wrap( struct vbo_exec_context
*exec
)
108 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
111 /* Run pipeline on current vertices, copy wrapped vertices
112 * to exec->vtx.copied.
114 vbo_exec_wrap_buffers( exec
);
116 /* Copy stored stored vertices to start of new list.
118 assert(exec
->vtx
.max_vert
- exec
->vtx
.vert_count
> exec
->vtx
.copied
.nr
);
120 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
121 _mesa_memcpy( exec
->vtx
.vbptr
, data
,
122 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
123 exec
->vtx
.vbptr
+= exec
->vtx
.vertex_size
;
124 data
+= exec
->vtx
.vertex_size
;
125 exec
->vtx
.vert_count
++;
128 exec
->vtx
.copied
.nr
= 0;
133 * Copy the active vertex's values to the ctx->Current fields.
135 static void vbo_exec_copy_to_current( struct vbo_exec_context
*exec
)
137 GLcontext
*ctx
= exec
->ctx
;
138 struct vbo_context
*vbo
= vbo_context(ctx
);
141 for (i
= VBO_ATTRIB_POS
+1 ; i
< VBO_ATTRIB_MAX
; i
++) {
142 if (exec
->vtx
.attrsz
[i
]) {
143 GLfloat
*current
= (GLfloat
*)vbo
->currval
[i
].Ptr
;
145 /* Note: the exec->vtx.current[i] pointers point into the
146 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
148 COPY_CLEAN_4V(current
,
150 exec
->vtx
.attrptr
[i
]);
153 /* Given that we explicitly state size here, there is no need
154 * for the COPY_CLEAN above, could just copy 16 bytes and be
155 * done. The only problem is when Mesa accesses ctx->Current
158 vbo
->currval
[i
].Size
= exec
->vtx
.attrsz
[i
];
160 /* This triggers rather too much recalculation of Mesa state
161 * that doesn't get used (eg light positions).
163 if (i
>= VBO_ATTRIB_MAT_FRONT_AMBIENT
&&
164 i
<= VBO_ATTRIB_MAT_BACK_INDEXES
)
165 ctx
->NewState
|= _NEW_LIGHT
;
169 /* Colormaterial -- this kindof sucks.
171 if (ctx
->Light
.ColorMaterialEnabled
&&
172 exec
->vtx
.attrsz
[VBO_ATTRIB_COLOR0
]) {
173 _mesa_update_color_material(ctx
,
174 ctx
->Current
.Attrib
[VBO_ATTRIB_COLOR0
]);
177 ctx
->Driver
.NeedFlush
&= ~FLUSH_UPDATE_CURRENT
;
181 static void vbo_exec_copy_from_current( struct vbo_exec_context
*exec
)
183 GLcontext
*ctx
= exec
->ctx
;
184 struct vbo_context
*vbo
= vbo_context(ctx
);
187 for (i
= VBO_ATTRIB_POS
+1 ; i
< VBO_ATTRIB_MAX
; i
++) {
188 const GLfloat
*current
= (GLfloat
*)vbo
->currval
[i
].Ptr
;
189 switch (exec
->vtx
.attrsz
[i
]) {
190 case 4: exec
->vtx
.attrptr
[i
][3] = current
[3];
191 case 3: exec
->vtx
.attrptr
[i
][2] = current
[2];
192 case 2: exec
->vtx
.attrptr
[i
][1] = current
[1];
193 case 1: exec
->vtx
.attrptr
[i
][0] = current
[0];
198 ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
202 /* Flush existing data, set new attrib size, replay copied vertices.
204 static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context
*exec
,
208 GLcontext
*ctx
= exec
->ctx
;
209 struct vbo_context
*vbo
= vbo_context(ctx
);
210 GLint lastcount
= exec
->vtx
.vert_count
;
215 /* Run pipeline on current vertices, copy wrapped vertices
216 * to exec->vtx.copied.
218 vbo_exec_wrap_buffers( exec
);
221 /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
222 * when the attribute already exists in the vertex and is having
223 * its size increased.
225 vbo_exec_copy_to_current( exec
);
228 /* Heuristic: Attempt to isolate attributes received outside
229 * begin/end so that they don't bloat the vertices.
231 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
&&
232 exec
->vtx
.attrsz
[attr
] == 0 &&
234 exec
->vtx
.vertex_size
) {
235 reset_attrfv( exec
);
240 oldsz
= exec
->vtx
.attrsz
[attr
];
241 exec
->vtx
.attrsz
[attr
] = newsz
;
243 exec
->vtx
.vertex_size
+= newsz
- oldsz
;
244 exec
->vtx
.max_vert
= VBO_VERT_BUFFER_SIZE
/ exec
->vtx
.vertex_size
;
245 exec
->vtx
.vert_count
= 0;
246 exec
->vtx
.vbptr
= (GLfloat
*)exec
->vtx
.buffer_map
;
249 /* Recalculate all the attrptr[] values
251 for (i
= 0, tmp
= exec
->vtx
.vertex
; i
< VBO_ATTRIB_MAX
; i
++) {
252 if (exec
->vtx
.attrsz
[i
]) {
253 exec
->vtx
.attrptr
[i
] = tmp
;
254 tmp
+= exec
->vtx
.attrsz
[i
];
257 exec
->vtx
.attrptr
[i
] = NULL
; /* will not be dereferenced */
260 /* Copy from current to repopulate the vertex with correct values.
262 vbo_exec_copy_from_current( exec
);
264 /* Replay stored vertices to translate them
265 * to new format here.
267 * -- No need to replay - just copy piecewise
269 if (exec
->vtx
.copied
.nr
)
271 GLfloat
*data
= exec
->vtx
.copied
.buffer
;
272 GLfloat
*dest
= exec
->vtx
.vbptr
;
275 assert(exec
->vtx
.vbptr
== (GLfloat
*)exec
->vtx
.buffer_map
);
277 for (i
= 0 ; i
< exec
->vtx
.copied
.nr
; i
++) {
278 for (j
= 0 ; j
< VBO_ATTRIB_MAX
; j
++) {
279 if (exec
->vtx
.attrsz
[j
]) {
282 COPY_CLEAN_4V( dest
, oldsz
, data
);
286 const GLfloat
*current
= (const GLfloat
*)vbo
->currval
[j
].Ptr
;
287 COPY_SZ_4V( dest
, newsz
, current
);
292 GLuint sz
= exec
->vtx
.attrsz
[j
];
293 COPY_SZ_4V( dest
, sz
, data
);
301 exec
->vtx
.vbptr
= dest
;
302 exec
->vtx
.vert_count
+= exec
->vtx
.copied
.nr
;
303 exec
->vtx
.copied
.nr
= 0;
308 static void vbo_exec_fixup_vertex( GLcontext
*ctx
,
309 GLuint attr
, GLuint sz
)
311 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
314 if (sz
> exec
->vtx
.attrsz
[attr
]) {
315 /* New size is larger. Need to flush existing vertices and get
316 * an enlarged vertex format.
318 vbo_exec_wrap_upgrade_vertex( exec
, attr
, sz
);
320 else if (sz
< exec
->vtx
.active_sz
[attr
]) {
321 static const GLfloat id
[4] = { 0, 0, 0, 1 };
323 /* New size is smaller - just need to fill in some
324 * zeros. Don't need to flush or wrap.
326 for (i
= sz
; i
<= exec
->vtx
.attrsz
[attr
] ; i
++)
327 exec
->vtx
.attrptr
[attr
][i
-1] = id
[i
-1];
330 exec
->vtx
.active_sz
[attr
] = sz
;
332 /* Does setting NeedFlush belong here? Necessitates resetting
333 * vtxfmt on each flush (otherwise flags won't get reset
337 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
339 exec
->ctx
->Driver
.NeedFlush
|= FLUSH_UPDATE_CURRENT
;
347 #define ATTR( A, N, V0, V1, V2, V3 ) \
349 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
351 if (exec->vtx.active_sz[A] != N) \
352 vbo_exec_fixup_vertex(ctx, A, N); \
355 GLfloat *dest = exec->vtx.attrptr[A]; \
356 if (N>0) dest[0] = V0; \
357 if (N>1) dest[1] = V1; \
358 if (N>2) dest[2] = V2; \
359 if (N>3) dest[3] = V3; \
365 for (i = 0; i < exec->vtx.vertex_size; i++) \
366 exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \
368 exec->vtx.vbptr += exec->vtx.vertex_size; \
369 exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
371 if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
372 vbo_exec_vtx_wrap( exec ); \
377 #define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
378 #define TAG(x) vbo_##x
380 #include "vbo_attrib_tmp.h"
388 static void GLAPIENTRY
vbo_exec_EvalCoord1f( GLfloat u
)
390 GET_CURRENT_CONTEXT( ctx
);
391 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
395 if (exec
->eval
.recalculate_maps
)
396 vbo_exec_eval_update( exec
);
398 for (i
= 0; i
<= VBO_ATTRIB_TEX7
; i
++) {
399 if (exec
->eval
.map1
[i
].map
)
400 if (exec
->vtx
.active_sz
[i
] != exec
->eval
.map1
[i
].sz
)
401 vbo_exec_fixup_vertex( ctx
, i
, exec
->eval
.map1
[i
].sz
);
406 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
407 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
409 vbo_exec_do_EvalCoord1f( exec
, u
);
411 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
412 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
415 static void GLAPIENTRY
vbo_exec_EvalCoord2f( GLfloat u
, GLfloat v
)
417 GET_CURRENT_CONTEXT( ctx
);
418 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
422 if (exec
->eval
.recalculate_maps
)
423 vbo_exec_eval_update( exec
);
425 for (i
= 0; i
<= VBO_ATTRIB_TEX7
; i
++) {
426 if (exec
->eval
.map2
[i
].map
)
427 if (exec
->vtx
.active_sz
[i
] != exec
->eval
.map2
[i
].sz
)
428 vbo_exec_fixup_vertex( ctx
, i
, exec
->eval
.map2
[i
].sz
);
431 if (ctx
->Eval
.AutoNormal
)
432 if (exec
->vtx
.active_sz
[VBO_ATTRIB_NORMAL
] != 3)
433 vbo_exec_fixup_vertex( ctx
, VBO_ATTRIB_NORMAL
, 3 );
436 _mesa_memcpy( exec
->vtx
.copied
.buffer
, exec
->vtx
.vertex
,
437 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
439 vbo_exec_do_EvalCoord2f( exec
, u
, v
);
441 _mesa_memcpy( exec
->vtx
.vertex
, exec
->vtx
.copied
.buffer
,
442 exec
->vtx
.vertex_size
* sizeof(GLfloat
));
445 static void GLAPIENTRY
vbo_exec_EvalCoord1fv( const GLfloat
*u
)
447 vbo_exec_EvalCoord1f( u
[0] );
450 static void GLAPIENTRY
vbo_exec_EvalCoord2fv( const GLfloat
*u
)
452 vbo_exec_EvalCoord2f( u
[0], u
[1] );
455 static void GLAPIENTRY
vbo_exec_EvalPoint1( GLint i
)
457 GET_CURRENT_CONTEXT( ctx
);
458 GLfloat du
= ((ctx
->Eval
.MapGrid1u2
- ctx
->Eval
.MapGrid1u1
) /
459 (GLfloat
) ctx
->Eval
.MapGrid1un
);
460 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid1u1
;
462 vbo_exec_EvalCoord1f( u
);
466 static void GLAPIENTRY
vbo_exec_EvalPoint2( GLint i
, GLint j
)
468 GET_CURRENT_CONTEXT( ctx
);
469 GLfloat du
= ((ctx
->Eval
.MapGrid2u2
- ctx
->Eval
.MapGrid2u1
) /
470 (GLfloat
) ctx
->Eval
.MapGrid2un
);
471 GLfloat dv
= ((ctx
->Eval
.MapGrid2v2
- ctx
->Eval
.MapGrid2v1
) /
472 (GLfloat
) ctx
->Eval
.MapGrid2vn
);
473 GLfloat u
= i
* du
+ ctx
->Eval
.MapGrid2u1
;
474 GLfloat v
= j
* dv
+ ctx
->Eval
.MapGrid2v1
;
476 vbo_exec_EvalCoord2f( u
, v
);
480 /* Build a list of primitives on the fly. Keep
481 * ctx->Driver.CurrentExecPrimitive uptodate as well.
483 static void GLAPIENTRY
vbo_exec_Begin( GLenum mode
)
485 GET_CURRENT_CONTEXT( ctx
);
487 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
488 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
492 _mesa_update_state( ctx
);
494 /* XXX also need to check if shader enabled, but invalid */
495 if ((ctx
->VertexProgram
.Enabled
&& !ctx
->VertexProgram
._Enabled
) ||
496 (ctx
->FragmentProgram
.Enabled
&& !ctx
->FragmentProgram
._Enabled
)) {
497 _mesa_error(ctx
, GL_INVALID_OPERATION
,
498 "glBegin (invalid vertex/fragment program)");
502 CALL_Begin(ctx
->Exec
, (mode
));
506 /* Heuristic: attempt to isolate attributes occuring outside
509 if (exec
->vtx
.vertex_size
&& !exec
->vtx
.attrsz
[0])
510 vbo_exec_FlushVertices( ctx
, ~0 );
512 i
= exec
->vtx
.prim_count
++;
513 exec
->vtx
.prim
[i
].mode
= mode
;
514 exec
->vtx
.prim
[i
].begin
= 1;
515 exec
->vtx
.prim
[i
].end
= 0;
516 exec
->vtx
.prim
[i
].indexed
= 0;
517 exec
->vtx
.prim
[i
].weak
= 0;
518 exec
->vtx
.prim
[i
].pad
= 0;
519 exec
->vtx
.prim
[i
].start
= exec
->vtx
.vert_count
;
520 exec
->vtx
.prim
[i
].count
= 0;
522 ctx
->Driver
.CurrentExecPrimitive
= mode
;
525 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin" );
529 static void GLAPIENTRY
vbo_exec_End( void )
531 GET_CURRENT_CONTEXT( ctx
);
533 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
534 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
535 int idx
= exec
->vtx
.vert_count
;
536 int i
= exec
->vtx
.prim_count
- 1;
538 exec
->vtx
.prim
[i
].end
= 1;
539 exec
->vtx
.prim
[i
].count
= idx
- exec
->vtx
.prim
[i
].start
;
541 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
543 if (exec
->vtx
.prim_count
== VBO_MAX_PRIM
)
544 vbo_exec_vtx_flush( exec
);
547 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glEnd" );
551 static void vbo_exec_vtxfmt_init( struct vbo_exec_context
*exec
)
553 GLvertexformat
*vfmt
= &exec
->vtxfmt
;
555 vfmt
->ArrayElement
= _ae_loopback_array_elt
; /* generic helper */
556 vfmt
->Begin
= vbo_exec_Begin
;
557 vfmt
->CallList
= _mesa_CallList
;
558 vfmt
->CallLists
= _mesa_CallLists
;
559 vfmt
->End
= vbo_exec_End
;
560 vfmt
->EvalCoord1f
= vbo_exec_EvalCoord1f
;
561 vfmt
->EvalCoord1fv
= vbo_exec_EvalCoord1fv
;
562 vfmt
->EvalCoord2f
= vbo_exec_EvalCoord2f
;
563 vfmt
->EvalCoord2fv
= vbo_exec_EvalCoord2fv
;
564 vfmt
->EvalPoint1
= vbo_exec_EvalPoint1
;
565 vfmt
->EvalPoint2
= vbo_exec_EvalPoint2
;
567 vfmt
->Rectf
= _mesa_noop_Rectf
;
568 vfmt
->EvalMesh1
= _mesa_noop_EvalMesh1
;
569 vfmt
->EvalMesh2
= _mesa_noop_EvalMesh2
;
572 /* from attrib_tmp.h:
574 vfmt
->Color3f
= vbo_Color3f
;
575 vfmt
->Color3fv
= vbo_Color3fv
;
576 vfmt
->Color4f
= vbo_Color4f
;
577 vfmt
->Color4fv
= vbo_Color4fv
;
578 vfmt
->FogCoordfEXT
= vbo_FogCoordfEXT
;
579 vfmt
->FogCoordfvEXT
= vbo_FogCoordfvEXT
;
580 vfmt
->MultiTexCoord1fARB
= vbo_MultiTexCoord1f
;
581 vfmt
->MultiTexCoord1fvARB
= vbo_MultiTexCoord1fv
;
582 vfmt
->MultiTexCoord2fARB
= vbo_MultiTexCoord2f
;
583 vfmt
->MultiTexCoord2fvARB
= vbo_MultiTexCoord2fv
;
584 vfmt
->MultiTexCoord3fARB
= vbo_MultiTexCoord3f
;
585 vfmt
->MultiTexCoord3fvARB
= vbo_MultiTexCoord3fv
;
586 vfmt
->MultiTexCoord4fARB
= vbo_MultiTexCoord4f
;
587 vfmt
->MultiTexCoord4fvARB
= vbo_MultiTexCoord4fv
;
588 vfmt
->Normal3f
= vbo_Normal3f
;
589 vfmt
->Normal3fv
= vbo_Normal3fv
;
590 vfmt
->SecondaryColor3fEXT
= vbo_SecondaryColor3fEXT
;
591 vfmt
->SecondaryColor3fvEXT
= vbo_SecondaryColor3fvEXT
;
592 vfmt
->TexCoord1f
= vbo_TexCoord1f
;
593 vfmt
->TexCoord1fv
= vbo_TexCoord1fv
;
594 vfmt
->TexCoord2f
= vbo_TexCoord2f
;
595 vfmt
->TexCoord2fv
= vbo_TexCoord2fv
;
596 vfmt
->TexCoord3f
= vbo_TexCoord3f
;
597 vfmt
->TexCoord3fv
= vbo_TexCoord3fv
;
598 vfmt
->TexCoord4f
= vbo_TexCoord4f
;
599 vfmt
->TexCoord4fv
= vbo_TexCoord4fv
;
600 vfmt
->Vertex2f
= vbo_Vertex2f
;
601 vfmt
->Vertex2fv
= vbo_Vertex2fv
;
602 vfmt
->Vertex3f
= vbo_Vertex3f
;
603 vfmt
->Vertex3fv
= vbo_Vertex3fv
;
604 vfmt
->Vertex4f
= vbo_Vertex4f
;
605 vfmt
->Vertex4fv
= vbo_Vertex4fv
;
607 vfmt
->VertexAttrib1fARB
= vbo_VertexAttrib1fARB
;
608 vfmt
->VertexAttrib1fvARB
= vbo_VertexAttrib1fvARB
;
609 vfmt
->VertexAttrib2fARB
= vbo_VertexAttrib2fARB
;
610 vfmt
->VertexAttrib2fvARB
= vbo_VertexAttrib2fvARB
;
611 vfmt
->VertexAttrib3fARB
= vbo_VertexAttrib3fARB
;
612 vfmt
->VertexAttrib3fvARB
= vbo_VertexAttrib3fvARB
;
613 vfmt
->VertexAttrib4fARB
= vbo_VertexAttrib4fARB
;
614 vfmt
->VertexAttrib4fvARB
= vbo_VertexAttrib4fvARB
;
616 vfmt
->VertexAttrib1fNV
= vbo_VertexAttrib1fNV
;
617 vfmt
->VertexAttrib1fvNV
= vbo_VertexAttrib1fvNV
;
618 vfmt
->VertexAttrib2fNV
= vbo_VertexAttrib2fNV
;
619 vfmt
->VertexAttrib2fvNV
= vbo_VertexAttrib2fvNV
;
620 vfmt
->VertexAttrib3fNV
= vbo_VertexAttrib3fNV
;
621 vfmt
->VertexAttrib3fvNV
= vbo_VertexAttrib3fvNV
;
622 vfmt
->VertexAttrib4fNV
= vbo_VertexAttrib4fNV
;
623 vfmt
->VertexAttrib4fvNV
= vbo_VertexAttrib4fvNV
;
625 vfmt
->Materialfv
= vbo_Materialfv
;
627 vfmt
->EdgeFlag
= vbo_EdgeFlag
;
628 vfmt
->Indexf
= vbo_Indexf
;
629 vfmt
->Indexfv
= vbo_Indexfv
;
635 * Tell the VBO module to use a real OpenGL vertex buffer object to
636 * store accumulated immediate-mode vertex data.
637 * This replaces the malloced buffer which was created in
638 * vb_exec_vtx_init() below.
640 void vbo_use_buffer_objects(GLcontext
*ctx
)
642 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
643 /* Any buffer name but 0 can be used here since this bufferobj won't
644 * go into the bufferobj hashtable.
646 GLuint bufName
= 0xaabbccdd;
647 GLenum target
= GL_ARRAY_BUFFER_ARB
;
648 GLenum access
= GL_READ_WRITE_ARB
;
649 GLenum usage
= GL_STREAM_DRAW_ARB
;
650 GLsizei size
= VBO_VERT_BUFFER_SIZE
* sizeof(GLfloat
);
652 /* Make sure this func is only used once */
653 assert(exec
->vtx
.bufferobj
== ctx
->Array
.NullBufferObj
);
654 if (exec
->vtx
.buffer_map
) {
655 _mesa_align_free(exec
->vtx
.buffer_map
);
658 /* Allocate a real buffer object now */
659 exec
->vtx
.bufferobj
= ctx
->Driver
.NewBufferObject(ctx
, bufName
, target
);
660 ctx
->Driver
.BufferData(ctx
, target
, size
, NULL
, usage
, exec
->vtx
.bufferobj
);
664 = ctx
->Driver
.MapBuffer(ctx
, target
, access
, exec
->vtx
.bufferobj
);
669 void vbo_exec_vtx_init( struct vbo_exec_context
*exec
)
671 GLcontext
*ctx
= exec
->ctx
;
672 struct vbo_context
*vbo
= vbo_context(ctx
);
675 /* Allocate a buffer object. Will just reuse this object
676 * continuously, unless vbo_use_buffer_objects() is called to enable
679 exec
->vtx
.bufferobj
= ctx
->Array
.NullBufferObj
;
680 exec
->vtx
.buffer_map
= ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE
* sizeof(GLfloat
), 64);
682 vbo_exec_vtxfmt_init( exec
);
684 /* Hook our functions into the dispatch table.
686 _mesa_install_exec_vtxfmt( exec
->ctx
, &exec
->vtxfmt
);
688 for (i
= 0 ; i
< VBO_ATTRIB_MAX
; i
++) {
689 exec
->vtx
.attrsz
[i
] = 0;
690 exec
->vtx
.active_sz
[i
] = 0;
691 exec
->vtx
.inputs
[i
] = &exec
->vtx
.arrays
[i
];
695 struct gl_client_array
*arrays
= exec
->vtx
.arrays
;
696 memcpy(arrays
, vbo
->legacy_currval
, 16 * sizeof(arrays
[0]));
697 memcpy(arrays
+ 16, vbo
->generic_currval
, 16 * sizeof(arrays
[0]));
700 exec
->vtx
.vertex_size
= 0;
704 void vbo_exec_vtx_destroy( struct vbo_exec_context
*exec
)
706 GLcontext
*ctx
= exec
->ctx
;
707 if (exec
->vtx
.bufferobj
->Name
) {
708 ctx
->Driver
.UnmapBuffer(ctx
, GL_ARRAY_BUFFER_ARB
, exec
->vtx
.bufferobj
);
709 ctx
->Driver
.DeleteBuffer(ctx
, exec
->vtx
.bufferobj
);
710 exec
->vtx
.bufferobj
= NULL
;
713 if (exec
->vtx
.buffer_map
) {
714 ALIGN_FREE(exec
->vtx
.buffer_map
);
715 exec
->vtx
.buffer_map
= NULL
;
721 void vbo_exec_FlushVertices( GLcontext
*ctx
, GLuint flags
)
723 struct vbo_exec_context
*exec
= &vbo_context(ctx
)->exec
;
725 if (exec
->ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
)
728 if (exec
->vtx
.vert_count
) {
729 vbo_exec_vtx_flush( exec
);
732 if (exec
->vtx
.vertex_size
) {
733 vbo_exec_copy_to_current( exec
);
734 reset_attrfv( exec
);
737 exec
->ctx
->Driver
.NeedFlush
= 0;
741 static void reset_attrfv( struct vbo_exec_context
*exec
)
745 for (i
= 0 ; i
< VBO_ATTRIB_MAX
; i
++) {
746 exec
->vtx
.attrsz
[i
] = 0;
747 exec
->vtx
.active_sz
[i
] = 0;
750 exec
->vtx
.vertex_size
= 0;