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