1 /**************************************************************************
3 Copyright 2002-2008 VMware, Inc.
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 VMWARE 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 <keithw@vmware.com>
33 #include "main/glheader.h"
34 #include "main/bufferobj.h"
35 #include "main/context.h"
36 #include "main/macros.h"
37 #include "main/dlist.h"
38 #include "main/eval.h"
39 #include "main/state.h"
40 #include "main/light.h"
41 #include "main/api_arrayelt.h"
42 #include "main/draw_validate.h"
43 #include "main/dispatch.h"
44 #include "util/bitscan.h"
45 #include "util/u_memory.h"
46 #include "api_exec_decl.h"
48 #include "vbo_private.h"
50 /** ID/name for immediate-mode VBO */
51 #define IMM_BUFFER_NAME 0xaabbccdd
55 vbo_reset_all_attr(struct vbo_exec_context *exec);
59 * Close off the last primitive, execute the buffer, restart the
60 * primitive. This is called when we fill a vertex buffer before
64 vbo_exec_wrap_buffers(struct vbo_exec_context *exec)
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;
72 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
73 unsigned last = exec->vtx.prim_count - 1;
74 struct pipe_draw_start_count_bias *last_draw = &exec->vtx.draw[last];
75 const bool last_begin = exec->vtx.markers[last].begin;
76 GLuint last_count = 0;
78 if (_mesa_inside_begin_end(ctx)) {
79 last_draw->count = exec->vtx.vert_count - last_draw->start;
80 last_count = last_draw->count;
81 exec->vtx.markers[last].end = 0;
84 /* Special handling for wrapping GL_LINE_LOOP */
85 if (exec->vtx.mode[last] == GL_LINE_LOOP &&
87 !exec->vtx.markers[last].end) {
88 /* draw this section of the incomplete line loop as a line strip */
89 exec->vtx.mode[last] = GL_LINE_STRIP;
91 /* This is not the first section of the line loop, so don't
92 * draw the 0th vertex. We're saving it until we draw the
93 * very last section of the loop.
100 /* Execute the buffer and save copied vertices.
102 if (exec->vtx.vert_count)
103 vbo_exec_vtx_flush(exec);
105 exec->vtx.prim_count = 0;
106 exec->vtx.copied.nr = 0;
109 /* Emit a glBegin to start the new list.
111 assert(exec->vtx.prim_count == 0);
113 if (_mesa_inside_begin_end(ctx)) {
114 exec->vtx.mode[0] = ctx->Driver.CurrentExecPrimitive;
115 exec->vtx.draw[0].start = 0;
116 exec->vtx.markers[0].begin = 0;
117 exec->vtx.prim_count++;
119 if (exec->vtx.copied.nr == last_count)
120 exec->vtx.markers[0].begin = last_begin;
127 * Deal with buffer wrapping where provoked by the vertex buffer
128 * filling up, as opposed to upgrade_vertex().
131 vbo_exec_vtx_wrap(struct vbo_exec_context *exec)
133 unsigned numComponents;
135 /* Run pipeline on current vertices, copy wrapped vertices
136 * to exec->vtx.copied.
138 vbo_exec_wrap_buffers(exec);
140 if (!exec->vtx.buffer_ptr) {
141 /* probably ran out of memory earlier when allocating the VBO */
145 /* Copy stored stored vertices to start of new list.
147 assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
149 numComponents = exec->vtx.copied.nr * exec->vtx.vertex_size;
150 memcpy(exec->vtx.buffer_ptr,
151 exec->vtx.copied.buffer,
152 numComponents * sizeof(fi_type));
153 exec->vtx.buffer_ptr += numComponents;
154 exec->vtx.vert_count += exec->vtx.copied.nr;
156 exec->vtx.copied.nr = 0;
161 * Copy the active vertex's values to the ctx->Current fields.
164 vbo_exec_copy_to_current(struct vbo_exec_context *exec)
166 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
167 struct vbo_context *vbo = vbo_context(ctx);
168 GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
169 bool color0_changed = false;
172 const int i = u_bit_scan64(&enabled);
174 /* Note: the exec->vtx.current[i] pointers point into the
175 * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
177 GLfloat *current = (GLfloat *)vbo->current[i].Ptr;
178 fi_type tmp[8]; /* space for doubles */
181 assert(exec->vtx.attr[i].size);
183 /* VBO_ATTRIB_SELECT_RESULT_INDEX has no current */
187 if (exec->vtx.attr[i].type == GL_DOUBLE ||
188 exec->vtx.attr[i].type == GL_UNSIGNED_INT64_ARB) {
189 memset(tmp, 0, sizeof(tmp));
190 memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attr[i].size * sizeof(GLfloat));
193 COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
194 exec->vtx.attr[i].size,
195 exec->vtx.attrptr[i],
196 exec->vtx.attr[i].type);
199 if (memcmp(current, tmp, 4 * sizeof(GLfloat) << dmul_shift) != 0) {
200 memcpy(current, tmp, 4 * sizeof(GLfloat) << dmul_shift);
202 if (i == VBO_ATTRIB_COLOR0)
203 color0_changed = true;
205 if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT) {
206 ctx->NewState |= _NEW_MATERIAL;
207 ctx->PopAttribState |= GL_LIGHTING_BIT;
209 /* The fixed-func vertex program uses this. */
210 if (i == VBO_ATTRIB_MAT_FRONT_SHININESS ||
211 i == VBO_ATTRIB_MAT_BACK_SHININESS)
212 ctx->NewState |= _NEW_FF_VERT_PROGRAM;
214 ctx->NewState |= _NEW_CURRENT_ATTRIB;
215 ctx->PopAttribState |= GL_CURRENT_BIT;
219 /* Given that we explicitly state size here, there is no need
220 * for the COPY_CLEAN above, could just copy 16 bytes and be
221 * done. The only problem is when Mesa accesses ctx->Current
224 /* Size here is in components - not bytes */
225 if (exec->vtx.attr[i].type != vbo->current[i].Format.Type ||
226 (exec->vtx.attr[i].size >> dmul_shift) != vbo->current[i].Format.Size) {
227 vbo_set_vertex_format(&vbo->current[i].Format,
228 exec->vtx.attr[i].size >> dmul_shift,
229 exec->vtx.attr[i].type);
233 if (color0_changed && ctx->Light.ColorMaterialEnabled) {
234 _mesa_update_color_material(ctx,
235 ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
241 * Flush existing data, set new attrib size, replay copied vertices.
242 * This is called when we transition from a small vertex attribute size
243 * to a larger one. Ex: glTexCoord2f -> glTexCoord4f.
244 * We need to go back over the previous 2-component texcoords and insert
245 * zero and one values.
246 * \param attr VBO_ATTRIB_x vertex attribute value
249 vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
250 GLuint attr, GLuint newSize, GLenum newType)
252 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
253 struct vbo_context *vbo = vbo_context(ctx);
254 const GLint lastcount = exec->vtx.vert_count;
255 fi_type *old_attrptr[VBO_ATTRIB_MAX];
256 const GLuint old_vtx_size_no_pos = exec->vtx.vertex_size_no_pos;
257 const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
258 const GLuint oldSize = exec->vtx.attr[attr].size;
261 assert(attr < VBO_ATTRIB_MAX);
263 if (unlikely(!exec->vtx.buffer_ptr)) {
264 /* We should only hit this when use_buffer_objects=true */
265 assert(exec->vtx.bufferobj);
266 vbo_exec_vtx_map(exec);
267 assert(exec->vtx.buffer_ptr);
270 /* Run pipeline on current vertices, copy wrapped vertices
271 * to exec->vtx.copied.
273 vbo_exec_wrap_buffers(exec);
275 if (unlikely(exec->vtx.copied.nr)) {
276 /* We're in the middle of a primitive, keep the old vertex
277 * format around to be able to translate the copied vertices to
280 memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
283 /* Heuristic: Attempt to isolate attributes received outside
284 * begin/end so that they don't bloat the vertices.
286 if (!_mesa_inside_begin_end(ctx) &&
287 !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
288 vbo_exec_copy_to_current(exec);
289 vbo_reset_all_attr(exec);
294 exec->vtx.attr[attr].size = newSize;
295 exec->vtx.attr[attr].active_size = newSize;
296 exec->vtx.attr[attr].type = newType;
297 exec->vtx.vertex_size += newSize - oldSize;
298 exec->vtx.vertex_size_no_pos = exec->vtx.vertex_size - exec->vtx.attr[0].size;
299 exec->vtx.max_vert = vbo_compute_max_verts(exec);
300 exec->vtx.vert_count = 0;
301 exec->vtx.buffer_ptr = exec->vtx.buffer_map;
302 exec->vtx.enabled |= BITFIELD64_BIT(attr);
305 if (unlikely(oldSize)) {
306 unsigned offset = exec->vtx.attrptr[attr] - exec->vtx.vertex;
308 /* If there are attribs after the resized attrib... */
309 if (offset + oldSize < old_vtx_size_no_pos) {
310 int size_diff = newSize - oldSize;
311 fi_type *old_first = exec->vtx.attrptr[attr] + oldSize;
312 fi_type *new_first = exec->vtx.attrptr[attr] + newSize;
313 fi_type *old_last = exec->vtx.vertex + old_vtx_size_no_pos - 1;
314 fi_type *new_last = exec->vtx.vertex + exec->vtx.vertex_size_no_pos - 1;
317 /* Decreasing the size: Copy from first to last to move
318 * elements to the left.
320 fi_type *old_end = old_last + 1;
321 fi_type *old = old_first;
322 fi_type *new = new_first;
326 } while (old != old_end);
328 /* Increasing the size: Copy from last to first to move
329 * elements to the right.
331 fi_type *old_end = old_first - 1;
332 fi_type *old = old_last;
333 fi_type *new = new_last;
337 } while (old != old_end);
340 /* Update pointers to attribs, because we moved them. */
341 GLbitfield64 enabled = exec->vtx.enabled &
342 ~BITFIELD64_BIT(VBO_ATTRIB_POS) &
343 ~BITFIELD64_BIT(attr);
345 unsigned i = u_bit_scan64(&enabled);
347 if (exec->vtx.attrptr[i] > exec->vtx.attrptr[attr])
348 exec->vtx.attrptr[i] += size_diff;
352 /* Just have to append the new attribute at the end */
353 exec->vtx.attrptr[attr] = exec->vtx.vertex +
354 exec->vtx.vertex_size_no_pos - newSize;
358 /* The position is always last. */
359 exec->vtx.attrptr[0] = exec->vtx.vertex + exec->vtx.vertex_size_no_pos;
361 /* Replay stored vertices to translate them
362 * to new format here.
364 * -- No need to replay - just copy piecewise
366 if (unlikely(exec->vtx.copied.nr)) {
367 fi_type *data = exec->vtx.copied.buffer;
368 fi_type *dest = exec->vtx.buffer_ptr;
370 assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
372 for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
373 GLbitfield64 enabled = exec->vtx.enabled;
375 const int j = u_bit_scan64(&enabled);
376 GLuint sz = exec->vtx.attr[j].size;
377 GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
378 GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
385 COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
387 exec->vtx.attr[j].type);
388 COPY_SZ_4V(dest + new_offset, newSize, tmp);
390 fi_type *current = (fi_type *)vbo->current[j].Ptr;
391 COPY_SZ_4V(dest + new_offset, sz, current);
395 COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
399 data += old_vtx_size;
400 dest += exec->vtx.vertex_size;
403 exec->vtx.buffer_ptr = dest;
404 exec->vtx.vert_count += exec->vtx.copied.nr;
405 exec->vtx.copied.nr = 0;
411 * This is when a vertex attribute transitions to a different size.
412 * For example, we saw a bunch of glTexCoord2f() calls and now we got a
413 * glTexCoord4f() call. We promote the array from size=2 to size=4.
414 * \param newSize size of new vertex (number of 32-bit words).
415 * \param attr VBO_ATTRIB_x vertex attribute value
418 vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr,
419 GLuint newSize, GLenum newType)
421 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
423 assert(attr < VBO_ATTRIB_MAX);
425 if (newSize > exec->vtx.attr[attr].size ||
426 newType != exec->vtx.attr[attr].type) {
427 /* New size is larger. Need to flush existing vertices and get
428 * an enlarged vertex format.
430 vbo_exec_wrap_upgrade_vertex(exec, attr, newSize, newType);
432 else if (newSize < exec->vtx.attr[attr].active_size) {
435 vbo_get_default_vals_as_union(exec->vtx.attr[attr].type);
437 /* New size is smaller - just need to fill in some
438 * zeros. Don't need to flush or wrap.
440 for (i = newSize; i <= exec->vtx.attr[attr].size; i++)
441 exec->vtx.attrptr[attr][i-1] = id[i-1];
443 exec->vtx.attr[attr].active_size = newSize;
449 * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
450 * It depends on a few things, including whether we're inside or outside
454 is_vertex_position(const struct gl_context *ctx, GLuint index)
456 return (index == 0 &&
457 _mesa_attr_zero_aliases_vertex(ctx) &&
458 _mesa_inside_begin_end(ctx));
461 /* Write a 64-bit value into a 32-bit pointer by preserving endianness. */
462 #if UTIL_ARCH_LITTLE_ENDIAN
463 #define SET_64BIT(dst32, u64) do { \
464 *(dst32)++ = (u64); \
465 *(dst32)++ = (uint64_t)(u64) >> 32; \
468 #define SET_64BIT(dst32, u64) do { \
469 *(dst32)++ = (uint64_t)(u64) >> 32; \
470 *(dst32)++ = (u64); \
476 * This macro is used to implement all the glVertex, glColor, glTexCoord,
477 * glVertexAttrib, etc functions.
478 * \param A VBO_ATTRIB_x attribute index
479 * \param N attribute size (1..4)
480 * \param T type (GL_FLOAT, GL_DOUBLE, GL_INT, GL_UNSIGNED_INT)
481 * \param C cast type (uint32_t or uint64_t)
482 * \param V0, V1, v2, V3 attribute value
484 #define ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3) \
486 struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
487 int sz = (sizeof(C) / sizeof(GLfloat)); \
489 assert(sz == 1 || sz == 2); \
490 /* store a copy of the attribute in exec except for glVertex */ \
492 /* Check if attribute size or type is changing. */ \
493 if (unlikely(exec->vtx.attr[A].active_size != N * sz || \
494 exec->vtx.attr[A].type != T)) { \
495 vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
498 C *dest = (C *)exec->vtx.attrptr[A]; \
499 if (N>0) dest[0] = V0; \
500 if (N>1) dest[1] = V1; \
501 if (N>2) dest[2] = V2; \
502 if (N>3) dest[3] = V3; \
503 assert(exec->vtx.attr[A].type == T); \
505 /* we now have accumulated a per-vertex attribute */ \
506 ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
508 /* This is a glVertex call */ \
509 int size = exec->vtx.attr[0].size; \
511 /* Check if attribute size or type is changing. */ \
512 if (unlikely(size < N * sz || \
513 exec->vtx.attr[0].type != T)) { \
514 vbo_exec_wrap_upgrade_vertex(exec, 0, N * sz, T); \
517 uint32_t *dst = (uint32_t *)exec->vtx.buffer_ptr; \
518 uint32_t *src = (uint32_t *)exec->vtx.vertex; \
519 unsigned vertex_size_no_pos = exec->vtx.vertex_size_no_pos; \
521 /* Copy over attributes from exec. */ \
522 for (unsigned i = 0; i < vertex_size_no_pos; i++) \
525 /* Store the position, which is always last and can have 32 or */ \
526 /* 64 bits per channel. */ \
527 if (sizeof(C) == 4) { \
528 if (N > 0) *dst++ = V0; \
529 if (N > 1) *dst++ = V1; \
530 if (N > 2) *dst++ = V2; \
531 if (N > 3) *dst++ = V3; \
533 if (unlikely(N < size)) { \
534 if (N < 2 && size >= 2) *dst++ = V1; \
535 if (N < 3 && size >= 3) *dst++ = V2; \
536 if (N < 4 && size >= 4) *dst++ = V3; \
539 /* 64 bits: dst can be unaligned, so copy each 4-byte word */ \
541 if (N > 0) SET_64BIT(dst, V0); \
542 if (N > 1) SET_64BIT(dst, V1); \
543 if (N > 2) SET_64BIT(dst, V2); \
544 if (N > 3) SET_64BIT(dst, V3); \
546 if (unlikely(N * 2 < size)) { \
547 if (N < 2 && size >= 4) SET_64BIT(dst, V1); \
548 if (N < 3 && size >= 6) SET_64BIT(dst, V2); \
549 if (N < 4 && size >= 8) SET_64BIT(dst, V3); \
553 /* dst now points at the beginning of the next vertex */ \
554 exec->vtx.buffer_ptr = (fi_type*)dst; \
556 /* Don't set FLUSH_UPDATE_CURRENT because */ \
557 /* Current.Attrib[VBO_ATTRIB_POS] is never used. */ \
559 if (unlikely(++exec->vtx.vert_count >= exec->vtx.max_vert)) \
560 vbo_exec_vtx_wrap(exec); \
565 #define ERROR(err) _mesa_error(ctx, err, __func__)
566 #define TAG(x) _mesa_##x
567 #define SUPPRESS_STATIC
569 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
570 ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3)
572 #include "vbo_attrib_tmp.h"
576 * Execute a glMaterial call. Note that if GL_COLOR_MATERIAL is enabled,
577 * this may be a (partial) no-op.
580 _mesa_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
582 GLbitfield updateMats;
583 GET_CURRENT_CONTEXT(ctx);
585 /* This function should be a no-op when it tries to update material
586 * attributes which are currently tracking glColor via glColorMaterial.
587 * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
588 * indicating which material attributes can actually be updated below.
590 if (ctx->Light.ColorMaterialEnabled) {
591 updateMats = ~ctx->Light._ColorMaterialBitmask;
594 /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
595 updateMats = ALL_MATERIAL_BITS;
598 if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
599 updateMats &= FRONT_MATERIAL_BITS;
601 else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
602 updateMats &= BACK_MATERIAL_BITS;
604 else if (face != GL_FRONT_AND_BACK) {
605 _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
611 if (updateMats & MAT_BIT_FRONT_EMISSION)
612 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
613 if (updateMats & MAT_BIT_BACK_EMISSION)
614 MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
617 if (updateMats & MAT_BIT_FRONT_AMBIENT)
618 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
619 if (updateMats & MAT_BIT_BACK_AMBIENT)
620 MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
623 if (updateMats & MAT_BIT_FRONT_DIFFUSE)
624 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
625 if (updateMats & MAT_BIT_BACK_DIFFUSE)
626 MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
629 if (updateMats & MAT_BIT_FRONT_SPECULAR)
630 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
631 if (updateMats & MAT_BIT_BACK_SPECULAR)
632 MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
635 if (*params < 0 || *params > ctx->Const.MaxShininess) {
636 _mesa_error(ctx, GL_INVALID_VALUE,
637 "glMaterial(invalid shininess: %f out range [0, %f])",
638 *params, ctx->Const.MaxShininess);
641 if (updateMats & MAT_BIT_FRONT_SHININESS)
642 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
643 if (updateMats & MAT_BIT_BACK_SHININESS)
644 MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
646 case GL_COLOR_INDEXES:
647 if (ctx->API != API_OPENGL_COMPAT) {
648 _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
651 if (updateMats & MAT_BIT_FRONT_INDEXES)
652 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
653 if (updateMats & MAT_BIT_BACK_INDEXES)
654 MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
656 case GL_AMBIENT_AND_DIFFUSE:
657 if (updateMats & MAT_BIT_FRONT_AMBIENT)
658 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
659 if (updateMats & MAT_BIT_FRONT_DIFFUSE)
660 MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
661 if (updateMats & MAT_BIT_BACK_AMBIENT)
662 MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
663 if (updateMats & MAT_BIT_BACK_DIFFUSE)
664 MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
667 _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
674 * Flush (draw) vertices.
676 * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
679 vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, unsigned flags)
681 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
683 if (flags & FLUSH_STORED_VERTICES) {
684 if (exec->vtx.vert_count) {
685 vbo_exec_vtx_flush(exec);
688 if (exec->vtx.vertex_size) {
689 vbo_exec_copy_to_current(exec);
690 vbo_reset_all_attr(exec);
694 ctx->Driver.NeedFlush = 0;
696 assert(flags == FLUSH_UPDATE_CURRENT);
698 /* Note that the vertex size is unchanged.
699 * (vbo_reset_all_attr isn't called)
701 vbo_exec_copy_to_current(exec);
703 /* Only FLUSH_UPDATE_CURRENT is done. */
704 ctx->Driver.NeedFlush = ~FLUSH_UPDATE_CURRENT;
710 _mesa_EvalCoord1f(GLfloat u)
712 GET_CURRENT_CONTEXT(ctx);
713 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
717 if (exec->eval.recalculate_maps)
718 vbo_exec_eval_update(exec);
720 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
721 if (exec->eval.map1[i].map)
722 if (exec->vtx.attr[i].active_size != exec->eval.map1[i].sz)
723 vbo_exec_fixup_vertex(ctx, i, exec->eval.map1[i].sz, GL_FLOAT);
727 memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
728 exec->vtx.vertex_size * sizeof(GLfloat));
730 vbo_exec_do_EvalCoord1f(exec, u);
732 memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
733 exec->vtx.vertex_size * sizeof(GLfloat));
738 _mesa_EvalCoord2f(GLfloat u, GLfloat v)
740 GET_CURRENT_CONTEXT(ctx);
741 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
745 if (exec->eval.recalculate_maps)
746 vbo_exec_eval_update(exec);
748 for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
749 if (exec->eval.map2[i].map)
750 if (exec->vtx.attr[i].active_size != exec->eval.map2[i].sz)
751 vbo_exec_fixup_vertex(ctx, i, exec->eval.map2[i].sz, GL_FLOAT);
754 if (ctx->Eval.AutoNormal)
755 if (exec->vtx.attr[VBO_ATTRIB_NORMAL].active_size != 3)
756 vbo_exec_fixup_vertex(ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT);
759 memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
760 exec->vtx.vertex_size * sizeof(GLfloat));
762 vbo_exec_do_EvalCoord2f(exec, u, v);
764 memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
765 exec->vtx.vertex_size * sizeof(GLfloat));
770 _mesa_EvalCoord1fv(const GLfloat *u)
772 _mesa_EvalCoord1f(u[0]);
777 _mesa_EvalCoord2fv(const GLfloat *u)
779 _mesa_EvalCoord2f(u[0], u[1]);
784 _mesa_EvalPoint1(GLint i)
786 GET_CURRENT_CONTEXT(ctx);
787 GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
788 (GLfloat) ctx->Eval.MapGrid1un);
789 GLfloat u = i * du + ctx->Eval.MapGrid1u1;
791 _mesa_EvalCoord1f(u);
796 _mesa_EvalPoint2(GLint i, GLint j)
798 GET_CURRENT_CONTEXT(ctx);
799 GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
800 (GLfloat) ctx->Eval.MapGrid2un);
801 GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
802 (GLfloat) ctx->Eval.MapGrid2vn);
803 GLfloat u = i * du + ctx->Eval.MapGrid2u1;
804 GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
806 _mesa_EvalCoord2f(u, v);
811 * Called via glBegin.
814 _mesa_Begin(GLenum mode)
816 GET_CURRENT_CONTEXT(ctx);
817 struct vbo_context *vbo = vbo_context(ctx);
818 struct vbo_exec_context *exec = &vbo->exec;
821 if (_mesa_inside_begin_end(ctx)) {
822 _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin");
827 _mesa_update_state(ctx);
829 GLenum error = _mesa_valid_prim_mode(ctx, mode);
830 if (error != GL_NO_ERROR) {
831 _mesa_error(ctx, error, "glBegin");
835 /* Heuristic: attempt to isolate attributes occurring outside
838 * Use FLUSH_STORED_VERTICES, because it updates current attribs and
839 * sets vertex_size to 0. (FLUSH_UPDATE_CURRENT doesn't change vertex_size)
841 if (exec->vtx.vertex_size && !exec->vtx.attr[VBO_ATTRIB_POS].size)
842 vbo_exec_FlushVertices_internal(exec, FLUSH_STORED_VERTICES);
844 i = exec->vtx.prim_count++;
845 exec->vtx.mode[i] = mode;
846 exec->vtx.draw[i].start = exec->vtx.vert_count;
847 exec->vtx.markers[i].begin = 1;
849 ctx->Driver.CurrentExecPrimitive = mode;
851 ctx->Exec = _mesa_hw_select_enabled(ctx) ?
852 ctx->HWSelectModeBeginEnd : ctx->BeginEnd;
854 /* We may have been called from a display list, in which case we should
855 * leave dlist.c's dispatch table in place.
857 if (ctx->GLThread.enabled) {
858 ctx->CurrentServerDispatch = ctx->Exec;
859 } else if (ctx->CurrentClientDispatch == ctx->OutsideBeginEnd) {
860 ctx->CurrentClientDispatch = ctx->CurrentServerDispatch = ctx->Exec;
861 _glapi_set_dispatch(ctx->CurrentClientDispatch);
863 assert(ctx->CurrentClientDispatch == ctx->Save);
869 * Try to merge / concatenate the two most recent VBO primitives.
872 try_vbo_merge(struct vbo_exec_context *exec)
874 unsigned cur = exec->vtx.prim_count - 1;
876 assert(exec->vtx.prim_count >= 1);
878 vbo_try_prim_conversion(&exec->vtx.mode[cur], &exec->vtx.draw[cur].count);
880 if (exec->vtx.prim_count >= 2) {
881 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
882 unsigned prev = cur - 1;
884 if (vbo_merge_draws(ctx, false,
885 exec->vtx.mode[prev],
887 exec->vtx.draw[prev].start,
888 exec->vtx.draw[cur].start,
889 &exec->vtx.draw[prev].count,
890 exec->vtx.draw[cur].count,
892 &exec->vtx.markers[prev].end,
893 exec->vtx.markers[cur].begin,
894 exec->vtx.markers[cur].end))
895 exec->vtx.prim_count--; /* drop the last primitive */
906 GET_CURRENT_CONTEXT(ctx);
907 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
909 if (!_mesa_inside_begin_end(ctx)) {
910 _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd");
914 ctx->Exec = ctx->OutsideBeginEnd;
916 if (ctx->GLThread.enabled) {
917 ctx->CurrentServerDispatch = ctx->Exec;
918 } else if (ctx->CurrentClientDispatch == ctx->BeginEnd ||
919 ctx->CurrentClientDispatch == ctx->HWSelectModeBeginEnd) {
920 ctx->CurrentClientDispatch = ctx->CurrentServerDispatch = ctx->Exec;
921 _glapi_set_dispatch(ctx->CurrentClientDispatch);
924 if (exec->vtx.prim_count > 0) {
925 /* close off current primitive */
926 unsigned last = exec->vtx.prim_count - 1;
927 struct pipe_draw_start_count_bias *last_draw = &exec->vtx.draw[last];
928 unsigned count = exec->vtx.vert_count - last_draw->start;
930 last_draw->count = count;
931 exec->vtx.markers[last].end = 1;
934 /* mark result buffer used */
935 if (_mesa_hw_select_enabled(ctx))
936 ctx->Select.ResultUsed = GL_TRUE;
938 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
941 /* Special handling for GL_LINE_LOOP */
942 if (exec->vtx.mode[last] == GL_LINE_LOOP &&
943 exec->vtx.markers[last].begin == 0) {
944 /* We're finishing drawing a line loop. Append 0th vertex onto
945 * end of vertex buffer so we can draw it as a line strip.
947 const fi_type *src = exec->vtx.buffer_map +
948 last_draw->start * exec->vtx.vertex_size;
949 fi_type *dst = exec->vtx.buffer_map +
950 exec->vtx.vert_count * exec->vtx.vertex_size;
952 /* copy 0th vertex to end of buffer */
953 memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type));
955 last_draw->start++; /* skip vertex0 */
956 /* note that the count stays unchanged */
957 exec->vtx.mode[last] = GL_LINE_STRIP;
959 /* Increment the vertex count so the next primitive doesn't
960 * overwrite the last vertex which we just added.
962 exec->vtx.vert_count++;
963 exec->vtx.buffer_ptr += exec->vtx.vertex_size;
969 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
971 if (exec->vtx.prim_count == VBO_MAX_PRIM)
972 vbo_exec_vtx_flush(exec);
974 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
981 * Called via glPrimitiveRestartNV()
984 _mesa_PrimitiveRestartNV(void)
987 GET_CURRENT_CONTEXT(ctx);
989 curPrim = ctx->Driver.CurrentExecPrimitive;
991 if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
992 _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV");
996 _mesa_Begin(curPrim);
1002 * A special version of glVertexAttrib4f that does not treat index 0 as
1006 VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1008 GET_CURRENT_CONTEXT(ctx);
1009 if (index < ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs)
1010 ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
1012 ERROR(GL_INVALID_VALUE);
1015 static void GLAPIENTRY
1016 _es_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1018 VertexAttrib4f_nopos(index, x, y, z, w);
1022 static void GLAPIENTRY
1023 _es_VertexAttrib1fARB(GLuint indx, GLfloat x)
1025 VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
1029 static void GLAPIENTRY
1030 _es_VertexAttrib1fvARB(GLuint indx, const GLfloat* values)
1032 VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
1036 static void GLAPIENTRY
1037 _es_VertexAttrib2fARB(GLuint indx, GLfloat x, GLfloat y)
1039 VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
1043 static void GLAPIENTRY
1044 _es_VertexAttrib2fvARB(GLuint indx, const GLfloat* values)
1046 VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
1050 static void GLAPIENTRY
1051 _es_VertexAttrib3fARB(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
1053 VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
1057 static void GLAPIENTRY
1058 _es_VertexAttrib3fvARB(GLuint indx, const GLfloat* values)
1060 VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
1064 static void GLAPIENTRY
1065 _es_VertexAttrib4fvARB(GLuint indx, const GLfloat* values)
1067 VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
1072 vbo_install_exec_vtxfmt(struct gl_context *ctx)
1074 #define NAME_AE(x) _mesa_##x
1075 #define NAME_CALLLIST(x) _mesa_##x
1076 #define NAME(x) _mesa_##x
1077 #define NAME_ES(x) _es_##x
1079 struct _glapi_table *tab = ctx->OutsideBeginEnd;
1080 #include "api_vtxfmt_init.h"
1082 if (ctx->BeginEnd) {
1083 tab = ctx->BeginEnd;
1084 #include "api_vtxfmt_init.h"
1090 vbo_reset_all_attr(struct vbo_exec_context *exec)
1092 while (exec->vtx.enabled) {
1093 const int i = u_bit_scan64(&exec->vtx.enabled);
1095 /* Reset the vertex attribute by setting its size to zero. */
1096 exec->vtx.attr[i].size = 0;
1097 exec->vtx.attr[i].type = GL_FLOAT;
1098 exec->vtx.attr[i].active_size = 0;
1099 exec->vtx.attrptr[i] = NULL;
1102 exec->vtx.vertex_size = 0;
1107 vbo_exec_vtx_init(struct vbo_exec_context *exec)
1109 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
1111 exec->vtx.bufferobj = _mesa_bufferobj_alloc(ctx, IMM_BUFFER_NAME);
1113 exec->vtx.enabled = u_bit_consecutive64(0, VBO_ATTRIB_MAX); /* reset all */
1114 vbo_reset_all_attr(exec);
1116 exec->vtx.info.instance_count = 1;
1117 exec->vtx.info.max_index = ~0;
1122 vbo_exec_vtx_destroy(struct vbo_exec_context *exec)
1124 /* using a real VBO for vertex data */
1125 struct gl_context *ctx = gl_context_from_vbo_exec(exec);
1127 /* True VBOs should already be unmapped
1129 if (exec->vtx.buffer_map) {
1130 assert(!exec->vtx.bufferobj ||
1131 exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
1132 if (!exec->vtx.bufferobj) {
1133 align_free(exec->vtx.buffer_map);
1134 exec->vtx.buffer_map = NULL;
1135 exec->vtx.buffer_ptr = NULL;
1139 /* Free the vertex buffer. Unmap first if needed.
1141 if (exec->vtx.bufferobj &&
1142 _mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
1143 _mesa_bufferobj_unmap(ctx, exec->vtx.bufferobj, MAP_INTERNAL);
1145 _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
1150 * If inside glBegin()/glEnd(), it should assert(0). Otherwise, if
1151 * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
1152 * vertices, if FLUSH_UPDATE_CURRENT bit is set updates
1153 * __struct gl_contextRec::Current and gl_light_attrib::Material
1155 * Note that the default T&L engine never clears the
1156 * FLUSH_UPDATE_CURRENT bit, even after performing the update.
1158 * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
1161 vbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags)
1163 struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
1166 /* debug check: make sure we don't get called recursively */
1167 exec->flush_call_depth++;
1168 assert(exec->flush_call_depth == 1);
1171 if (_mesa_inside_begin_end(ctx)) {
1172 /* We've had glBegin but not glEnd! */
1174 exec->flush_call_depth--;
1175 assert(exec->flush_call_depth == 0);
1181 vbo_exec_FlushVertices_internal(exec, flags);
1184 exec->flush_call_depth--;
1185 assert(exec->flush_call_depth == 0);
1191 _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1193 _mesa_Color4f(r, g, b, a);
1198 _es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
1200 _mesa_Normal3f(x, y, z);
1205 _es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1207 _mesa_MultiTexCoord4fARB(target, s, t, r, q);
1212 _es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1214 _mesa_Materialfv(face, pname, params);
1219 _es_Materialf(GLenum face, GLenum pname, GLfloat param)
1223 p[1] = p[2] = p[3] = 0.0F;
1224 _mesa_Materialfv(face, pname, p);
1228 #undef SUPPRESS_STATIC
1229 #define TAG(x) _hw_select_##x
1230 /* filter out none vertex api */
1231 #define HW_SELECT_MODE
1234 #define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
1237 ATTR_UNION_BASE(VBO_ATTRIB_SELECT_RESULT_OFFSET, 1, GL_UNSIGNED_INT, uint32_t, \
1238 ctx->Select.ResultOffset, 0, 0, 0); \
1240 ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3); \
1243 #include "vbo_attrib_tmp.h"
1246 vbo_install_hw_select_begin_end(struct gl_context *ctx)
1248 int numEntries = MAX2(_gloffset_COUNT, _glapi_get_dispatch_table_size());
1249 memcpy(ctx->HWSelectModeBeginEnd, ctx->BeginEnd, numEntries * sizeof(_glapi_proc));
1252 #define NAME(x) _hw_select_##x
1253 struct _glapi_table *tab = ctx->HWSelectModeBeginEnd;
1254 #include "api_hw_select_init.h"