1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci
3bf215546Sopenharmony_ciCopyright 2002-2008 VMware, Inc.
4bf215546Sopenharmony_ci
5bf215546Sopenharmony_ciAll Rights Reserved.
6bf215546Sopenharmony_ci
7bf215546Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_cicopy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_cito deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_cion the rights to use, copy, modify, merge, publish, distribute, sub
11bf215546Sopenharmony_cilicense, and/or sell copies of the Software, and to permit persons to whom
12bf215546Sopenharmony_cithe Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci
14bf215546Sopenharmony_ciThe above copyright notice and this permission notice (including the next
15bf215546Sopenharmony_ciparagraph) shall be included in all copies or substantial portions of the
16bf215546Sopenharmony_ciSoftware.
17bf215546Sopenharmony_ci
18bf215546Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bf215546Sopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bf215546Sopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21bf215546Sopenharmony_ciVMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22bf215546Sopenharmony_ciDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23bf215546Sopenharmony_ciOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24bf215546Sopenharmony_ciUSE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci**************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/*
29bf215546Sopenharmony_ci * Authors:
30bf215546Sopenharmony_ci *   Keith Whitwell <keithw@vmware.com>
31bf215546Sopenharmony_ci */
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "main/glheader.h"
34bf215546Sopenharmony_ci#include "main/bufferobj.h"
35bf215546Sopenharmony_ci#include "main/context.h"
36bf215546Sopenharmony_ci#include "main/macros.h"
37bf215546Sopenharmony_ci#include "main/dlist.h"
38bf215546Sopenharmony_ci#include "main/eval.h"
39bf215546Sopenharmony_ci#include "main/state.h"
40bf215546Sopenharmony_ci#include "main/light.h"
41bf215546Sopenharmony_ci#include "main/api_arrayelt.h"
42bf215546Sopenharmony_ci#include "main/draw_validate.h"
43bf215546Sopenharmony_ci#include "main/dispatch.h"
44bf215546Sopenharmony_ci#include "util/bitscan.h"
45bf215546Sopenharmony_ci#include "util/u_memory.h"
46bf215546Sopenharmony_ci#include "api_exec_decl.h"
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci#include "vbo_private.h"
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci/** ID/name for immediate-mode VBO */
51bf215546Sopenharmony_ci#define IMM_BUFFER_NAME 0xaabbccdd
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_cistatic void
55bf215546Sopenharmony_civbo_reset_all_attr(struct vbo_exec_context *exec);
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci/**
59bf215546Sopenharmony_ci * Close off the last primitive, execute the buffer, restart the
60bf215546Sopenharmony_ci * primitive.  This is called when we fill a vertex buffer before
61bf215546Sopenharmony_ci * hitting glEnd.
62bf215546Sopenharmony_ci */
63bf215546Sopenharmony_cistatic void
64bf215546Sopenharmony_civbo_exec_wrap_buffers(struct vbo_exec_context *exec)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   if (exec->vtx.prim_count == 0) {
67bf215546Sopenharmony_ci      exec->vtx.copied.nr = 0;
68bf215546Sopenharmony_ci      exec->vtx.vert_count = 0;
69bf215546Sopenharmony_ci      exec->vtx.buffer_ptr = exec->vtx.buffer_map;
70bf215546Sopenharmony_ci   }
71bf215546Sopenharmony_ci   else {
72bf215546Sopenharmony_ci      struct gl_context *ctx = gl_context_from_vbo_exec(exec);
73bf215546Sopenharmony_ci      unsigned last = exec->vtx.prim_count - 1;
74bf215546Sopenharmony_ci      struct pipe_draw_start_count_bias *last_draw = &exec->vtx.draw[last];
75bf215546Sopenharmony_ci      const bool last_begin = exec->vtx.markers[last].begin;
76bf215546Sopenharmony_ci      GLuint last_count = 0;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci      if (_mesa_inside_begin_end(ctx)) {
79bf215546Sopenharmony_ci         last_draw->count = exec->vtx.vert_count - last_draw->start;
80bf215546Sopenharmony_ci         last_count = last_draw->count;
81bf215546Sopenharmony_ci         exec->vtx.markers[last].end = 0;
82bf215546Sopenharmony_ci      }
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci      /* Special handling for wrapping GL_LINE_LOOP */
85bf215546Sopenharmony_ci      if (exec->vtx.mode[last] == GL_LINE_LOOP &&
86bf215546Sopenharmony_ci          last_count > 0 &&
87bf215546Sopenharmony_ci          !exec->vtx.markers[last].end) {
88bf215546Sopenharmony_ci         /* draw this section of the incomplete line loop as a line strip */
89bf215546Sopenharmony_ci         exec->vtx.mode[last] = GL_LINE_STRIP;
90bf215546Sopenharmony_ci         if (!last_begin) {
91bf215546Sopenharmony_ci            /* This is not the first section of the line loop, so don't
92bf215546Sopenharmony_ci             * draw the 0th vertex.  We're saving it until we draw the
93bf215546Sopenharmony_ci             * very last section of the loop.
94bf215546Sopenharmony_ci             */
95bf215546Sopenharmony_ci            last_draw->start++;
96bf215546Sopenharmony_ci            last_draw->count--;
97bf215546Sopenharmony_ci         }
98bf215546Sopenharmony_ci      }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci      /* Execute the buffer and save copied vertices.
101bf215546Sopenharmony_ci       */
102bf215546Sopenharmony_ci      if (exec->vtx.vert_count)
103bf215546Sopenharmony_ci         vbo_exec_vtx_flush(exec);
104bf215546Sopenharmony_ci      else {
105bf215546Sopenharmony_ci         exec->vtx.prim_count = 0;
106bf215546Sopenharmony_ci         exec->vtx.copied.nr = 0;
107bf215546Sopenharmony_ci      }
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci      /* Emit a glBegin to start the new list.
110bf215546Sopenharmony_ci       */
111bf215546Sopenharmony_ci      assert(exec->vtx.prim_count == 0);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci      if (_mesa_inside_begin_end(ctx)) {
114bf215546Sopenharmony_ci         exec->vtx.mode[0] = ctx->Driver.CurrentExecPrimitive;
115bf215546Sopenharmony_ci         exec->vtx.draw[0].start = 0;
116bf215546Sopenharmony_ci         exec->vtx.markers[0].begin = 0;
117bf215546Sopenharmony_ci         exec->vtx.prim_count++;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci         if (exec->vtx.copied.nr == last_count)
120bf215546Sopenharmony_ci            exec->vtx.markers[0].begin = last_begin;
121bf215546Sopenharmony_ci      }
122bf215546Sopenharmony_ci   }
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci/**
127bf215546Sopenharmony_ci * Deal with buffer wrapping where provoked by the vertex buffer
128bf215546Sopenharmony_ci * filling up, as opposed to upgrade_vertex().
129bf215546Sopenharmony_ci */
130bf215546Sopenharmony_cistatic void
131bf215546Sopenharmony_civbo_exec_vtx_wrap(struct vbo_exec_context *exec)
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci   unsigned numComponents;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   /* Run pipeline on current vertices, copy wrapped vertices
136bf215546Sopenharmony_ci    * to exec->vtx.copied.
137bf215546Sopenharmony_ci    */
138bf215546Sopenharmony_ci   vbo_exec_wrap_buffers(exec);
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   if (!exec->vtx.buffer_ptr) {
141bf215546Sopenharmony_ci      /* probably ran out of memory earlier when allocating the VBO */
142bf215546Sopenharmony_ci      return;
143bf215546Sopenharmony_ci   }
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   /* Copy stored stored vertices to start of new list.
146bf215546Sopenharmony_ci    */
147bf215546Sopenharmony_ci   assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   numComponents = exec->vtx.copied.nr * exec->vtx.vertex_size;
150bf215546Sopenharmony_ci   memcpy(exec->vtx.buffer_ptr,
151bf215546Sopenharmony_ci          exec->vtx.copied.buffer,
152bf215546Sopenharmony_ci          numComponents * sizeof(fi_type));
153bf215546Sopenharmony_ci   exec->vtx.buffer_ptr += numComponents;
154bf215546Sopenharmony_ci   exec->vtx.vert_count += exec->vtx.copied.nr;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   exec->vtx.copied.nr = 0;
157bf215546Sopenharmony_ci}
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci/**
161bf215546Sopenharmony_ci * Copy the active vertex's values to the ctx->Current fields.
162bf215546Sopenharmony_ci */
163bf215546Sopenharmony_cistatic void
164bf215546Sopenharmony_civbo_exec_copy_to_current(struct vbo_exec_context *exec)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   struct gl_context *ctx = gl_context_from_vbo_exec(exec);
167bf215546Sopenharmony_ci   struct vbo_context *vbo = vbo_context(ctx);
168bf215546Sopenharmony_ci   GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
169bf215546Sopenharmony_ci   bool color0_changed = false;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   while (enabled) {
172bf215546Sopenharmony_ci      const int i = u_bit_scan64(&enabled);
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci      /* Note: the exec->vtx.current[i] pointers point into the
175bf215546Sopenharmony_ci       * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
176bf215546Sopenharmony_ci       */
177bf215546Sopenharmony_ci      GLfloat *current = (GLfloat *)vbo->current[i].Ptr;
178bf215546Sopenharmony_ci      fi_type tmp[8]; /* space for doubles */
179bf215546Sopenharmony_ci      int dmul_shift = 0;
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci      assert(exec->vtx.attr[i].size);
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci      /* VBO_ATTRIB_SELECT_RESULT_INDEX has no current */
184bf215546Sopenharmony_ci      if (!current)
185bf215546Sopenharmony_ci         continue;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci      if (exec->vtx.attr[i].type == GL_DOUBLE ||
188bf215546Sopenharmony_ci          exec->vtx.attr[i].type == GL_UNSIGNED_INT64_ARB) {
189bf215546Sopenharmony_ci         memset(tmp, 0, sizeof(tmp));
190bf215546Sopenharmony_ci         memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attr[i].size * sizeof(GLfloat));
191bf215546Sopenharmony_ci         dmul_shift = 1;
192bf215546Sopenharmony_ci      } else {
193bf215546Sopenharmony_ci         COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
194bf215546Sopenharmony_ci                                     exec->vtx.attr[i].size,
195bf215546Sopenharmony_ci                                     exec->vtx.attrptr[i],
196bf215546Sopenharmony_ci                                     exec->vtx.attr[i].type);
197bf215546Sopenharmony_ci      }
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci      if (memcmp(current, tmp, 4 * sizeof(GLfloat) << dmul_shift) != 0) {
200bf215546Sopenharmony_ci         memcpy(current, tmp, 4 * sizeof(GLfloat) << dmul_shift);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci         if (i == VBO_ATTRIB_COLOR0)
203bf215546Sopenharmony_ci            color0_changed = true;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci         if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT) {
206bf215546Sopenharmony_ci            ctx->NewState |= _NEW_MATERIAL;
207bf215546Sopenharmony_ci            ctx->PopAttribState |= GL_LIGHTING_BIT;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci            /* The fixed-func vertex program uses this. */
210bf215546Sopenharmony_ci            if (i == VBO_ATTRIB_MAT_FRONT_SHININESS ||
211bf215546Sopenharmony_ci                i == VBO_ATTRIB_MAT_BACK_SHININESS)
212bf215546Sopenharmony_ci               ctx->NewState |= _NEW_FF_VERT_PROGRAM;
213bf215546Sopenharmony_ci         } else {
214bf215546Sopenharmony_ci            ctx->NewState |= _NEW_CURRENT_ATTRIB;
215bf215546Sopenharmony_ci            ctx->PopAttribState |= GL_CURRENT_BIT;
216bf215546Sopenharmony_ci         }
217bf215546Sopenharmony_ci      }
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci      /* Given that we explicitly state size here, there is no need
220bf215546Sopenharmony_ci       * for the COPY_CLEAN above, could just copy 16 bytes and be
221bf215546Sopenharmony_ci       * done.  The only problem is when Mesa accesses ctx->Current
222bf215546Sopenharmony_ci       * directly.
223bf215546Sopenharmony_ci       */
224bf215546Sopenharmony_ci      /* Size here is in components - not bytes */
225bf215546Sopenharmony_ci      if (exec->vtx.attr[i].type != vbo->current[i].Format.Type ||
226bf215546Sopenharmony_ci          (exec->vtx.attr[i].size >> dmul_shift) != vbo->current[i].Format.Size) {
227bf215546Sopenharmony_ci         vbo_set_vertex_format(&vbo->current[i].Format,
228bf215546Sopenharmony_ci                               exec->vtx.attr[i].size >> dmul_shift,
229bf215546Sopenharmony_ci                               exec->vtx.attr[i].type);
230bf215546Sopenharmony_ci      }
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   if (color0_changed && ctx->Light.ColorMaterialEnabled) {
234bf215546Sopenharmony_ci      _mesa_update_color_material(ctx,
235bf215546Sopenharmony_ci                                  ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
236bf215546Sopenharmony_ci   }
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci/**
241bf215546Sopenharmony_ci * Flush existing data, set new attrib size, replay copied vertices.
242bf215546Sopenharmony_ci * This is called when we transition from a small vertex attribute size
243bf215546Sopenharmony_ci * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
244bf215546Sopenharmony_ci * We need to go back over the previous 2-component texcoords and insert
245bf215546Sopenharmony_ci * zero and one values.
246bf215546Sopenharmony_ci * \param attr  VBO_ATTRIB_x vertex attribute value
247bf215546Sopenharmony_ci */
248bf215546Sopenharmony_cistatic void
249bf215546Sopenharmony_civbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
250bf215546Sopenharmony_ci                             GLuint attr, GLuint newSize, GLenum newType)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   struct gl_context *ctx = gl_context_from_vbo_exec(exec);
253bf215546Sopenharmony_ci   struct vbo_context *vbo = vbo_context(ctx);
254bf215546Sopenharmony_ci   const GLint lastcount = exec->vtx.vert_count;
255bf215546Sopenharmony_ci   fi_type *old_attrptr[VBO_ATTRIB_MAX];
256bf215546Sopenharmony_ci   const GLuint old_vtx_size_no_pos = exec->vtx.vertex_size_no_pos;
257bf215546Sopenharmony_ci   const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
258bf215546Sopenharmony_ci   const GLuint oldSize = exec->vtx.attr[attr].size;
259bf215546Sopenharmony_ci   GLuint i;
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ci   assert(attr < VBO_ATTRIB_MAX);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   if (unlikely(!exec->vtx.buffer_ptr)) {
264bf215546Sopenharmony_ci      /* We should only hit this when use_buffer_objects=true */
265bf215546Sopenharmony_ci      assert(exec->vtx.bufferobj);
266bf215546Sopenharmony_ci      vbo_exec_vtx_map(exec);
267bf215546Sopenharmony_ci      assert(exec->vtx.buffer_ptr);
268bf215546Sopenharmony_ci   }
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   /* Run pipeline on current vertices, copy wrapped vertices
271bf215546Sopenharmony_ci    * to exec->vtx.copied.
272bf215546Sopenharmony_ci    */
273bf215546Sopenharmony_ci   vbo_exec_wrap_buffers(exec);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   if (unlikely(exec->vtx.copied.nr)) {
276bf215546Sopenharmony_ci      /* We're in the middle of a primitive, keep the old vertex
277bf215546Sopenharmony_ci       * format around to be able to translate the copied vertices to
278bf215546Sopenharmony_ci       * the new format.
279bf215546Sopenharmony_ci       */
280bf215546Sopenharmony_ci      memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
281bf215546Sopenharmony_ci   }
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   /* Heuristic: Attempt to isolate attributes received outside
284bf215546Sopenharmony_ci    * begin/end so that they don't bloat the vertices.
285bf215546Sopenharmony_ci    */
286bf215546Sopenharmony_ci   if (!_mesa_inside_begin_end(ctx) &&
287bf215546Sopenharmony_ci       !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
288bf215546Sopenharmony_ci      vbo_exec_copy_to_current(exec);
289bf215546Sopenharmony_ci      vbo_reset_all_attr(exec);
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   /* Fix up sizes:
293bf215546Sopenharmony_ci    */
294bf215546Sopenharmony_ci   exec->vtx.attr[attr].size = newSize;
295bf215546Sopenharmony_ci   exec->vtx.attr[attr].active_size = newSize;
296bf215546Sopenharmony_ci   exec->vtx.attr[attr].type = newType;
297bf215546Sopenharmony_ci   exec->vtx.vertex_size += newSize - oldSize;
298bf215546Sopenharmony_ci   exec->vtx.vertex_size_no_pos = exec->vtx.vertex_size - exec->vtx.attr[0].size;
299bf215546Sopenharmony_ci   exec->vtx.max_vert = vbo_compute_max_verts(exec);
300bf215546Sopenharmony_ci   exec->vtx.vert_count = 0;
301bf215546Sopenharmony_ci   exec->vtx.buffer_ptr = exec->vtx.buffer_map;
302bf215546Sopenharmony_ci   exec->vtx.enabled |= BITFIELD64_BIT(attr);
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   if (attr != 0) {
305bf215546Sopenharmony_ci      if (unlikely(oldSize)) {
306bf215546Sopenharmony_ci         unsigned offset = exec->vtx.attrptr[attr] - exec->vtx.vertex;
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci         /* If there are attribs after the resized attrib... */
309bf215546Sopenharmony_ci         if (offset + oldSize < old_vtx_size_no_pos) {
310bf215546Sopenharmony_ci            int size_diff = newSize - oldSize;
311bf215546Sopenharmony_ci            fi_type *old_first = exec->vtx.attrptr[attr] + oldSize;
312bf215546Sopenharmony_ci            fi_type *new_first = exec->vtx.attrptr[attr] + newSize;
313bf215546Sopenharmony_ci            fi_type *old_last = exec->vtx.vertex + old_vtx_size_no_pos - 1;
314bf215546Sopenharmony_ci            fi_type *new_last = exec->vtx.vertex + exec->vtx.vertex_size_no_pos - 1;
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci            if (size_diff < 0) {
317bf215546Sopenharmony_ci               /* Decreasing the size: Copy from first to last to move
318bf215546Sopenharmony_ci                * elements to the left.
319bf215546Sopenharmony_ci                */
320bf215546Sopenharmony_ci               fi_type *old_end = old_last + 1;
321bf215546Sopenharmony_ci               fi_type *old = old_first;
322bf215546Sopenharmony_ci               fi_type *new = new_first;
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci               do {
325bf215546Sopenharmony_ci                  *new++ = *old++;
326bf215546Sopenharmony_ci               } while (old != old_end);
327bf215546Sopenharmony_ci            } else {
328bf215546Sopenharmony_ci               /* Increasing the size: Copy from last to first to move
329bf215546Sopenharmony_ci                * elements to the right.
330bf215546Sopenharmony_ci                */
331bf215546Sopenharmony_ci               fi_type *old_end = old_first - 1;
332bf215546Sopenharmony_ci               fi_type *old = old_last;
333bf215546Sopenharmony_ci               fi_type *new = new_last;
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci               do {
336bf215546Sopenharmony_ci                  *new-- = *old--;
337bf215546Sopenharmony_ci               } while (old != old_end);
338bf215546Sopenharmony_ci            }
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci            /* Update pointers to attribs, because we moved them. */
341bf215546Sopenharmony_ci            GLbitfield64 enabled = exec->vtx.enabled &
342bf215546Sopenharmony_ci                                   ~BITFIELD64_BIT(VBO_ATTRIB_POS) &
343bf215546Sopenharmony_ci                                   ~BITFIELD64_BIT(attr);
344bf215546Sopenharmony_ci            while (enabled) {
345bf215546Sopenharmony_ci               unsigned i = u_bit_scan64(&enabled);
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci               if (exec->vtx.attrptr[i] > exec->vtx.attrptr[attr])
348bf215546Sopenharmony_ci                  exec->vtx.attrptr[i] += size_diff;
349bf215546Sopenharmony_ci            }
350bf215546Sopenharmony_ci         }
351bf215546Sopenharmony_ci      } else {
352bf215546Sopenharmony_ci         /* Just have to append the new attribute at the end */
353bf215546Sopenharmony_ci         exec->vtx.attrptr[attr] = exec->vtx.vertex +
354bf215546Sopenharmony_ci           exec->vtx.vertex_size_no_pos - newSize;
355bf215546Sopenharmony_ci      }
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   /* The position is always last. */
359bf215546Sopenharmony_ci   exec->vtx.attrptr[0] = exec->vtx.vertex + exec->vtx.vertex_size_no_pos;
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci   /* Replay stored vertices to translate them
362bf215546Sopenharmony_ci    * to new format here.
363bf215546Sopenharmony_ci    *
364bf215546Sopenharmony_ci    * -- No need to replay - just copy piecewise
365bf215546Sopenharmony_ci    */
366bf215546Sopenharmony_ci   if (unlikely(exec->vtx.copied.nr)) {
367bf215546Sopenharmony_ci      fi_type *data = exec->vtx.copied.buffer;
368bf215546Sopenharmony_ci      fi_type *dest = exec->vtx.buffer_ptr;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci      assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci      for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
373bf215546Sopenharmony_ci         GLbitfield64 enabled = exec->vtx.enabled;
374bf215546Sopenharmony_ci         while (enabled) {
375bf215546Sopenharmony_ci            const int j = u_bit_scan64(&enabled);
376bf215546Sopenharmony_ci            GLuint sz = exec->vtx.attr[j].size;
377bf215546Sopenharmony_ci            GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
378bf215546Sopenharmony_ci            GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci            assert(sz);
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci            if (j == attr) {
383bf215546Sopenharmony_ci               if (oldSize) {
384bf215546Sopenharmony_ci                  fi_type tmp[4];
385bf215546Sopenharmony_ci                  COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
386bf215546Sopenharmony_ci                                              data + old_offset,
387bf215546Sopenharmony_ci                                              exec->vtx.attr[j].type);
388bf215546Sopenharmony_ci                  COPY_SZ_4V(dest + new_offset, newSize, tmp);
389bf215546Sopenharmony_ci               } else {
390bf215546Sopenharmony_ci                  fi_type *current = (fi_type *)vbo->current[j].Ptr;
391bf215546Sopenharmony_ci                  COPY_SZ_4V(dest + new_offset, sz, current);
392bf215546Sopenharmony_ci               }
393bf215546Sopenharmony_ci            }
394bf215546Sopenharmony_ci            else {
395bf215546Sopenharmony_ci               COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
396bf215546Sopenharmony_ci            }
397bf215546Sopenharmony_ci         }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci         data += old_vtx_size;
400bf215546Sopenharmony_ci         dest += exec->vtx.vertex_size;
401bf215546Sopenharmony_ci      }
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci      exec->vtx.buffer_ptr = dest;
404bf215546Sopenharmony_ci      exec->vtx.vert_count += exec->vtx.copied.nr;
405bf215546Sopenharmony_ci      exec->vtx.copied.nr = 0;
406bf215546Sopenharmony_ci   }
407bf215546Sopenharmony_ci}
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci/**
411bf215546Sopenharmony_ci * This is when a vertex attribute transitions to a different size.
412bf215546Sopenharmony_ci * For example, we saw a bunch of glTexCoord2f() calls and now we got a
413bf215546Sopenharmony_ci * glTexCoord4f() call.  We promote the array from size=2 to size=4.
414bf215546Sopenharmony_ci * \param newSize  size of new vertex (number of 32-bit words).
415bf215546Sopenharmony_ci * \param attr  VBO_ATTRIB_x vertex attribute value
416bf215546Sopenharmony_ci */
417bf215546Sopenharmony_cistatic void
418bf215546Sopenharmony_civbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr,
419bf215546Sopenharmony_ci                      GLuint newSize, GLenum newType)
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci   assert(attr < VBO_ATTRIB_MAX);
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci   if (newSize > exec->vtx.attr[attr].size ||
426bf215546Sopenharmony_ci       newType != exec->vtx.attr[attr].type) {
427bf215546Sopenharmony_ci      /* New size is larger.  Need to flush existing vertices and get
428bf215546Sopenharmony_ci       * an enlarged vertex format.
429bf215546Sopenharmony_ci       */
430bf215546Sopenharmony_ci      vbo_exec_wrap_upgrade_vertex(exec, attr, newSize, newType);
431bf215546Sopenharmony_ci   }
432bf215546Sopenharmony_ci   else if (newSize < exec->vtx.attr[attr].active_size) {
433bf215546Sopenharmony_ci      GLuint i;
434bf215546Sopenharmony_ci      const fi_type *id =
435bf215546Sopenharmony_ci            vbo_get_default_vals_as_union(exec->vtx.attr[attr].type);
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci      /* New size is smaller - just need to fill in some
438bf215546Sopenharmony_ci       * zeros.  Don't need to flush or wrap.
439bf215546Sopenharmony_ci       */
440bf215546Sopenharmony_ci      for (i = newSize; i <= exec->vtx.attr[attr].size; i++)
441bf215546Sopenharmony_ci         exec->vtx.attrptr[attr][i-1] = id[i-1];
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      exec->vtx.attr[attr].active_size = newSize;
444bf215546Sopenharmony_ci   }
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci/**
449bf215546Sopenharmony_ci * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
450bf215546Sopenharmony_ci * It depends on a few things, including whether we're inside or outside
451bf215546Sopenharmony_ci * of glBegin/glEnd.
452bf215546Sopenharmony_ci */
453bf215546Sopenharmony_cistatic inline bool
454bf215546Sopenharmony_ciis_vertex_position(const struct gl_context *ctx, GLuint index)
455bf215546Sopenharmony_ci{
456bf215546Sopenharmony_ci   return (index == 0 &&
457bf215546Sopenharmony_ci           _mesa_attr_zero_aliases_vertex(ctx) &&
458bf215546Sopenharmony_ci           _mesa_inside_begin_end(ctx));
459bf215546Sopenharmony_ci}
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci/* Write a 64-bit value into a 32-bit pointer by preserving endianness. */
462bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN
463bf215546Sopenharmony_ci   #define SET_64BIT(dst32, u64) do { \
464bf215546Sopenharmony_ci         *(dst32)++ = (u64); \
465bf215546Sopenharmony_ci         *(dst32)++ = (uint64_t)(u64) >> 32; \
466bf215546Sopenharmony_ci      } while (0)
467bf215546Sopenharmony_ci#else
468bf215546Sopenharmony_ci   #define SET_64BIT(dst32, u64) do { \
469bf215546Sopenharmony_ci         *(dst32)++ = (uint64_t)(u64) >> 32; \
470bf215546Sopenharmony_ci         *(dst32)++ = (u64); \
471bf215546Sopenharmony_ci      } while (0)
472bf215546Sopenharmony_ci#endif
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci/**
476bf215546Sopenharmony_ci * This macro is used to implement all the glVertex, glColor, glTexCoord,
477bf215546Sopenharmony_ci * glVertexAttrib, etc functions.
478bf215546Sopenharmony_ci * \param A  VBO_ATTRIB_x attribute index
479bf215546Sopenharmony_ci * \param N  attribute size (1..4)
480bf215546Sopenharmony_ci * \param T  type (GL_FLOAT, GL_DOUBLE, GL_INT, GL_UNSIGNED_INT)
481bf215546Sopenharmony_ci * \param C  cast type (uint32_t or uint64_t)
482bf215546Sopenharmony_ci * \param V0, V1, v2, V3  attribute value
483bf215546Sopenharmony_ci */
484bf215546Sopenharmony_ci#define ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3)                     \
485bf215546Sopenharmony_cido {                                                                    \
486bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;             \
487bf215546Sopenharmony_ci   int sz = (sizeof(C) / sizeof(GLfloat));                              \
488bf215546Sopenharmony_ci                                                                        \
489bf215546Sopenharmony_ci   assert(sz == 1 || sz == 2);                                          \
490bf215546Sopenharmony_ci   /* store a copy of the attribute in exec except for glVertex */      \
491bf215546Sopenharmony_ci   if ((A) != 0) {                                                      \
492bf215546Sopenharmony_ci      /* Check if attribute size or type is changing. */                \
493bf215546Sopenharmony_ci      if (unlikely(exec->vtx.attr[A].active_size != N * sz ||           \
494bf215546Sopenharmony_ci                   exec->vtx.attr[A].type != T)) {                      \
495bf215546Sopenharmony_ci         vbo_exec_fixup_vertex(ctx, A, N * sz, T);                      \
496bf215546Sopenharmony_ci      }                                                                 \
497bf215546Sopenharmony_ci                                                                        \
498bf215546Sopenharmony_ci      C *dest = (C *)exec->vtx.attrptr[A];                              \
499bf215546Sopenharmony_ci      if (N>0) dest[0] = V0;                                            \
500bf215546Sopenharmony_ci      if (N>1) dest[1] = V1;                                            \
501bf215546Sopenharmony_ci      if (N>2) dest[2] = V2;                                            \
502bf215546Sopenharmony_ci      if (N>3) dest[3] = V3;                                            \
503bf215546Sopenharmony_ci      assert(exec->vtx.attr[A].type == T);                              \
504bf215546Sopenharmony_ci                                                                        \
505bf215546Sopenharmony_ci      /* we now have accumulated a per-vertex attribute */              \
506bf215546Sopenharmony_ci      ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;                    \
507bf215546Sopenharmony_ci   } else {                                                             \
508bf215546Sopenharmony_ci      /* This is a glVertex call */                                     \
509bf215546Sopenharmony_ci      int size = exec->vtx.attr[0].size;                                \
510bf215546Sopenharmony_ci                                                                        \
511bf215546Sopenharmony_ci      /* Check if attribute size or type is changing. */                \
512bf215546Sopenharmony_ci      if (unlikely(size < N * sz ||                                     \
513bf215546Sopenharmony_ci                   exec->vtx.attr[0].type != T)) {                      \
514bf215546Sopenharmony_ci         vbo_exec_wrap_upgrade_vertex(exec, 0, N * sz, T);              \
515bf215546Sopenharmony_ci      }                                                                 \
516bf215546Sopenharmony_ci                                                                        \
517bf215546Sopenharmony_ci      uint32_t *dst = (uint32_t *)exec->vtx.buffer_ptr;                 \
518bf215546Sopenharmony_ci      uint32_t *src = (uint32_t *)exec->vtx.vertex;                     \
519bf215546Sopenharmony_ci      unsigned vertex_size_no_pos = exec->vtx.vertex_size_no_pos;       \
520bf215546Sopenharmony_ci                                                                        \
521bf215546Sopenharmony_ci      /* Copy over attributes from exec. */                             \
522bf215546Sopenharmony_ci      for (unsigned i = 0; i < vertex_size_no_pos; i++)                 \
523bf215546Sopenharmony_ci         *dst++ = *src++;                                               \
524bf215546Sopenharmony_ci                                                                        \
525bf215546Sopenharmony_ci      /* Store the position, which is always last and can have 32 or */ \
526bf215546Sopenharmony_ci      /* 64 bits per channel. */                                        \
527bf215546Sopenharmony_ci      if (sizeof(C) == 4) {                                             \
528bf215546Sopenharmony_ci         if (N > 0) *dst++ = V0;                                        \
529bf215546Sopenharmony_ci         if (N > 1) *dst++ = V1;                                        \
530bf215546Sopenharmony_ci         if (N > 2) *dst++ = V2;                                        \
531bf215546Sopenharmony_ci         if (N > 3) *dst++ = V3;                                        \
532bf215546Sopenharmony_ci                                                                        \
533bf215546Sopenharmony_ci         if (unlikely(N < size)) {                                      \
534bf215546Sopenharmony_ci            if (N < 2 && size >= 2) *dst++ = V1;                        \
535bf215546Sopenharmony_ci            if (N < 3 && size >= 3) *dst++ = V2;                        \
536bf215546Sopenharmony_ci            if (N < 4 && size >= 4) *dst++ = V3;                        \
537bf215546Sopenharmony_ci         }                                                              \
538bf215546Sopenharmony_ci      } else {                                                          \
539bf215546Sopenharmony_ci         /* 64 bits: dst can be unaligned, so copy each 4-byte word */  \
540bf215546Sopenharmony_ci         /* separately */                                               \
541bf215546Sopenharmony_ci         if (N > 0) SET_64BIT(dst, V0);                                 \
542bf215546Sopenharmony_ci         if (N > 1) SET_64BIT(dst, V1);                                 \
543bf215546Sopenharmony_ci         if (N > 2) SET_64BIT(dst, V2);                                 \
544bf215546Sopenharmony_ci         if (N > 3) SET_64BIT(dst, V3);                                 \
545bf215546Sopenharmony_ci                                                                        \
546bf215546Sopenharmony_ci         if (unlikely(N * 2 < size)) {                                  \
547bf215546Sopenharmony_ci            if (N < 2 && size >= 4) SET_64BIT(dst, V1);                 \
548bf215546Sopenharmony_ci            if (N < 3 && size >= 6) SET_64BIT(dst, V2);                 \
549bf215546Sopenharmony_ci            if (N < 4 && size >= 8) SET_64BIT(dst, V3);                 \
550bf215546Sopenharmony_ci         }                                                              \
551bf215546Sopenharmony_ci      }                                                                 \
552bf215546Sopenharmony_ci                                                                        \
553bf215546Sopenharmony_ci      /* dst now points at the beginning of the next vertex */          \
554bf215546Sopenharmony_ci      exec->vtx.buffer_ptr = (fi_type*)dst;                             \
555bf215546Sopenharmony_ci                                                                        \
556bf215546Sopenharmony_ci      /* Don't set FLUSH_UPDATE_CURRENT because */                      \
557bf215546Sopenharmony_ci      /* Current.Attrib[VBO_ATTRIB_POS] is never used. */               \
558bf215546Sopenharmony_ci                                                                        \
559bf215546Sopenharmony_ci      if (unlikely(++exec->vtx.vert_count >= exec->vtx.max_vert))       \
560bf215546Sopenharmony_ci         vbo_exec_vtx_wrap(exec);                                       \
561bf215546Sopenharmony_ci   }                                                                    \
562bf215546Sopenharmony_ci} while (0)
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci#undef ERROR
565bf215546Sopenharmony_ci#define ERROR(err) _mesa_error(ctx, err, __func__)
566bf215546Sopenharmony_ci#define TAG(x) _mesa_##x
567bf215546Sopenharmony_ci#define SUPPRESS_STATIC
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
570bf215546Sopenharmony_ci   ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3)
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci#include "vbo_attrib_tmp.h"
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_ci/**
576bf215546Sopenharmony_ci * Execute a glMaterial call.  Note that if GL_COLOR_MATERIAL is enabled,
577bf215546Sopenharmony_ci * this may be a (partial) no-op.
578bf215546Sopenharmony_ci */
579bf215546Sopenharmony_civoid GLAPIENTRY
580bf215546Sopenharmony_ci_mesa_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
581bf215546Sopenharmony_ci{
582bf215546Sopenharmony_ci   GLbitfield updateMats;
583bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   /* This function should be a no-op when it tries to update material
586bf215546Sopenharmony_ci    * attributes which are currently tracking glColor via glColorMaterial.
587bf215546Sopenharmony_ci    * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
588bf215546Sopenharmony_ci    * indicating which material attributes can actually be updated below.
589bf215546Sopenharmony_ci    */
590bf215546Sopenharmony_ci   if (ctx->Light.ColorMaterialEnabled) {
591bf215546Sopenharmony_ci      updateMats = ~ctx->Light._ColorMaterialBitmask;
592bf215546Sopenharmony_ci   }
593bf215546Sopenharmony_ci   else {
594bf215546Sopenharmony_ci      /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
595bf215546Sopenharmony_ci      updateMats = ALL_MATERIAL_BITS;
596bf215546Sopenharmony_ci   }
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
599bf215546Sopenharmony_ci      updateMats &= FRONT_MATERIAL_BITS;
600bf215546Sopenharmony_ci   }
601bf215546Sopenharmony_ci   else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
602bf215546Sopenharmony_ci      updateMats &= BACK_MATERIAL_BITS;
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci   else if (face != GL_FRONT_AND_BACK) {
605bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
606bf215546Sopenharmony_ci      return;
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   switch (pname) {
610bf215546Sopenharmony_ci   case GL_EMISSION:
611bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_EMISSION)
612bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
613bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_EMISSION)
614bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
615bf215546Sopenharmony_ci      break;
616bf215546Sopenharmony_ci   case GL_AMBIENT:
617bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_AMBIENT)
618bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
619bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_AMBIENT)
620bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
621bf215546Sopenharmony_ci      break;
622bf215546Sopenharmony_ci   case GL_DIFFUSE:
623bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_DIFFUSE)
624bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
625bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_DIFFUSE)
626bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
627bf215546Sopenharmony_ci      break;
628bf215546Sopenharmony_ci   case GL_SPECULAR:
629bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_SPECULAR)
630bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
631bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_SPECULAR)
632bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
633bf215546Sopenharmony_ci      break;
634bf215546Sopenharmony_ci   case GL_SHININESS:
635bf215546Sopenharmony_ci      if (*params < 0 || *params > ctx->Const.MaxShininess) {
636bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_VALUE,
637bf215546Sopenharmony_ci                     "glMaterial(invalid shininess: %f out range [0, %f])",
638bf215546Sopenharmony_ci                     *params, ctx->Const.MaxShininess);
639bf215546Sopenharmony_ci         return;
640bf215546Sopenharmony_ci      }
641bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_SHININESS)
642bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
643bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_SHININESS)
644bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
645bf215546Sopenharmony_ci      break;
646bf215546Sopenharmony_ci   case GL_COLOR_INDEXES:
647bf215546Sopenharmony_ci      if (ctx->API != API_OPENGL_COMPAT) {
648bf215546Sopenharmony_ci         _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
649bf215546Sopenharmony_ci         return;
650bf215546Sopenharmony_ci      }
651bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_INDEXES)
652bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
653bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_INDEXES)
654bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
655bf215546Sopenharmony_ci      break;
656bf215546Sopenharmony_ci   case GL_AMBIENT_AND_DIFFUSE:
657bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_AMBIENT)
658bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
659bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_FRONT_DIFFUSE)
660bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
661bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_AMBIENT)
662bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
663bf215546Sopenharmony_ci      if (updateMats & MAT_BIT_BACK_DIFFUSE)
664bf215546Sopenharmony_ci         MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
665bf215546Sopenharmony_ci      break;
666bf215546Sopenharmony_ci   default:
667bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
668bf215546Sopenharmony_ci      return;
669bf215546Sopenharmony_ci   }
670bf215546Sopenharmony_ci}
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci/**
674bf215546Sopenharmony_ci * Flush (draw) vertices.
675bf215546Sopenharmony_ci *
676bf215546Sopenharmony_ci * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
677bf215546Sopenharmony_ci */
678bf215546Sopenharmony_cistatic void
679bf215546Sopenharmony_civbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, unsigned flags)
680bf215546Sopenharmony_ci{
681bf215546Sopenharmony_ci   struct gl_context *ctx = gl_context_from_vbo_exec(exec);
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_ci   if (flags & FLUSH_STORED_VERTICES) {
684bf215546Sopenharmony_ci      if (exec->vtx.vert_count) {
685bf215546Sopenharmony_ci         vbo_exec_vtx_flush(exec);
686bf215546Sopenharmony_ci      }
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci      if (exec->vtx.vertex_size) {
689bf215546Sopenharmony_ci         vbo_exec_copy_to_current(exec);
690bf215546Sopenharmony_ci         vbo_reset_all_attr(exec);
691bf215546Sopenharmony_ci      }
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci      /* All done. */
694bf215546Sopenharmony_ci      ctx->Driver.NeedFlush = 0;
695bf215546Sopenharmony_ci   } else {
696bf215546Sopenharmony_ci      assert(flags == FLUSH_UPDATE_CURRENT);
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci      /* Note that the vertex size is unchanged.
699bf215546Sopenharmony_ci       * (vbo_reset_all_attr isn't called)
700bf215546Sopenharmony_ci       */
701bf215546Sopenharmony_ci      vbo_exec_copy_to_current(exec);
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci      /* Only FLUSH_UPDATE_CURRENT is done. */
704bf215546Sopenharmony_ci      ctx->Driver.NeedFlush = ~FLUSH_UPDATE_CURRENT;
705bf215546Sopenharmony_ci   }
706bf215546Sopenharmony_ci}
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_civoid GLAPIENTRY
710bf215546Sopenharmony_ci_mesa_EvalCoord1f(GLfloat u)
711bf215546Sopenharmony_ci{
712bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
713bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci   {
716bf215546Sopenharmony_ci      GLint i;
717bf215546Sopenharmony_ci      if (exec->eval.recalculate_maps)
718bf215546Sopenharmony_ci         vbo_exec_eval_update(exec);
719bf215546Sopenharmony_ci
720bf215546Sopenharmony_ci      for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
721bf215546Sopenharmony_ci         if (exec->eval.map1[i].map)
722bf215546Sopenharmony_ci            if (exec->vtx.attr[i].active_size != exec->eval.map1[i].sz)
723bf215546Sopenharmony_ci               vbo_exec_fixup_vertex(ctx, i, exec->eval.map1[i].sz, GL_FLOAT);
724bf215546Sopenharmony_ci      }
725bf215546Sopenharmony_ci   }
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
728bf215546Sopenharmony_ci          exec->vtx.vertex_size * sizeof(GLfloat));
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci   vbo_exec_do_EvalCoord1f(exec, u);
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_ci   memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
733bf215546Sopenharmony_ci          exec->vtx.vertex_size * sizeof(GLfloat));
734bf215546Sopenharmony_ci}
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_civoid GLAPIENTRY
738bf215546Sopenharmony_ci_mesa_EvalCoord2f(GLfloat u, GLfloat v)
739bf215546Sopenharmony_ci{
740bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
741bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
742bf215546Sopenharmony_ci
743bf215546Sopenharmony_ci   {
744bf215546Sopenharmony_ci      GLint i;
745bf215546Sopenharmony_ci      if (exec->eval.recalculate_maps)
746bf215546Sopenharmony_ci         vbo_exec_eval_update(exec);
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci      for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
749bf215546Sopenharmony_ci         if (exec->eval.map2[i].map)
750bf215546Sopenharmony_ci            if (exec->vtx.attr[i].active_size != exec->eval.map2[i].sz)
751bf215546Sopenharmony_ci               vbo_exec_fixup_vertex(ctx, i, exec->eval.map2[i].sz, GL_FLOAT);
752bf215546Sopenharmony_ci      }
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci      if (ctx->Eval.AutoNormal)
755bf215546Sopenharmony_ci         if (exec->vtx.attr[VBO_ATTRIB_NORMAL].active_size != 3)
756bf215546Sopenharmony_ci            vbo_exec_fixup_vertex(ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT);
757bf215546Sopenharmony_ci   }
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci   memcpy(exec->vtx.copied.buffer, exec->vtx.vertex,
760bf215546Sopenharmony_ci          exec->vtx.vertex_size * sizeof(GLfloat));
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_ci   vbo_exec_do_EvalCoord2f(exec, u, v);
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   memcpy(exec->vtx.vertex, exec->vtx.copied.buffer,
765bf215546Sopenharmony_ci          exec->vtx.vertex_size * sizeof(GLfloat));
766bf215546Sopenharmony_ci}
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_civoid GLAPIENTRY
770bf215546Sopenharmony_ci_mesa_EvalCoord1fv(const GLfloat *u)
771bf215546Sopenharmony_ci{
772bf215546Sopenharmony_ci   _mesa_EvalCoord1f(u[0]);
773bf215546Sopenharmony_ci}
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_civoid GLAPIENTRY
777bf215546Sopenharmony_ci_mesa_EvalCoord2fv(const GLfloat *u)
778bf215546Sopenharmony_ci{
779bf215546Sopenharmony_ci   _mesa_EvalCoord2f(u[0], u[1]);
780bf215546Sopenharmony_ci}
781bf215546Sopenharmony_ci
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_civoid GLAPIENTRY
784bf215546Sopenharmony_ci_mesa_EvalPoint1(GLint i)
785bf215546Sopenharmony_ci{
786bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
787bf215546Sopenharmony_ci   GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
788bf215546Sopenharmony_ci                 (GLfloat) ctx->Eval.MapGrid1un);
789bf215546Sopenharmony_ci   GLfloat u = i * du + ctx->Eval.MapGrid1u1;
790bf215546Sopenharmony_ci
791bf215546Sopenharmony_ci   _mesa_EvalCoord1f(u);
792bf215546Sopenharmony_ci}
793bf215546Sopenharmony_ci
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_civoid GLAPIENTRY
796bf215546Sopenharmony_ci_mesa_EvalPoint2(GLint i, GLint j)
797bf215546Sopenharmony_ci{
798bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
799bf215546Sopenharmony_ci   GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
800bf215546Sopenharmony_ci                 (GLfloat) ctx->Eval.MapGrid2un);
801bf215546Sopenharmony_ci   GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
802bf215546Sopenharmony_ci                 (GLfloat) ctx->Eval.MapGrid2vn);
803bf215546Sopenharmony_ci   GLfloat u = i * du + ctx->Eval.MapGrid2u1;
804bf215546Sopenharmony_ci   GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_ci   _mesa_EvalCoord2f(u, v);
807bf215546Sopenharmony_ci}
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci/**
811bf215546Sopenharmony_ci * Called via glBegin.
812bf215546Sopenharmony_ci */
813bf215546Sopenharmony_civoid GLAPIENTRY
814bf215546Sopenharmony_ci_mesa_Begin(GLenum mode)
815bf215546Sopenharmony_ci{
816bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
817bf215546Sopenharmony_ci   struct vbo_context *vbo = vbo_context(ctx);
818bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo->exec;
819bf215546Sopenharmony_ci   int i;
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci   if (_mesa_inside_begin_end(ctx)) {
822bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin");
823bf215546Sopenharmony_ci      return;
824bf215546Sopenharmony_ci   }
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci   if (ctx->NewState)
827bf215546Sopenharmony_ci      _mesa_update_state(ctx);
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci   GLenum error = _mesa_valid_prim_mode(ctx, mode);
830bf215546Sopenharmony_ci   if (error != GL_NO_ERROR) {
831bf215546Sopenharmony_ci      _mesa_error(ctx, error, "glBegin");
832bf215546Sopenharmony_ci      return;
833bf215546Sopenharmony_ci   }
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   /* Heuristic: attempt to isolate attributes occurring outside
836bf215546Sopenharmony_ci    * begin/end pairs.
837bf215546Sopenharmony_ci    *
838bf215546Sopenharmony_ci    * Use FLUSH_STORED_VERTICES, because it updates current attribs and
839bf215546Sopenharmony_ci    * sets vertex_size to 0. (FLUSH_UPDATE_CURRENT doesn't change vertex_size)
840bf215546Sopenharmony_ci    */
841bf215546Sopenharmony_ci   if (exec->vtx.vertex_size && !exec->vtx.attr[VBO_ATTRIB_POS].size)
842bf215546Sopenharmony_ci      vbo_exec_FlushVertices_internal(exec, FLUSH_STORED_VERTICES);
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci   i = exec->vtx.prim_count++;
845bf215546Sopenharmony_ci   exec->vtx.mode[i] = mode;
846bf215546Sopenharmony_ci   exec->vtx.draw[i].start = exec->vtx.vert_count;
847bf215546Sopenharmony_ci   exec->vtx.markers[i].begin = 1;
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ci   ctx->Driver.CurrentExecPrimitive = mode;
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci   ctx->Exec = _mesa_hw_select_enabled(ctx) ?
852bf215546Sopenharmony_ci      ctx->HWSelectModeBeginEnd : ctx->BeginEnd;
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   /* We may have been called from a display list, in which case we should
855bf215546Sopenharmony_ci    * leave dlist.c's dispatch table in place.
856bf215546Sopenharmony_ci    */
857bf215546Sopenharmony_ci   if (ctx->GLThread.enabled) {
858bf215546Sopenharmony_ci      if (ctx->CurrentServerDispatch == ctx->OutsideBeginEnd)
859bf215546Sopenharmony_ci         ctx->CurrentServerDispatch = ctx->Exec;
860bf215546Sopenharmony_ci   } else if (ctx->CurrentClientDispatch == ctx->OutsideBeginEnd) {
861bf215546Sopenharmony_ci      ctx->CurrentClientDispatch = ctx->CurrentServerDispatch = ctx->Exec;
862bf215546Sopenharmony_ci      _glapi_set_dispatch(ctx->CurrentClientDispatch);
863bf215546Sopenharmony_ci   } else {
864bf215546Sopenharmony_ci      assert(ctx->CurrentClientDispatch == ctx->Save);
865bf215546Sopenharmony_ci   }
866bf215546Sopenharmony_ci}
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci
869bf215546Sopenharmony_ci/**
870bf215546Sopenharmony_ci * Try to merge / concatenate the two most recent VBO primitives.
871bf215546Sopenharmony_ci */
872bf215546Sopenharmony_cistatic void
873bf215546Sopenharmony_citry_vbo_merge(struct vbo_exec_context *exec)
874bf215546Sopenharmony_ci{
875bf215546Sopenharmony_ci   unsigned cur = exec->vtx.prim_count - 1;
876bf215546Sopenharmony_ci
877bf215546Sopenharmony_ci   assert(exec->vtx.prim_count >= 1);
878bf215546Sopenharmony_ci
879bf215546Sopenharmony_ci   vbo_try_prim_conversion(&exec->vtx.mode[cur], &exec->vtx.draw[cur].count);
880bf215546Sopenharmony_ci
881bf215546Sopenharmony_ci   if (exec->vtx.prim_count >= 2) {
882bf215546Sopenharmony_ci      struct gl_context *ctx = gl_context_from_vbo_exec(exec);
883bf215546Sopenharmony_ci      unsigned prev = cur - 1;
884bf215546Sopenharmony_ci
885bf215546Sopenharmony_ci      if (vbo_merge_draws(ctx, false,
886bf215546Sopenharmony_ci                          exec->vtx.mode[prev],
887bf215546Sopenharmony_ci                          exec->vtx.mode[cur],
888bf215546Sopenharmony_ci                          exec->vtx.draw[prev].start,
889bf215546Sopenharmony_ci                          exec->vtx.draw[cur].start,
890bf215546Sopenharmony_ci                          &exec->vtx.draw[prev].count,
891bf215546Sopenharmony_ci                          exec->vtx.draw[cur].count,
892bf215546Sopenharmony_ci                          0, 0,
893bf215546Sopenharmony_ci                          &exec->vtx.markers[prev].end,
894bf215546Sopenharmony_ci                          exec->vtx.markers[cur].begin,
895bf215546Sopenharmony_ci                          exec->vtx.markers[cur].end))
896bf215546Sopenharmony_ci         exec->vtx.prim_count--;  /* drop the last primitive */
897bf215546Sopenharmony_ci   }
898bf215546Sopenharmony_ci}
899bf215546Sopenharmony_ci
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci/**
902bf215546Sopenharmony_ci * Called via glEnd.
903bf215546Sopenharmony_ci */
904bf215546Sopenharmony_civoid GLAPIENTRY
905bf215546Sopenharmony_ci_mesa_End(void)
906bf215546Sopenharmony_ci{
907bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
908bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_ci   if (!_mesa_inside_begin_end(ctx)) {
911bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd");
912bf215546Sopenharmony_ci      return;
913bf215546Sopenharmony_ci   }
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci   ctx->Exec = ctx->OutsideBeginEnd;
916bf215546Sopenharmony_ci
917bf215546Sopenharmony_ci   if (ctx->GLThread.enabled) {
918bf215546Sopenharmony_ci      if (ctx->CurrentServerDispatch == ctx->BeginEnd ||
919bf215546Sopenharmony_ci          ctx->CurrentServerDispatch == ctx->HWSelectModeBeginEnd) {
920bf215546Sopenharmony_ci         ctx->CurrentServerDispatch = ctx->Exec;
921bf215546Sopenharmony_ci      }
922bf215546Sopenharmony_ci   } else if (ctx->CurrentClientDispatch == ctx->BeginEnd ||
923bf215546Sopenharmony_ci              ctx->CurrentClientDispatch == ctx->HWSelectModeBeginEnd) {
924bf215546Sopenharmony_ci      ctx->CurrentClientDispatch = ctx->CurrentServerDispatch = ctx->Exec;
925bf215546Sopenharmony_ci      _glapi_set_dispatch(ctx->CurrentClientDispatch);
926bf215546Sopenharmony_ci   }
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   if (exec->vtx.prim_count > 0) {
929bf215546Sopenharmony_ci      /* close off current primitive */
930bf215546Sopenharmony_ci      unsigned last = exec->vtx.prim_count - 1;
931bf215546Sopenharmony_ci      struct pipe_draw_start_count_bias *last_draw = &exec->vtx.draw[last];
932bf215546Sopenharmony_ci      unsigned count = exec->vtx.vert_count - last_draw->start;
933bf215546Sopenharmony_ci
934bf215546Sopenharmony_ci      last_draw->count = count;
935bf215546Sopenharmony_ci      exec->vtx.markers[last].end = 1;
936bf215546Sopenharmony_ci
937bf215546Sopenharmony_ci      if (count) {
938bf215546Sopenharmony_ci         /* mark result buffer used */
939bf215546Sopenharmony_ci         if (_mesa_hw_select_enabled(ctx))
940bf215546Sopenharmony_ci            ctx->Select.ResultUsed = GL_TRUE;
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_ci         ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
943bf215546Sopenharmony_ci      }
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_ci      /* Special handling for GL_LINE_LOOP */
946bf215546Sopenharmony_ci      if (exec->vtx.mode[last] == GL_LINE_LOOP &&
947bf215546Sopenharmony_ci          exec->vtx.markers[last].begin == 0) {
948bf215546Sopenharmony_ci         /* We're finishing drawing a line loop.  Append 0th vertex onto
949bf215546Sopenharmony_ci          * end of vertex buffer so we can draw it as a line strip.
950bf215546Sopenharmony_ci          */
951bf215546Sopenharmony_ci         const fi_type *src = exec->vtx.buffer_map +
952bf215546Sopenharmony_ci            last_draw->start * exec->vtx.vertex_size;
953bf215546Sopenharmony_ci         fi_type *dst = exec->vtx.buffer_map +
954bf215546Sopenharmony_ci            exec->vtx.vert_count * exec->vtx.vertex_size;
955bf215546Sopenharmony_ci
956bf215546Sopenharmony_ci         /* copy 0th vertex to end of buffer */
957bf215546Sopenharmony_ci         memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type));
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_ci         last_draw->start++;  /* skip vertex0 */
960bf215546Sopenharmony_ci         /* note that the count stays unchanged */
961bf215546Sopenharmony_ci         exec->vtx.mode[last] = GL_LINE_STRIP;
962bf215546Sopenharmony_ci
963bf215546Sopenharmony_ci         /* Increment the vertex count so the next primitive doesn't
964bf215546Sopenharmony_ci          * overwrite the last vertex which we just added.
965bf215546Sopenharmony_ci          */
966bf215546Sopenharmony_ci         exec->vtx.vert_count++;
967bf215546Sopenharmony_ci         exec->vtx.buffer_ptr += exec->vtx.vertex_size;
968bf215546Sopenharmony_ci      }
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci      try_vbo_merge(exec);
971bf215546Sopenharmony_ci   }
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci   ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci   if (exec->vtx.prim_count == VBO_MAX_PRIM)
976bf215546Sopenharmony_ci      vbo_exec_vtx_flush(exec);
977bf215546Sopenharmony_ci
978bf215546Sopenharmony_ci   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
979bf215546Sopenharmony_ci      _mesa_flush(ctx);
980bf215546Sopenharmony_ci   }
981bf215546Sopenharmony_ci}
982bf215546Sopenharmony_ci
983bf215546Sopenharmony_ci
984bf215546Sopenharmony_ci/**
985bf215546Sopenharmony_ci * Called via glPrimitiveRestartNV()
986bf215546Sopenharmony_ci */
987bf215546Sopenharmony_civoid GLAPIENTRY
988bf215546Sopenharmony_ci_mesa_PrimitiveRestartNV(void)
989bf215546Sopenharmony_ci{
990bf215546Sopenharmony_ci   GLenum curPrim;
991bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
992bf215546Sopenharmony_ci
993bf215546Sopenharmony_ci   curPrim = ctx->Driver.CurrentExecPrimitive;
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ci   if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
996bf215546Sopenharmony_ci      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV");
997bf215546Sopenharmony_ci   }
998bf215546Sopenharmony_ci   else {
999bf215546Sopenharmony_ci      _mesa_End();
1000bf215546Sopenharmony_ci      _mesa_Begin(curPrim);
1001bf215546Sopenharmony_ci   }
1002bf215546Sopenharmony_ci}
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci/**
1006bf215546Sopenharmony_ci * A special version of glVertexAttrib4f that does not treat index 0 as
1007bf215546Sopenharmony_ci * VBO_ATTRIB_POS.
1008bf215546Sopenharmony_ci */
1009bf215546Sopenharmony_cistatic void
1010bf215546Sopenharmony_ciVertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1011bf215546Sopenharmony_ci{
1012bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
1013bf215546Sopenharmony_ci   if (index < ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs)
1014bf215546Sopenharmony_ci      ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
1015bf215546Sopenharmony_ci   else
1016bf215546Sopenharmony_ci      ERROR(GL_INVALID_VALUE);
1017bf215546Sopenharmony_ci}
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_cistatic void GLAPIENTRY
1020bf215546Sopenharmony_ci_es_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1021bf215546Sopenharmony_ci{
1022bf215546Sopenharmony_ci   VertexAttrib4f_nopos(index, x, y, z, w);
1023bf215546Sopenharmony_ci}
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_cistatic void GLAPIENTRY
1027bf215546Sopenharmony_ci_es_VertexAttrib1fARB(GLuint indx, GLfloat x)
1028bf215546Sopenharmony_ci{
1029bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
1030bf215546Sopenharmony_ci}
1031bf215546Sopenharmony_ci
1032bf215546Sopenharmony_ci
1033bf215546Sopenharmony_cistatic void GLAPIENTRY
1034bf215546Sopenharmony_ci_es_VertexAttrib1fvARB(GLuint indx, const GLfloat* values)
1035bf215546Sopenharmony_ci{
1036bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
1037bf215546Sopenharmony_ci}
1038bf215546Sopenharmony_ci
1039bf215546Sopenharmony_ci
1040bf215546Sopenharmony_cistatic void GLAPIENTRY
1041bf215546Sopenharmony_ci_es_VertexAttrib2fARB(GLuint indx, GLfloat x, GLfloat y)
1042bf215546Sopenharmony_ci{
1043bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
1044bf215546Sopenharmony_ci}
1045bf215546Sopenharmony_ci
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_cistatic void GLAPIENTRY
1048bf215546Sopenharmony_ci_es_VertexAttrib2fvARB(GLuint indx, const GLfloat* values)
1049bf215546Sopenharmony_ci{
1050bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
1051bf215546Sopenharmony_ci}
1052bf215546Sopenharmony_ci
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_cistatic void GLAPIENTRY
1055bf215546Sopenharmony_ci_es_VertexAttrib3fARB(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
1056bf215546Sopenharmony_ci{
1057bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
1058bf215546Sopenharmony_ci}
1059bf215546Sopenharmony_ci
1060bf215546Sopenharmony_ci
1061bf215546Sopenharmony_cistatic void GLAPIENTRY
1062bf215546Sopenharmony_ci_es_VertexAttrib3fvARB(GLuint indx, const GLfloat* values)
1063bf215546Sopenharmony_ci{
1064bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
1065bf215546Sopenharmony_ci}
1066bf215546Sopenharmony_ci
1067bf215546Sopenharmony_ci
1068bf215546Sopenharmony_cistatic void GLAPIENTRY
1069bf215546Sopenharmony_ci_es_VertexAttrib4fvARB(GLuint indx, const GLfloat* values)
1070bf215546Sopenharmony_ci{
1071bf215546Sopenharmony_ci   VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
1072bf215546Sopenharmony_ci}
1073bf215546Sopenharmony_ci
1074bf215546Sopenharmony_ci
1075bf215546Sopenharmony_civoid
1076bf215546Sopenharmony_civbo_install_exec_vtxfmt(struct gl_context *ctx)
1077bf215546Sopenharmony_ci{
1078bf215546Sopenharmony_ci#define NAME_AE(x) _mesa_##x
1079bf215546Sopenharmony_ci#define NAME_CALLLIST(x) _mesa_##x
1080bf215546Sopenharmony_ci#define NAME(x) _mesa_##x
1081bf215546Sopenharmony_ci#define NAME_ES(x) _es_##x
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ci   struct _glapi_table *tab = ctx->Exec;
1084bf215546Sopenharmony_ci   #include "api_vtxfmt_init.h"
1085bf215546Sopenharmony_ci
1086bf215546Sopenharmony_ci   if (ctx->BeginEnd) {
1087bf215546Sopenharmony_ci      tab = ctx->BeginEnd;
1088bf215546Sopenharmony_ci      #include "api_vtxfmt_init.h"
1089bf215546Sopenharmony_ci   }
1090bf215546Sopenharmony_ci}
1091bf215546Sopenharmony_ci
1092bf215546Sopenharmony_ci
1093bf215546Sopenharmony_cistatic void
1094bf215546Sopenharmony_civbo_reset_all_attr(struct vbo_exec_context *exec)
1095bf215546Sopenharmony_ci{
1096bf215546Sopenharmony_ci   while (exec->vtx.enabled) {
1097bf215546Sopenharmony_ci      const int i = u_bit_scan64(&exec->vtx.enabled);
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_ci      /* Reset the vertex attribute by setting its size to zero. */
1100bf215546Sopenharmony_ci      exec->vtx.attr[i].size = 0;
1101bf215546Sopenharmony_ci      exec->vtx.attr[i].type = GL_FLOAT;
1102bf215546Sopenharmony_ci      exec->vtx.attr[i].active_size = 0;
1103bf215546Sopenharmony_ci      exec->vtx.attrptr[i] = NULL;
1104bf215546Sopenharmony_ci   }
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_ci   exec->vtx.vertex_size = 0;
1107bf215546Sopenharmony_ci}
1108bf215546Sopenharmony_ci
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_civoid
1111bf215546Sopenharmony_civbo_exec_vtx_init(struct vbo_exec_context *exec)
1112bf215546Sopenharmony_ci{
1113bf215546Sopenharmony_ci   struct gl_context *ctx = gl_context_from_vbo_exec(exec);
1114bf215546Sopenharmony_ci
1115bf215546Sopenharmony_ci   exec->vtx.bufferobj = _mesa_bufferobj_alloc(ctx, IMM_BUFFER_NAME);
1116bf215546Sopenharmony_ci
1117bf215546Sopenharmony_ci   exec->vtx.enabled = u_bit_consecutive64(0, VBO_ATTRIB_MAX); /* reset all */
1118bf215546Sopenharmony_ci   vbo_reset_all_attr(exec);
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci   exec->vtx.info.instance_count = 1;
1121bf215546Sopenharmony_ci   exec->vtx.info.max_index = ~0;
1122bf215546Sopenharmony_ci}
1123bf215546Sopenharmony_ci
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_civoid
1126bf215546Sopenharmony_civbo_exec_vtx_destroy(struct vbo_exec_context *exec)
1127bf215546Sopenharmony_ci{
1128bf215546Sopenharmony_ci   /* using a real VBO for vertex data */
1129bf215546Sopenharmony_ci   struct gl_context *ctx = gl_context_from_vbo_exec(exec);
1130bf215546Sopenharmony_ci
1131bf215546Sopenharmony_ci   /* True VBOs should already be unmapped
1132bf215546Sopenharmony_ci    */
1133bf215546Sopenharmony_ci   if (exec->vtx.buffer_map) {
1134bf215546Sopenharmony_ci      assert(!exec->vtx.bufferobj ||
1135bf215546Sopenharmony_ci             exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
1136bf215546Sopenharmony_ci      if (!exec->vtx.bufferobj) {
1137bf215546Sopenharmony_ci         align_free(exec->vtx.buffer_map);
1138bf215546Sopenharmony_ci         exec->vtx.buffer_map = NULL;
1139bf215546Sopenharmony_ci         exec->vtx.buffer_ptr = NULL;
1140bf215546Sopenharmony_ci      }
1141bf215546Sopenharmony_ci   }
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   /* Free the vertex buffer.  Unmap first if needed.
1144bf215546Sopenharmony_ci    */
1145bf215546Sopenharmony_ci   if (exec->vtx.bufferobj &&
1146bf215546Sopenharmony_ci       _mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
1147bf215546Sopenharmony_ci      _mesa_bufferobj_unmap(ctx, exec->vtx.bufferobj, MAP_INTERNAL);
1148bf215546Sopenharmony_ci   }
1149bf215546Sopenharmony_ci   _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
1150bf215546Sopenharmony_ci}
1151bf215546Sopenharmony_ci
1152bf215546Sopenharmony_ci
1153bf215546Sopenharmony_ci/**
1154bf215546Sopenharmony_ci * If inside glBegin()/glEnd(), it should assert(0).  Otherwise, if
1155bf215546Sopenharmony_ci * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
1156bf215546Sopenharmony_ci * vertices, if FLUSH_UPDATE_CURRENT bit is set updates
1157bf215546Sopenharmony_ci * __struct gl_contextRec::Current and gl_light_attrib::Material
1158bf215546Sopenharmony_ci *
1159bf215546Sopenharmony_ci * Note that the default T&L engine never clears the
1160bf215546Sopenharmony_ci * FLUSH_UPDATE_CURRENT bit, even after performing the update.
1161bf215546Sopenharmony_ci *
1162bf215546Sopenharmony_ci * \param flags  bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
1163bf215546Sopenharmony_ci */
1164bf215546Sopenharmony_civoid
1165bf215546Sopenharmony_civbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags)
1166bf215546Sopenharmony_ci{
1167bf215546Sopenharmony_ci   struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
1168bf215546Sopenharmony_ci
1169bf215546Sopenharmony_ci#ifndef NDEBUG
1170bf215546Sopenharmony_ci   /* debug check: make sure we don't get called recursively */
1171bf215546Sopenharmony_ci   exec->flush_call_depth++;
1172bf215546Sopenharmony_ci   assert(exec->flush_call_depth == 1);
1173bf215546Sopenharmony_ci#endif
1174bf215546Sopenharmony_ci
1175bf215546Sopenharmony_ci   if (_mesa_inside_begin_end(ctx)) {
1176bf215546Sopenharmony_ci      /* We've had glBegin but not glEnd! */
1177bf215546Sopenharmony_ci#ifndef NDEBUG
1178bf215546Sopenharmony_ci      exec->flush_call_depth--;
1179bf215546Sopenharmony_ci      assert(exec->flush_call_depth == 0);
1180bf215546Sopenharmony_ci#endif
1181bf215546Sopenharmony_ci      return;
1182bf215546Sopenharmony_ci   }
1183bf215546Sopenharmony_ci
1184bf215546Sopenharmony_ci   /* Flush (draw). */
1185bf215546Sopenharmony_ci   vbo_exec_FlushVertices_internal(exec, flags);
1186bf215546Sopenharmony_ci
1187bf215546Sopenharmony_ci#ifndef NDEBUG
1188bf215546Sopenharmony_ci   exec->flush_call_depth--;
1189bf215546Sopenharmony_ci   assert(exec->flush_call_depth == 0);
1190bf215546Sopenharmony_ci#endif
1191bf215546Sopenharmony_ci}
1192bf215546Sopenharmony_ci
1193bf215546Sopenharmony_ci
1194bf215546Sopenharmony_civoid GLAPIENTRY
1195bf215546Sopenharmony_ci_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1196bf215546Sopenharmony_ci{
1197bf215546Sopenharmony_ci   _mesa_Color4f(r, g, b, a);
1198bf215546Sopenharmony_ci}
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_ci
1201bf215546Sopenharmony_civoid GLAPIENTRY
1202bf215546Sopenharmony_ci_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
1203bf215546Sopenharmony_ci{
1204bf215546Sopenharmony_ci   _mesa_Normal3f(x, y, z);
1205bf215546Sopenharmony_ci}
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_civoid GLAPIENTRY
1209bf215546Sopenharmony_ci_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1210bf215546Sopenharmony_ci{
1211bf215546Sopenharmony_ci   _mesa_MultiTexCoord4fARB(target, s, t, r, q);
1212bf215546Sopenharmony_ci}
1213bf215546Sopenharmony_ci
1214bf215546Sopenharmony_ci
1215bf215546Sopenharmony_civoid GLAPIENTRY
1216bf215546Sopenharmony_ci_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
1217bf215546Sopenharmony_ci{
1218bf215546Sopenharmony_ci   _mesa_Materialfv(face, pname, params);
1219bf215546Sopenharmony_ci}
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci
1222bf215546Sopenharmony_civoid GLAPIENTRY
1223bf215546Sopenharmony_ci_es_Materialf(GLenum face, GLenum pname, GLfloat param)
1224bf215546Sopenharmony_ci{
1225bf215546Sopenharmony_ci   GLfloat p[4];
1226bf215546Sopenharmony_ci   p[0] = param;
1227bf215546Sopenharmony_ci   p[1] = p[2] = p[3] = 0.0F;
1228bf215546Sopenharmony_ci   _mesa_Materialfv(face, pname, p);
1229bf215546Sopenharmony_ci}
1230bf215546Sopenharmony_ci
1231bf215546Sopenharmony_ci#undef TAG
1232bf215546Sopenharmony_ci#undef SUPPRESS_STATIC
1233bf215546Sopenharmony_ci#define TAG(x) _hw_select_##x
1234bf215546Sopenharmony_ci/* filter out none vertex api */
1235bf215546Sopenharmony_ci#define HW_SELECT_MODE
1236bf215546Sopenharmony_ci
1237bf215546Sopenharmony_ci#undef ATTR_UNION
1238bf215546Sopenharmony_ci#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3)     \
1239bf215546Sopenharmony_ci   do {                                            \
1240bf215546Sopenharmony_ci      if ((A) == 0) {                              \
1241bf215546Sopenharmony_ci         ATTR_UNION_BASE(VBO_ATTRIB_SELECT_RESULT_OFFSET, 1, GL_UNSIGNED_INT, uint32_t, \
1242bf215546Sopenharmony_ci                         ctx->Select.ResultOffset, 0, 0, 0); \
1243bf215546Sopenharmony_ci      }                                            \
1244bf215546Sopenharmony_ci      ATTR_UNION_BASE(A, N, T, C, V0, V1, V2, V3); \
1245bf215546Sopenharmony_ci   } while (0)
1246bf215546Sopenharmony_ci
1247bf215546Sopenharmony_ci#include "vbo_attrib_tmp.h"
1248bf215546Sopenharmony_ci
1249bf215546Sopenharmony_civoid
1250bf215546Sopenharmony_civbo_install_hw_select_begin_end(struct gl_context *ctx)
1251bf215546Sopenharmony_ci{
1252bf215546Sopenharmony_ci   int numEntries = MAX2(_gloffset_COUNT, _glapi_get_dispatch_table_size());
1253bf215546Sopenharmony_ci   memcpy(ctx->HWSelectModeBeginEnd, ctx->BeginEnd, numEntries * sizeof(_glapi_proc));
1254bf215546Sopenharmony_ci
1255bf215546Sopenharmony_ci#undef NAME
1256bf215546Sopenharmony_ci#define NAME(x) _hw_select_##x
1257bf215546Sopenharmony_ci   struct _glapi_table *tab = ctx->HWSelectModeBeginEnd;
1258bf215546Sopenharmony_ci   #include "api_hw_select_init.h"
1259bf215546Sopenharmony_ci}
1260