1848b8605Smrg/************************************************************************** 2848b8605Smrg 3848b8605SmrgCopyright 2002-2008 VMware, Inc. 4848b8605Smrg 5848b8605SmrgAll Rights Reserved. 6848b8605Smrg 7848b8605SmrgPermission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrgcopy of this software and associated documentation files (the "Software"), 9848b8605Smrgto deal in the Software without restriction, including without limitation 10848b8605Smrgon the rights to use, copy, modify, merge, publish, distribute, sub 11848b8605Smrglicense, and/or sell copies of the Software, and to permit persons to whom 12848b8605Smrgthe Software is furnished to do so, subject to the following conditions: 13848b8605Smrg 14848b8605SmrgThe above copyright notice and this permission notice (including the next 15848b8605Smrgparagraph) shall be included in all copies or substantial portions of the 16848b8605SmrgSoftware. 17848b8605Smrg 18848b8605SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19848b8605SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20848b8605SmrgFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21848b8605SmrgVMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 22848b8605SmrgDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23848b8605SmrgOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24848b8605SmrgUSE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg 26848b8605Smrg**************************************************************************/ 27848b8605Smrg 28848b8605Smrg/* 29848b8605Smrg * Authors: 30848b8605Smrg * Keith Whitwell <keithw@vmware.com> 31848b8605Smrg */ 32848b8605Smrg 33848b8605Smrg#include "main/glheader.h" 34848b8605Smrg#include "main/bufferobj.h" 35848b8605Smrg#include "main/context.h" 36848b8605Smrg#include "main/macros.h" 37848b8605Smrg#include "main/vtxfmt.h" 38848b8605Smrg#include "main/dlist.h" 39848b8605Smrg#include "main/eval.h" 40848b8605Smrg#include "main/state.h" 41848b8605Smrg#include "main/light.h" 42848b8605Smrg#include "main/api_arrayelt.h" 43b8e80941Smrg#include "main/draw_validate.h" 44848b8605Smrg#include "main/dispatch.h" 45b8e80941Smrg#include "util/bitscan.h" 46848b8605Smrg 47848b8605Smrg#include "vbo_noop.h" 48b8e80941Smrg#include "vbo_private.h" 49848b8605Smrg 50848b8605Smrg 51848b8605Smrg/** ID/name for immediate-mode VBO */ 52848b8605Smrg#define IMM_BUFFER_NAME 0xaabbccdd 53848b8605Smrg 54848b8605Smrg 55b8e80941Smrgstatic void 56b8e80941Smrgvbo_reset_all_attr(struct vbo_exec_context *exec); 57848b8605Smrg 58848b8605Smrg 59848b8605Smrg/** 60848b8605Smrg * Close off the last primitive, execute the buffer, restart the 61b8e80941Smrg * primitive. This is called when we fill a vertex buffer before 62b8e80941Smrg * hitting glEnd. 63848b8605Smrg */ 64b8e80941Smrgstatic void 65b8e80941Smrgvbo_exec_wrap_buffers(struct vbo_exec_context *exec) 66848b8605Smrg{ 67848b8605Smrg if (exec->vtx.prim_count == 0) { 68848b8605Smrg exec->vtx.copied.nr = 0; 69848b8605Smrg exec->vtx.vert_count = 0; 70848b8605Smrg exec->vtx.buffer_ptr = exec->vtx.buffer_map; 71848b8605Smrg } 72848b8605Smrg else { 73b8e80941Smrg struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; 74b8e80941Smrg const GLuint last_begin = last_prim->begin; 75848b8605Smrg GLuint last_count; 76848b8605Smrg 77848b8605Smrg if (_mesa_inside_begin_end(exec->ctx)) { 78b8e80941Smrg last_prim->count = exec->vtx.vert_count - last_prim->start; 79848b8605Smrg } 80848b8605Smrg 81b8e80941Smrg last_count = last_prim->count; 82b8e80941Smrg 83b8e80941Smrg /* Special handling for wrapping GL_LINE_LOOP */ 84b8e80941Smrg if (last_prim->mode == GL_LINE_LOOP && 85b8e80941Smrg last_count > 0 && 86b8e80941Smrg !last_prim->end) { 87b8e80941Smrg /* draw this section of the incomplete line loop as a line strip */ 88b8e80941Smrg last_prim->mode = GL_LINE_STRIP; 89b8e80941Smrg if (!last_prim->begin) { 90b8e80941Smrg /* This is not the first section of the line loop, so don't 91b8e80941Smrg * draw the 0th vertex. We're saving it until we draw the 92b8e80941Smrg * very last section of the loop. 93b8e80941Smrg */ 94b8e80941Smrg last_prim->start++; 95b8e80941Smrg last_prim->count--; 96b8e80941Smrg } 97b8e80941Smrg } 98848b8605Smrg 99848b8605Smrg /* Execute the buffer and save copied vertices. 100848b8605Smrg */ 101848b8605Smrg if (exec->vtx.vert_count) 102b8e80941Smrg vbo_exec_vtx_flush(exec, GL_FALSE); 103848b8605Smrg else { 104b8e80941Smrg exec->vtx.prim_count = 0; 105b8e80941Smrg exec->vtx.copied.nr = 0; 106848b8605Smrg } 107848b8605Smrg 108848b8605Smrg /* Emit a glBegin to start the new list. 109848b8605Smrg */ 110848b8605Smrg assert(exec->vtx.prim_count == 0); 111848b8605Smrg 112848b8605Smrg if (_mesa_inside_begin_end(exec->ctx)) { 113b8e80941Smrg exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; 114b8e80941Smrg exec->vtx.prim[0].begin = 0; 115b8e80941Smrg exec->vtx.prim[0].end = 0; 116b8e80941Smrg exec->vtx.prim[0].start = 0; 117b8e80941Smrg exec->vtx.prim[0].count = 0; 118b8e80941Smrg exec->vtx.prim_count++; 119b8e80941Smrg 120b8e80941Smrg if (exec->vtx.copied.nr == last_count) 121b8e80941Smrg exec->vtx.prim[0].begin = last_begin; 122848b8605Smrg } 123848b8605Smrg } 124848b8605Smrg} 125848b8605Smrg 126848b8605Smrg 127848b8605Smrg/** 128848b8605Smrg * Deal with buffer wrapping where provoked by the vertex buffer 129848b8605Smrg * filling up, as opposed to upgrade_vertex(). 130848b8605Smrg */ 131b8e80941Smrgstatic void 132b8e80941Smrgvbo_exec_vtx_wrap(struct vbo_exec_context *exec) 133848b8605Smrg{ 134b8e80941Smrg unsigned numComponents; 135848b8605Smrg 136848b8605Smrg /* Run pipeline on current vertices, copy wrapped vertices 137848b8605Smrg * to exec->vtx.copied. 138848b8605Smrg */ 139b8e80941Smrg vbo_exec_wrap_buffers(exec); 140b8e80941Smrg 141848b8605Smrg if (!exec->vtx.buffer_ptr) { 142848b8605Smrg /* probably ran out of memory earlier when allocating the VBO */ 143848b8605Smrg return; 144848b8605Smrg } 145848b8605Smrg 146b8e80941Smrg /* Copy stored stored vertices to start of new list. 147848b8605Smrg */ 148848b8605Smrg assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); 149848b8605Smrg 150b8e80941Smrg numComponents = exec->vtx.copied.nr * exec->vtx.vertex_size; 151b8e80941Smrg memcpy(exec->vtx.buffer_ptr, 152b8e80941Smrg exec->vtx.copied.buffer, 153b8e80941Smrg numComponents * sizeof(fi_type)); 154b8e80941Smrg exec->vtx.buffer_ptr += numComponents; 155b8e80941Smrg exec->vtx.vert_count += exec->vtx.copied.nr; 156848b8605Smrg 157848b8605Smrg exec->vtx.copied.nr = 0; 158848b8605Smrg} 159848b8605Smrg 160848b8605Smrg 161848b8605Smrg/** 162848b8605Smrg * Copy the active vertex's values to the ctx->Current fields. 163848b8605Smrg */ 164b8e80941Smrgstatic void 165b8e80941Smrgvbo_exec_copy_to_current(struct vbo_exec_context *exec) 166848b8605Smrg{ 167848b8605Smrg struct gl_context *ctx = exec->ctx; 168848b8605Smrg struct vbo_context *vbo = vbo_context(ctx); 169b8e80941Smrg GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS)); 170848b8605Smrg 171b8e80941Smrg while (enabled) { 172b8e80941Smrg const int i = u_bit_scan64(&enabled); 173848b8605Smrg 174b8e80941Smrg /* Note: the exec->vtx.current[i] pointers point into the 175b8e80941Smrg * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. 176b8e80941Smrg */ 177b8e80941Smrg GLfloat *current = (GLfloat *)vbo->current[i].Ptr; 178b8e80941Smrg fi_type tmp[8]; /* space for doubles */ 179b8e80941Smrg int dmul = 1; 180b8e80941Smrg 181b8e80941Smrg if (exec->vtx.attrtype[i] == GL_DOUBLE || 182b8e80941Smrg exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) 183b8e80941Smrg dmul = 2; 184b8e80941Smrg 185b8e80941Smrg assert(exec->vtx.attrsz[i]); 186b8e80941Smrg 187b8e80941Smrg if (exec->vtx.attrtype[i] == GL_DOUBLE || 188b8e80941Smrg exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) { 189b8e80941Smrg memset(tmp, 0, sizeof(tmp)); 190b8e80941Smrg memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat)); 191b8e80941Smrg } else { 192b8e80941Smrg COPY_CLEAN_4V_TYPE_AS_UNION(tmp, 193848b8605Smrg exec->vtx.attrsz[i], 194848b8605Smrg exec->vtx.attrptr[i], 195848b8605Smrg exec->vtx.attrtype[i]); 196b8e80941Smrg } 197b8e80941Smrg 198b8e80941Smrg if (exec->vtx.attrtype[i] != vbo->current[i].Format.Type || 199b8e80941Smrg memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) { 200b8e80941Smrg memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul); 201b8e80941Smrg 202b8e80941Smrg /* Given that we explicitly state size here, there is no need 203b8e80941Smrg * for the COPY_CLEAN above, could just copy 16 bytes and be 204b8e80941Smrg * done. The only problem is when Mesa accesses ctx->Current 205b8e80941Smrg * directly. 206b8e80941Smrg */ 207b8e80941Smrg /* Size here is in components - not bytes */ 208b8e80941Smrg vbo_set_vertex_format(&vbo->current[i].Format, 209b8e80941Smrg exec->vtx.attrsz[i] / dmul, 210b8e80941Smrg exec->vtx.attrtype[i]); 211b8e80941Smrg 212b8e80941Smrg /* This triggers rather too much recalculation of Mesa state 213b8e80941Smrg * that doesn't get used (eg light positions). 214b8e80941Smrg */ 215b8e80941Smrg if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && 216b8e80941Smrg i <= VBO_ATTRIB_MAT_BACK_INDEXES) 217b8e80941Smrg ctx->NewState |= _NEW_LIGHT; 218b8e80941Smrg 219b8e80941Smrg ctx->NewState |= _NEW_CURRENT_ATTRIB; 220848b8605Smrg } 221848b8605Smrg } 222848b8605Smrg 223848b8605Smrg /* Colormaterial -- this kindof sucks. 224848b8605Smrg */ 225848b8605Smrg if (ctx->Light.ColorMaterialEnabled && 226848b8605Smrg exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) { 227b8e80941Smrg _mesa_update_color_material(ctx, 228b8e80941Smrg ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); 229848b8605Smrg } 230848b8605Smrg} 231848b8605Smrg 232848b8605Smrg 233848b8605Smrg/** 234848b8605Smrg * Copy current vertex attribute values into the current vertex. 235848b8605Smrg */ 236848b8605Smrgstatic void 237848b8605Smrgvbo_exec_copy_from_current(struct vbo_exec_context *exec) 238848b8605Smrg{ 239848b8605Smrg struct gl_context *ctx = exec->ctx; 240848b8605Smrg struct vbo_context *vbo = vbo_context(ctx); 241848b8605Smrg GLint i; 242848b8605Smrg 243848b8605Smrg for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { 244b8e80941Smrg if (exec->vtx.attrtype[i] == GL_DOUBLE || 245b8e80941Smrg exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) { 246b8e80941Smrg memcpy(exec->vtx.attrptr[i], vbo->current[i].Ptr, 247b8e80941Smrg exec->vtx.attrsz[i] * sizeof(GLfloat)); 248b8e80941Smrg } else { 249b8e80941Smrg const fi_type *current = (fi_type *) vbo->current[i].Ptr; 250b8e80941Smrg switch (exec->vtx.attrsz[i]) { 251b8e80941Smrg case 4: exec->vtx.attrptr[i][3] = current[3]; 252b8e80941Smrg case 3: exec->vtx.attrptr[i][2] = current[2]; 253b8e80941Smrg case 2: exec->vtx.attrptr[i][1] = current[1]; 254b8e80941Smrg case 1: exec->vtx.attrptr[i][0] = current[0]; 255b8e80941Smrg break; 256b8e80941Smrg } 257848b8605Smrg } 258848b8605Smrg } 259848b8605Smrg} 260848b8605Smrg 261848b8605Smrg 262848b8605Smrg/** 263848b8605Smrg * Flush existing data, set new attrib size, replay copied vertices. 264848b8605Smrg * This is called when we transition from a small vertex attribute size 265848b8605Smrg * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. 266848b8605Smrg * We need to go back over the previous 2-component texcoords and insert 267848b8605Smrg * zero and one values. 268b8e80941Smrg * \param attr VBO_ATTRIB_x vertex attribute value 269b8e80941Smrg */ 270848b8605Smrgstatic void 271848b8605Smrgvbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, 272b8e80941Smrg GLuint attr, GLuint newSize) 273848b8605Smrg{ 274848b8605Smrg struct gl_context *ctx = exec->ctx; 275848b8605Smrg struct vbo_context *vbo = vbo_context(ctx); 276848b8605Smrg const GLint lastcount = exec->vtx.vert_count; 277b8e80941Smrg fi_type *old_attrptr[VBO_ATTRIB_MAX]; 278848b8605Smrg const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ 279848b8605Smrg const GLuint oldSize = exec->vtx.attrsz[attr]; 280848b8605Smrg GLuint i; 281848b8605Smrg 282b8e80941Smrg assert(attr < VBO_ATTRIB_MAX); 283b8e80941Smrg 284848b8605Smrg /* Run pipeline on current vertices, copy wrapped vertices 285848b8605Smrg * to exec->vtx.copied. 286848b8605Smrg */ 287b8e80941Smrg vbo_exec_wrap_buffers(exec); 288848b8605Smrg 289848b8605Smrg if (unlikely(exec->vtx.copied.nr)) { 290848b8605Smrg /* We're in the middle of a primitive, keep the old vertex 291848b8605Smrg * format around to be able to translate the copied vertices to 292848b8605Smrg * the new format. 293848b8605Smrg */ 294848b8605Smrg memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); 295848b8605Smrg } 296848b8605Smrg 297848b8605Smrg if (unlikely(oldSize)) { 298848b8605Smrg /* Do a COPY_TO_CURRENT to ensure back-copying works for the 299848b8605Smrg * case when the attribute already exists in the vertex and is 300848b8605Smrg * having its size increased. 301848b8605Smrg */ 302b8e80941Smrg vbo_exec_copy_to_current(exec); 303848b8605Smrg } 304848b8605Smrg 305848b8605Smrg /* Heuristic: Attempt to isolate attributes received outside 306848b8605Smrg * begin/end so that they don't bloat the vertices. 307848b8605Smrg */ 308848b8605Smrg if (!_mesa_inside_begin_end(ctx) && 309848b8605Smrg !oldSize && lastcount > 8 && exec->vtx.vertex_size) { 310b8e80941Smrg vbo_exec_copy_to_current(exec); 311b8e80941Smrg vbo_reset_all_attr(exec); 312848b8605Smrg } 313848b8605Smrg 314848b8605Smrg /* Fix up sizes: 315848b8605Smrg */ 316848b8605Smrg exec->vtx.attrsz[attr] = newSize; 317848b8605Smrg exec->vtx.vertex_size += newSize - oldSize; 318b8e80941Smrg exec->vtx.max_vert = vbo_compute_max_verts(exec); 319848b8605Smrg exec->vtx.vert_count = 0; 320848b8605Smrg exec->vtx.buffer_ptr = exec->vtx.buffer_map; 321b8e80941Smrg exec->vtx.enabled |= BITFIELD64_BIT(attr); 322848b8605Smrg 323848b8605Smrg if (unlikely(oldSize)) { 324848b8605Smrg /* Size changed, recalculate all the attrptr[] values 325848b8605Smrg */ 326b8e80941Smrg fi_type *tmp = exec->vtx.vertex; 327848b8605Smrg 328848b8605Smrg for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 329b8e80941Smrg if (exec->vtx.attrsz[i]) { 330b8e80941Smrg exec->vtx.attrptr[i] = tmp; 331b8e80941Smrg tmp += exec->vtx.attrsz[i]; 332b8e80941Smrg } 333b8e80941Smrg else 334b8e80941Smrg exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ 335848b8605Smrg } 336848b8605Smrg 337848b8605Smrg /* Copy from current to repopulate the vertex with correct 338848b8605Smrg * values. 339848b8605Smrg */ 340b8e80941Smrg vbo_exec_copy_from_current(exec); 341848b8605Smrg } 342848b8605Smrg else { 343848b8605Smrg /* Just have to append the new attribute at the end */ 344848b8605Smrg exec->vtx.attrptr[attr] = exec->vtx.vertex + 345b8e80941Smrg exec->vtx.vertex_size - newSize; 346848b8605Smrg } 347848b8605Smrg 348848b8605Smrg /* Replay stored vertices to translate them 349848b8605Smrg * to new format here. 350848b8605Smrg * 351848b8605Smrg * -- No need to replay - just copy piecewise 352848b8605Smrg */ 353848b8605Smrg if (unlikely(exec->vtx.copied.nr)) { 354b8e80941Smrg fi_type *data = exec->vtx.copied.buffer; 355b8e80941Smrg fi_type *dest = exec->vtx.buffer_ptr; 356848b8605Smrg 357848b8605Smrg assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); 358848b8605Smrg 359848b8605Smrg for (i = 0 ; i < exec->vtx.copied.nr ; i++) { 360b8e80941Smrg GLbitfield64 enabled = exec->vtx.enabled; 361b8e80941Smrg while (enabled) { 362b8e80941Smrg const int j = u_bit_scan64(&enabled); 363b8e80941Smrg GLuint sz = exec->vtx.attrsz[j]; 364b8e80941Smrg GLint old_offset = old_attrptr[j] - exec->vtx.vertex; 365b8e80941Smrg GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; 366b8e80941Smrg 367b8e80941Smrg assert(sz); 368b8e80941Smrg 369b8e80941Smrg if (j == attr) { 370b8e80941Smrg if (oldSize) { 371b8e80941Smrg fi_type tmp[4]; 372b8e80941Smrg COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize, 373b8e80941Smrg data + old_offset, 374b8e80941Smrg exec->vtx.attrtype[j]); 375b8e80941Smrg COPY_SZ_4V(dest + new_offset, newSize, tmp); 376b8e80941Smrg } else { 377b8e80941Smrg fi_type *current = (fi_type *)vbo->current[j].Ptr; 378b8e80941Smrg COPY_SZ_4V(dest + new_offset, sz, current); 379b8e80941Smrg } 380b8e80941Smrg } 381b8e80941Smrg else { 382b8e80941Smrg COPY_SZ_4V(dest + new_offset, sz, data + old_offset); 383b8e80941Smrg } 384b8e80941Smrg } 385b8e80941Smrg 386b8e80941Smrg data += old_vtx_size; 387b8e80941Smrg dest += exec->vtx.vertex_size; 388848b8605Smrg } 389848b8605Smrg 390848b8605Smrg exec->vtx.buffer_ptr = dest; 391848b8605Smrg exec->vtx.vert_count += exec->vtx.copied.nr; 392848b8605Smrg exec->vtx.copied.nr = 0; 393848b8605Smrg } 394848b8605Smrg} 395848b8605Smrg 396848b8605Smrg 397848b8605Smrg/** 398848b8605Smrg * This is when a vertex attribute transitions to a different size. 399848b8605Smrg * For example, we saw a bunch of glTexCoord2f() calls and now we got a 400848b8605Smrg * glTexCoord4f() call. We promote the array from size=2 to size=4. 401b8e80941Smrg * \param newSize size of new vertex (number of 32-bit words). 402b8e80941Smrg * \param attr VBO_ATTRIB_x vertex attribute value 403848b8605Smrg */ 404848b8605Smrgstatic void 405b8e80941Smrgvbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, 406b8e80941Smrg GLuint newSize, GLenum newType) 407848b8605Smrg{ 408848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 409848b8605Smrg 410b8e80941Smrg assert(attr < VBO_ATTRIB_MAX); 411b8e80941Smrg 412b8e80941Smrg if (newSize > exec->vtx.attrsz[attr] || 413b8e80941Smrg newType != exec->vtx.attrtype[attr]) { 414848b8605Smrg /* New size is larger. Need to flush existing vertices and get 415848b8605Smrg * an enlarged vertex format. 416848b8605Smrg */ 417b8e80941Smrg vbo_exec_wrap_upgrade_vertex(exec, attr, newSize); 418848b8605Smrg } 419848b8605Smrg else if (newSize < exec->vtx.active_sz[attr]) { 420848b8605Smrg GLuint i; 421b8e80941Smrg const fi_type *id = 422b8e80941Smrg vbo_get_default_vals_as_union(exec->vtx.attrtype[attr]); 423848b8605Smrg 424848b8605Smrg /* New size is smaller - just need to fill in some 425848b8605Smrg * zeros. Don't need to flush or wrap. 426848b8605Smrg */ 427848b8605Smrg for (i = newSize; i <= exec->vtx.attrsz[attr]; i++) 428b8e80941Smrg exec->vtx.attrptr[attr][i-1] = id[i-1]; 429848b8605Smrg } 430848b8605Smrg 431848b8605Smrg exec->vtx.active_sz[attr] = newSize; 432b8e80941Smrg exec->vtx.attrtype[attr] = newType; 433848b8605Smrg 434848b8605Smrg /* Does setting NeedFlush belong here? Necessitates resetting 435848b8605Smrg * vtxfmt on each flush (otherwise flags won't get reset 436848b8605Smrg * afterwards). 437848b8605Smrg */ 438b8e80941Smrg if (attr == 0) 439848b8605Smrg ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; 440848b8605Smrg} 441848b8605Smrg 442848b8605Smrg 443b8e80941Smrg/** 444b8e80941Smrg * Called upon first glVertex, glColor, glTexCoord, etc. 445b8e80941Smrg */ 446b8e80941Smrgstatic void 447b8e80941Smrgvbo_exec_begin_vertices(struct gl_context *ctx) 448b8e80941Smrg{ 449b8e80941Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 450b8e80941Smrg 451b8e80941Smrg vbo_exec_vtx_map(exec); 452b8e80941Smrg 453b8e80941Smrg assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); 454b8e80941Smrg assert(exec->begin_vertices_flags); 455b8e80941Smrg 456b8e80941Smrg ctx->Driver.NeedFlush |= exec->begin_vertices_flags; 457b8e80941Smrg} 458b8e80941Smrg 459b8e80941Smrg 460b8e80941Smrg/** 461b8e80941Smrg * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex? 462b8e80941Smrg * It depends on a few things, including whether we're inside or outside 463b8e80941Smrg * of glBegin/glEnd. 464b8e80941Smrg */ 465b8e80941Smrgstatic inline bool 466b8e80941Smrgis_vertex_position(const struct gl_context *ctx, GLuint index) 467b8e80941Smrg{ 468b8e80941Smrg return (index == 0 && 469b8e80941Smrg _mesa_attr_zero_aliases_vertex(ctx) && 470b8e80941Smrg _mesa_inside_begin_end(ctx)); 471b8e80941Smrg} 472b8e80941Smrg 473b8e80941Smrg 474848b8605Smrg/** 475848b8605Smrg * This macro is used to implement all the glVertex, glColor, glTexCoord, 476848b8605Smrg * glVertexAttrib, etc functions. 477b8e80941Smrg * \param A VBO_ATTRIB_x attribute index 478b8e80941Smrg * \param N attribute size (1..4) 479b8e80941Smrg * \param T type (GL_FLOAT, GL_DOUBLE, GL_INT, GL_UNSIGNED_INT) 480b8e80941Smrg * \param C cast type (fi_type or double) 481b8e80941Smrg * \param V0, V1, v2, V3 attribute value 482848b8605Smrg */ 483b8e80941Smrg#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \ 484b8e80941Smrgdo { \ 485b8e80941Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ 486b8e80941Smrg int sz = (sizeof(C) / sizeof(GLfloat)); \ 487b8e80941Smrg \ 488b8e80941Smrg assert(sz == 1 || sz == 2); \ 489b8e80941Smrg \ 490b8e80941Smrg /* check if attribute size or type is changing */ \ 491b8e80941Smrg if (unlikely(exec->vtx.active_sz[A] != N * sz) || \ 492b8e80941Smrg unlikely(exec->vtx.attrtype[A] != T)) { \ 493b8e80941Smrg vbo_exec_fixup_vertex(ctx, A, N * sz, T); \ 494b8e80941Smrg } \ 495b8e80941Smrg \ 496b8e80941Smrg /* store vertex attribute in vertex buffer */ \ 497b8e80941Smrg { \ 498b8e80941Smrg C *dest = (C *)exec->vtx.attrptr[A]; \ 499b8e80941Smrg if (N>0) dest[0] = V0; \ 500b8e80941Smrg if (N>1) dest[1] = V1; \ 501b8e80941Smrg if (N>2) dest[2] = V2; \ 502b8e80941Smrg if (N>3) dest[3] = V3; \ 503b8e80941Smrg assert(exec->vtx.attrtype[A] == T); \ 504b8e80941Smrg } \ 505b8e80941Smrg \ 506b8e80941Smrg if ((A) == 0) { \ 507b8e80941Smrg /* This is a glVertex call */ \ 508b8e80941Smrg GLuint i; \ 509b8e80941Smrg \ 510b8e80941Smrg if (unlikely((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0)) { \ 511b8e80941Smrg vbo_exec_begin_vertices(ctx); \ 512b8e80941Smrg } \ 513b8e80941Smrg \ 514b8e80941Smrg if (unlikely(!exec->vtx.buffer_ptr)) { \ 515b8e80941Smrg vbo_exec_vtx_map(exec); \ 516b8e80941Smrg } \ 517b8e80941Smrg assert(exec->vtx.buffer_ptr); \ 518b8e80941Smrg \ 519b8e80941Smrg /* copy 32-bit words */ \ 520b8e80941Smrg for (i = 0; i < exec->vtx.vertex_size; i++) \ 521b8e80941Smrg exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ 522b8e80941Smrg \ 523b8e80941Smrg exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ 524b8e80941Smrg \ 525b8e80941Smrg /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ 526b8e80941Smrg /* something to draw (not just updating a color or texcoord).*/ \ 527b8e80941Smrg ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ 528b8e80941Smrg \ 529b8e80941Smrg if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ 530b8e80941Smrg vbo_exec_vtx_wrap(exec); \ 531b8e80941Smrg } else { \ 532b8e80941Smrg /* we now have accumulated per-vertex attributes */ \ 533b8e80941Smrg ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ 534b8e80941Smrg } \ 535848b8605Smrg} while (0) 536848b8605Smrg 537848b8605Smrg 538b8e80941Smrg#undef ERROR 539b8e80941Smrg#define ERROR(err) _mesa_error(ctx, err, __func__) 540848b8605Smrg#define TAG(x) vbo_##x 541848b8605Smrg 542848b8605Smrg#include "vbo_attrib_tmp.h" 543848b8605Smrg 544848b8605Smrg 545848b8605Smrg 546848b8605Smrg/** 547848b8605Smrg * Execute a glMaterial call. Note that if GL_COLOR_MATERIAL is enabled, 548848b8605Smrg * this may be a (partial) no-op. 549848b8605Smrg */ 550848b8605Smrgstatic void GLAPIENTRY 551848b8605Smrgvbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params) 552848b8605Smrg{ 553848b8605Smrg GLbitfield updateMats; 554848b8605Smrg GET_CURRENT_CONTEXT(ctx); 555848b8605Smrg 556848b8605Smrg /* This function should be a no-op when it tries to update material 557848b8605Smrg * attributes which are currently tracking glColor via glColorMaterial. 558848b8605Smrg * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits 559848b8605Smrg * indicating which material attributes can actually be updated below. 560848b8605Smrg */ 561848b8605Smrg if (ctx->Light.ColorMaterialEnabled) { 562848b8605Smrg updateMats = ~ctx->Light._ColorMaterialBitmask; 563848b8605Smrg } 564848b8605Smrg else { 565848b8605Smrg /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */ 566848b8605Smrg updateMats = ALL_MATERIAL_BITS; 567848b8605Smrg } 568848b8605Smrg 569848b8605Smrg if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) { 570848b8605Smrg updateMats &= FRONT_MATERIAL_BITS; 571848b8605Smrg } 572848b8605Smrg else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) { 573848b8605Smrg updateMats &= BACK_MATERIAL_BITS; 574848b8605Smrg } 575848b8605Smrg else if (face != GL_FRONT_AND_BACK) { 576848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)"); 577848b8605Smrg return; 578848b8605Smrg } 579848b8605Smrg 580848b8605Smrg switch (pname) { 581848b8605Smrg case GL_EMISSION: 582848b8605Smrg if (updateMats & MAT_BIT_FRONT_EMISSION) 583848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params); 584848b8605Smrg if (updateMats & MAT_BIT_BACK_EMISSION) 585848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params); 586848b8605Smrg break; 587848b8605Smrg case GL_AMBIENT: 588848b8605Smrg if (updateMats & MAT_BIT_FRONT_AMBIENT) 589848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params); 590848b8605Smrg if (updateMats & MAT_BIT_BACK_AMBIENT) 591848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params); 592848b8605Smrg break; 593848b8605Smrg case GL_DIFFUSE: 594848b8605Smrg if (updateMats & MAT_BIT_FRONT_DIFFUSE) 595848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params); 596848b8605Smrg if (updateMats & MAT_BIT_BACK_DIFFUSE) 597848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params); 598848b8605Smrg break; 599848b8605Smrg case GL_SPECULAR: 600848b8605Smrg if (updateMats & MAT_BIT_FRONT_SPECULAR) 601848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params); 602848b8605Smrg if (updateMats & MAT_BIT_BACK_SPECULAR) 603848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params); 604848b8605Smrg break; 605848b8605Smrg case GL_SHININESS: 606848b8605Smrg if (*params < 0 || *params > ctx->Const.MaxShininess) { 607848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 608848b8605Smrg "glMaterial(invalid shininess: %f out range [0, %f])", 609b8e80941Smrg *params, ctx->Const.MaxShininess); 610848b8605Smrg return; 611848b8605Smrg } 612848b8605Smrg if (updateMats & MAT_BIT_FRONT_SHININESS) 613848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params); 614848b8605Smrg if (updateMats & MAT_BIT_BACK_SHININESS) 615848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params); 616848b8605Smrg break; 617848b8605Smrg case GL_COLOR_INDEXES: 618848b8605Smrg if (ctx->API != API_OPENGL_COMPAT) { 619848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)"); 620848b8605Smrg return; 621848b8605Smrg } 622848b8605Smrg if (updateMats & MAT_BIT_FRONT_INDEXES) 623848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params); 624848b8605Smrg if (updateMats & MAT_BIT_BACK_INDEXES) 625848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params); 626848b8605Smrg break; 627848b8605Smrg case GL_AMBIENT_AND_DIFFUSE: 628848b8605Smrg if (updateMats & MAT_BIT_FRONT_AMBIENT) 629848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params); 630848b8605Smrg if (updateMats & MAT_BIT_FRONT_DIFFUSE) 631848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params); 632848b8605Smrg if (updateMats & MAT_BIT_BACK_AMBIENT) 633848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params); 634848b8605Smrg if (updateMats & MAT_BIT_BACK_DIFFUSE) 635848b8605Smrg MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params); 636848b8605Smrg break; 637848b8605Smrg default: 638848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)"); 639848b8605Smrg return; 640848b8605Smrg } 641848b8605Smrg} 642848b8605Smrg 643848b8605Smrg 644848b8605Smrg/** 645848b8605Smrg * Flush (draw) vertices. 646848b8605Smrg * \param unmap - leave VBO unmapped after flushing? 647848b8605Smrg */ 648848b8605Smrgstatic void 649848b8605Smrgvbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap) 650848b8605Smrg{ 651848b8605Smrg if (exec->vtx.vert_count || unmap) { 652b8e80941Smrg vbo_exec_vtx_flush(exec, unmap); 653848b8605Smrg } 654848b8605Smrg 655848b8605Smrg if (exec->vtx.vertex_size) { 656b8e80941Smrg vbo_exec_copy_to_current(exec); 657b8e80941Smrg vbo_reset_all_attr(exec); 658848b8605Smrg } 659848b8605Smrg} 660848b8605Smrg 661848b8605Smrg 662b8e80941Smrgstatic void GLAPIENTRY 663b8e80941Smrgvbo_exec_EvalCoord1f(GLfloat u) 664848b8605Smrg{ 665b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 666848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 667848b8605Smrg 668848b8605Smrg { 669848b8605Smrg GLint i; 670b8e80941Smrg if (exec->eval.recalculate_maps) 671b8e80941Smrg vbo_exec_eval_update(exec); 672848b8605Smrg 673848b8605Smrg for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { 674b8e80941Smrg if (exec->eval.map1[i].map) 675b8e80941Smrg if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) 676b8e80941Smrg vbo_exec_fixup_vertex(ctx, i, exec->eval.map1[i].sz, GL_FLOAT); 677848b8605Smrg } 678848b8605Smrg } 679848b8605Smrg 680b8e80941Smrg memcpy(exec->vtx.copied.buffer, exec->vtx.vertex, 681b8e80941Smrg exec->vtx.vertex_size * sizeof(GLfloat)); 682848b8605Smrg 683b8e80941Smrg vbo_exec_do_EvalCoord1f(exec, u); 684848b8605Smrg 685b8e80941Smrg memcpy(exec->vtx.vertex, exec->vtx.copied.buffer, 686b8e80941Smrg exec->vtx.vertex_size * sizeof(GLfloat)); 687848b8605Smrg} 688848b8605Smrg 689b8e80941Smrg 690b8e80941Smrgstatic void GLAPIENTRY 691b8e80941Smrgvbo_exec_EvalCoord2f(GLfloat u, GLfloat v) 692848b8605Smrg{ 693b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 694848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 695848b8605Smrg 696848b8605Smrg { 697848b8605Smrg GLint i; 698b8e80941Smrg if (exec->eval.recalculate_maps) 699b8e80941Smrg vbo_exec_eval_update(exec); 700848b8605Smrg 701848b8605Smrg for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { 702b8e80941Smrg if (exec->eval.map2[i].map) 703b8e80941Smrg if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) 704b8e80941Smrg vbo_exec_fixup_vertex(ctx, i, exec->eval.map2[i].sz, GL_FLOAT); 705848b8605Smrg } 706848b8605Smrg 707b8e80941Smrg if (ctx->Eval.AutoNormal) 708b8e80941Smrg if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) 709b8e80941Smrg vbo_exec_fixup_vertex(ctx, VBO_ATTRIB_NORMAL, 3, GL_FLOAT); 710848b8605Smrg } 711848b8605Smrg 712b8e80941Smrg memcpy(exec->vtx.copied.buffer, exec->vtx.vertex, 713b8e80941Smrg exec->vtx.vertex_size * sizeof(GLfloat)); 714848b8605Smrg 715b8e80941Smrg vbo_exec_do_EvalCoord2f(exec, u, v); 716848b8605Smrg 717b8e80941Smrg memcpy(exec->vtx.vertex, exec->vtx.copied.buffer, 718b8e80941Smrg exec->vtx.vertex_size * sizeof(GLfloat)); 719848b8605Smrg} 720848b8605Smrg 721b8e80941Smrg 722b8e80941Smrgstatic void GLAPIENTRY 723b8e80941Smrgvbo_exec_EvalCoord1fv(const GLfloat *u) 724848b8605Smrg{ 725b8e80941Smrg vbo_exec_EvalCoord1f(u[0]); 726848b8605Smrg} 727848b8605Smrg 728b8e80941Smrg 729b8e80941Smrgstatic void GLAPIENTRY 730b8e80941Smrgvbo_exec_EvalCoord2fv(const GLfloat *u) 731848b8605Smrg{ 732b8e80941Smrg vbo_exec_EvalCoord2f(u[0], u[1]); 733848b8605Smrg} 734848b8605Smrg 735b8e80941Smrg 736b8e80941Smrgstatic void GLAPIENTRY 737b8e80941Smrgvbo_exec_EvalPoint1(GLint i) 738848b8605Smrg{ 739b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 740848b8605Smrg GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / 741b8e80941Smrg (GLfloat) ctx->Eval.MapGrid1un); 742848b8605Smrg GLfloat u = i * du + ctx->Eval.MapGrid1u1; 743848b8605Smrg 744b8e80941Smrg vbo_exec_EvalCoord1f(u); 745848b8605Smrg} 746848b8605Smrg 747848b8605Smrg 748b8e80941Smrgstatic void GLAPIENTRY 749b8e80941Smrgvbo_exec_EvalPoint2(GLint i, GLint j) 750848b8605Smrg{ 751b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 752b8e80941Smrg GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / 753b8e80941Smrg (GLfloat) ctx->Eval.MapGrid2un); 754b8e80941Smrg GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / 755b8e80941Smrg (GLfloat) ctx->Eval.MapGrid2vn); 756848b8605Smrg GLfloat u = i * du + ctx->Eval.MapGrid2u1; 757848b8605Smrg GLfloat v = j * dv + ctx->Eval.MapGrid2v1; 758848b8605Smrg 759b8e80941Smrg vbo_exec_EvalCoord2f(u, v); 760848b8605Smrg} 761848b8605Smrg 762848b8605Smrg 763848b8605Smrg/** 764848b8605Smrg * Called via glBegin. 765848b8605Smrg */ 766b8e80941Smrgstatic void GLAPIENTRY 767b8e80941Smrgvbo_exec_Begin(GLenum mode) 768848b8605Smrg{ 769b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 770b8e80941Smrg struct vbo_context *vbo = vbo_context(ctx); 771b8e80941Smrg struct vbo_exec_context *exec = &vbo->exec; 772848b8605Smrg int i; 773848b8605Smrg 774848b8605Smrg if (_mesa_inside_begin_end(ctx)) { 775848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBegin"); 776848b8605Smrg return; 777848b8605Smrg } 778848b8605Smrg 779848b8605Smrg if (!_mesa_valid_prim_mode(ctx, mode, "glBegin")) { 780848b8605Smrg return; 781848b8605Smrg } 782848b8605Smrg 783848b8605Smrg if (ctx->NewState) { 784b8e80941Smrg _mesa_update_state(ctx); 785848b8605Smrg 786848b8605Smrg CALL_Begin(ctx->Exec, (mode)); 787848b8605Smrg return; 788848b8605Smrg } 789848b8605Smrg 790848b8605Smrg if (!_mesa_valid_to_render(ctx, "glBegin")) { 791848b8605Smrg return; 792848b8605Smrg } 793848b8605Smrg 794b8e80941Smrg /* Heuristic: attempt to isolate attributes occurring outside 795848b8605Smrg * begin/end pairs. 796848b8605Smrg */ 797848b8605Smrg if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) 798848b8605Smrg vbo_exec_FlushVertices_internal(exec, GL_FALSE); 799848b8605Smrg 800848b8605Smrg i = exec->vtx.prim_count++; 801848b8605Smrg exec->vtx.prim[i].mode = mode; 802848b8605Smrg exec->vtx.prim[i].begin = 1; 803848b8605Smrg exec->vtx.prim[i].end = 0; 804848b8605Smrg exec->vtx.prim[i].indexed = 0; 805848b8605Smrg exec->vtx.prim[i].pad = 0; 806848b8605Smrg exec->vtx.prim[i].start = exec->vtx.vert_count; 807848b8605Smrg exec->vtx.prim[i].count = 0; 808848b8605Smrg exec->vtx.prim[i].num_instances = 1; 809848b8605Smrg exec->vtx.prim[i].base_instance = 0; 810848b8605Smrg exec->vtx.prim[i].is_indirect = 0; 811848b8605Smrg 812848b8605Smrg ctx->Driver.CurrentExecPrimitive = mode; 813848b8605Smrg 814848b8605Smrg ctx->Exec = ctx->BeginEnd; 815b8e80941Smrg 816848b8605Smrg /* We may have been called from a display list, in which case we should 817848b8605Smrg * leave dlist.c's dispatch table in place. 818848b8605Smrg */ 819b8e80941Smrg if (ctx->CurrentClientDispatch == ctx->MarshalExec) { 820b8e80941Smrg ctx->CurrentServerDispatch = ctx->Exec; 821b8e80941Smrg } else if (ctx->CurrentClientDispatch == ctx->OutsideBeginEnd) { 822b8e80941Smrg ctx->CurrentClientDispatch = ctx->Exec; 823b8e80941Smrg _glapi_set_dispatch(ctx->CurrentClientDispatch); 824848b8605Smrg } else { 825b8e80941Smrg assert(ctx->CurrentClientDispatch == ctx->Save); 826848b8605Smrg } 827848b8605Smrg} 828848b8605Smrg 829848b8605Smrg 830848b8605Smrg/** 831848b8605Smrg * Try to merge / concatenate the two most recent VBO primitives. 832848b8605Smrg */ 833848b8605Smrgstatic void 834848b8605Smrgtry_vbo_merge(struct vbo_exec_context *exec) 835848b8605Smrg{ 836848b8605Smrg struct _mesa_prim *cur = &exec->vtx.prim[exec->vtx.prim_count - 1]; 837848b8605Smrg 838848b8605Smrg assert(exec->vtx.prim_count >= 1); 839848b8605Smrg 840848b8605Smrg vbo_try_prim_conversion(cur); 841848b8605Smrg 842848b8605Smrg if (exec->vtx.prim_count >= 2) { 843848b8605Smrg struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2]; 844848b8605Smrg assert(prev == cur - 1); 845848b8605Smrg 846848b8605Smrg if (vbo_can_merge_prims(prev, cur)) { 847848b8605Smrg assert(cur->begin); 848848b8605Smrg assert(cur->end); 849848b8605Smrg assert(prev->begin); 850848b8605Smrg assert(prev->end); 851848b8605Smrg vbo_merge_prims(prev, cur); 852848b8605Smrg exec->vtx.prim_count--; /* drop the last primitive */ 853848b8605Smrg } 854848b8605Smrg } 855848b8605Smrg} 856848b8605Smrg 857848b8605Smrg 858848b8605Smrg/** 859848b8605Smrg * Called via glEnd. 860848b8605Smrg */ 861b8e80941Smrgstatic void GLAPIENTRY 862b8e80941Smrgvbo_exec_End(void) 863848b8605Smrg{ 864b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 865848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 866848b8605Smrg 867848b8605Smrg if (!_mesa_inside_begin_end(ctx)) { 868848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); 869848b8605Smrg return; 870848b8605Smrg } 871848b8605Smrg 872848b8605Smrg ctx->Exec = ctx->OutsideBeginEnd; 873b8e80941Smrg 874b8e80941Smrg if (ctx->CurrentClientDispatch == ctx->MarshalExec) { 875b8e80941Smrg ctx->CurrentServerDispatch = ctx->Exec; 876b8e80941Smrg } else if (ctx->CurrentClientDispatch == ctx->BeginEnd) { 877b8e80941Smrg ctx->CurrentClientDispatch = ctx->Exec; 878b8e80941Smrg _glapi_set_dispatch(ctx->CurrentClientDispatch); 879848b8605Smrg } 880848b8605Smrg 881848b8605Smrg if (exec->vtx.prim_count > 0) { 882848b8605Smrg /* close off current primitive */ 883b8e80941Smrg struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; 884b8e80941Smrg 885b8e80941Smrg last_prim->end = 1; 886b8e80941Smrg last_prim->count = exec->vtx.vert_count - last_prim->start; 887b8e80941Smrg 888b8e80941Smrg /* Special handling for GL_LINE_LOOP */ 889b8e80941Smrg if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) { 890b8e80941Smrg /* We're finishing drawing a line loop. Append 0th vertex onto 891b8e80941Smrg * end of vertex buffer so we can draw it as a line strip. 892b8e80941Smrg */ 893b8e80941Smrg const fi_type *src = exec->vtx.buffer_map + 894b8e80941Smrg last_prim->start * exec->vtx.vertex_size; 895b8e80941Smrg fi_type *dst = exec->vtx.buffer_map + 896b8e80941Smrg exec->vtx.vert_count * exec->vtx.vertex_size; 897848b8605Smrg 898b8e80941Smrg /* copy 0th vertex to end of buffer */ 899b8e80941Smrg memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type)); 900b8e80941Smrg 901b8e80941Smrg last_prim->start++; /* skip vertex0 */ 902b8e80941Smrg /* note that last_prim->count stays unchanged */ 903b8e80941Smrg last_prim->mode = GL_LINE_STRIP; 904b8e80941Smrg 905b8e80941Smrg /* Increment the vertex count so the next primitive doesn't 906b8e80941Smrg * overwrite the last vertex which we just added. 907b8e80941Smrg */ 908b8e80941Smrg exec->vtx.vert_count++; 909b8e80941Smrg exec->vtx.buffer_ptr += exec->vtx.vertex_size; 910b8e80941Smrg } 911848b8605Smrg 912848b8605Smrg try_vbo_merge(exec); 913848b8605Smrg } 914848b8605Smrg 915848b8605Smrg ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; 916848b8605Smrg 917848b8605Smrg if (exec->vtx.prim_count == VBO_MAX_PRIM) 918b8e80941Smrg vbo_exec_vtx_flush(exec, GL_FALSE); 919848b8605Smrg 920848b8605Smrg if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { 921848b8605Smrg _mesa_flush(ctx); 922848b8605Smrg } 923848b8605Smrg} 924848b8605Smrg 925848b8605Smrg 926848b8605Smrg/** 927848b8605Smrg * Called via glPrimitiveRestartNV() 928848b8605Smrg */ 929848b8605Smrgstatic void GLAPIENTRY 930848b8605Smrgvbo_exec_PrimitiveRestartNV(void) 931848b8605Smrg{ 932848b8605Smrg GLenum curPrim; 933b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 934848b8605Smrg 935848b8605Smrg curPrim = ctx->Driver.CurrentExecPrimitive; 936848b8605Smrg 937848b8605Smrg if (curPrim == PRIM_OUTSIDE_BEGIN_END) { 938b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV"); 939848b8605Smrg } 940848b8605Smrg else { 941848b8605Smrg vbo_exec_End(); 942848b8605Smrg vbo_exec_Begin(curPrim); 943848b8605Smrg } 944848b8605Smrg} 945848b8605Smrg 946848b8605Smrg 947b8e80941Smrgstatic void 948b8e80941Smrgvbo_exec_vtxfmt_init(struct vbo_exec_context *exec) 949848b8605Smrg{ 950848b8605Smrg struct gl_context *ctx = exec->ctx; 951848b8605Smrg GLvertexformat *vfmt = &exec->vtxfmt; 952848b8605Smrg 953848b8605Smrg vfmt->ArrayElement = _ae_ArrayElement; 954848b8605Smrg 955848b8605Smrg vfmt->Begin = vbo_exec_Begin; 956848b8605Smrg vfmt->End = vbo_exec_End; 957848b8605Smrg vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV; 958848b8605Smrg 959848b8605Smrg vfmt->CallList = _mesa_CallList; 960848b8605Smrg vfmt->CallLists = _mesa_CallLists; 961848b8605Smrg 962848b8605Smrg vfmt->EvalCoord1f = vbo_exec_EvalCoord1f; 963848b8605Smrg vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv; 964848b8605Smrg vfmt->EvalCoord2f = vbo_exec_EvalCoord2f; 965848b8605Smrg vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv; 966848b8605Smrg vfmt->EvalPoint1 = vbo_exec_EvalPoint1; 967848b8605Smrg vfmt->EvalPoint2 = vbo_exec_EvalPoint2; 968848b8605Smrg 969848b8605Smrg /* from attrib_tmp.h: 970848b8605Smrg */ 971848b8605Smrg vfmt->Color3f = vbo_Color3f; 972848b8605Smrg vfmt->Color3fv = vbo_Color3fv; 973848b8605Smrg vfmt->Color4f = vbo_Color4f; 974848b8605Smrg vfmt->Color4fv = vbo_Color4fv; 975848b8605Smrg vfmt->FogCoordfEXT = vbo_FogCoordfEXT; 976848b8605Smrg vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT; 977848b8605Smrg vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f; 978848b8605Smrg vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv; 979848b8605Smrg vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f; 980848b8605Smrg vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv; 981848b8605Smrg vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f; 982848b8605Smrg vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv; 983848b8605Smrg vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f; 984848b8605Smrg vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv; 985848b8605Smrg vfmt->Normal3f = vbo_Normal3f; 986848b8605Smrg vfmt->Normal3fv = vbo_Normal3fv; 987848b8605Smrg vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT; 988848b8605Smrg vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT; 989848b8605Smrg vfmt->TexCoord1f = vbo_TexCoord1f; 990848b8605Smrg vfmt->TexCoord1fv = vbo_TexCoord1fv; 991848b8605Smrg vfmt->TexCoord2f = vbo_TexCoord2f; 992848b8605Smrg vfmt->TexCoord2fv = vbo_TexCoord2fv; 993848b8605Smrg vfmt->TexCoord3f = vbo_TexCoord3f; 994848b8605Smrg vfmt->TexCoord3fv = vbo_TexCoord3fv; 995848b8605Smrg vfmt->TexCoord4f = vbo_TexCoord4f; 996848b8605Smrg vfmt->TexCoord4fv = vbo_TexCoord4fv; 997848b8605Smrg vfmt->Vertex2f = vbo_Vertex2f; 998848b8605Smrg vfmt->Vertex2fv = vbo_Vertex2fv; 999848b8605Smrg vfmt->Vertex3f = vbo_Vertex3f; 1000848b8605Smrg vfmt->Vertex3fv = vbo_Vertex3fv; 1001848b8605Smrg vfmt->Vertex4f = vbo_Vertex4f; 1002848b8605Smrg vfmt->Vertex4fv = vbo_Vertex4fv; 1003b8e80941Smrg 1004848b8605Smrg if (ctx->API == API_OPENGLES2) { 1005848b8605Smrg vfmt->VertexAttrib1fARB = _es_VertexAttrib1f; 1006848b8605Smrg vfmt->VertexAttrib1fvARB = _es_VertexAttrib1fv; 1007848b8605Smrg vfmt->VertexAttrib2fARB = _es_VertexAttrib2f; 1008848b8605Smrg vfmt->VertexAttrib2fvARB = _es_VertexAttrib2fv; 1009848b8605Smrg vfmt->VertexAttrib3fARB = _es_VertexAttrib3f; 1010848b8605Smrg vfmt->VertexAttrib3fvARB = _es_VertexAttrib3fv; 1011848b8605Smrg vfmt->VertexAttrib4fARB = _es_VertexAttrib4f; 1012848b8605Smrg vfmt->VertexAttrib4fvARB = _es_VertexAttrib4fv; 1013848b8605Smrg } else { 1014848b8605Smrg vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB; 1015848b8605Smrg vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB; 1016848b8605Smrg vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB; 1017848b8605Smrg vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB; 1018848b8605Smrg vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB; 1019848b8605Smrg vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB; 1020848b8605Smrg vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB; 1021848b8605Smrg vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB; 1022848b8605Smrg } 1023848b8605Smrg 1024848b8605Smrg /* Note that VertexAttrib4fNV is used from dlist.c and api_arrayelt.c so 1025848b8605Smrg * they can have a single entrypoint for updating any of the legacy 1026848b8605Smrg * attribs. 1027848b8605Smrg */ 1028848b8605Smrg vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV; 1029848b8605Smrg vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV; 1030848b8605Smrg vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV; 1031848b8605Smrg vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV; 1032848b8605Smrg vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV; 1033848b8605Smrg vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV; 1034848b8605Smrg vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; 1035848b8605Smrg vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; 1036848b8605Smrg 1037848b8605Smrg /* integer-valued */ 1038848b8605Smrg vfmt->VertexAttribI1i = vbo_VertexAttribI1i; 1039848b8605Smrg vfmt->VertexAttribI2i = vbo_VertexAttribI2i; 1040848b8605Smrg vfmt->VertexAttribI3i = vbo_VertexAttribI3i; 1041848b8605Smrg vfmt->VertexAttribI4i = vbo_VertexAttribI4i; 1042848b8605Smrg vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv; 1043848b8605Smrg vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv; 1044848b8605Smrg vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv; 1045848b8605Smrg 1046848b8605Smrg /* unsigned integer-valued */ 1047848b8605Smrg vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui; 1048848b8605Smrg vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui; 1049848b8605Smrg vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui; 1050848b8605Smrg vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui; 1051848b8605Smrg vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv; 1052848b8605Smrg vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv; 1053848b8605Smrg vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv; 1054848b8605Smrg 1055848b8605Smrg vfmt->Materialfv = vbo_Materialfv; 1056848b8605Smrg 1057848b8605Smrg vfmt->EdgeFlag = vbo_EdgeFlag; 1058848b8605Smrg vfmt->Indexf = vbo_Indexf; 1059848b8605Smrg vfmt->Indexfv = vbo_Indexfv; 1060848b8605Smrg 1061848b8605Smrg /* ARB_vertex_type_2_10_10_10_rev */ 1062848b8605Smrg vfmt->VertexP2ui = vbo_VertexP2ui; 1063848b8605Smrg vfmt->VertexP2uiv = vbo_VertexP2uiv; 1064848b8605Smrg vfmt->VertexP3ui = vbo_VertexP3ui; 1065848b8605Smrg vfmt->VertexP3uiv = vbo_VertexP3uiv; 1066848b8605Smrg vfmt->VertexP4ui = vbo_VertexP4ui; 1067848b8605Smrg vfmt->VertexP4uiv = vbo_VertexP4uiv; 1068848b8605Smrg 1069848b8605Smrg vfmt->TexCoordP1ui = vbo_TexCoordP1ui; 1070848b8605Smrg vfmt->TexCoordP1uiv = vbo_TexCoordP1uiv; 1071848b8605Smrg vfmt->TexCoordP2ui = vbo_TexCoordP2ui; 1072848b8605Smrg vfmt->TexCoordP2uiv = vbo_TexCoordP2uiv; 1073848b8605Smrg vfmt->TexCoordP3ui = vbo_TexCoordP3ui; 1074848b8605Smrg vfmt->TexCoordP3uiv = vbo_TexCoordP3uiv; 1075848b8605Smrg vfmt->TexCoordP4ui = vbo_TexCoordP4ui; 1076848b8605Smrg vfmt->TexCoordP4uiv = vbo_TexCoordP4uiv; 1077848b8605Smrg 1078848b8605Smrg vfmt->MultiTexCoordP1ui = vbo_MultiTexCoordP1ui; 1079848b8605Smrg vfmt->MultiTexCoordP1uiv = vbo_MultiTexCoordP1uiv; 1080848b8605Smrg vfmt->MultiTexCoordP2ui = vbo_MultiTexCoordP2ui; 1081848b8605Smrg vfmt->MultiTexCoordP2uiv = vbo_MultiTexCoordP2uiv; 1082848b8605Smrg vfmt->MultiTexCoordP3ui = vbo_MultiTexCoordP3ui; 1083848b8605Smrg vfmt->MultiTexCoordP3uiv = vbo_MultiTexCoordP3uiv; 1084848b8605Smrg vfmt->MultiTexCoordP4ui = vbo_MultiTexCoordP4ui; 1085848b8605Smrg vfmt->MultiTexCoordP4uiv = vbo_MultiTexCoordP4uiv; 1086b8e80941Smrg 1087848b8605Smrg vfmt->NormalP3ui = vbo_NormalP3ui; 1088848b8605Smrg vfmt->NormalP3uiv = vbo_NormalP3uiv; 1089848b8605Smrg 1090848b8605Smrg vfmt->ColorP3ui = vbo_ColorP3ui; 1091848b8605Smrg vfmt->ColorP3uiv = vbo_ColorP3uiv; 1092848b8605Smrg vfmt->ColorP4ui = vbo_ColorP4ui; 1093848b8605Smrg vfmt->ColorP4uiv = vbo_ColorP4uiv; 1094848b8605Smrg 1095848b8605Smrg vfmt->SecondaryColorP3ui = vbo_SecondaryColorP3ui; 1096848b8605Smrg vfmt->SecondaryColorP3uiv = vbo_SecondaryColorP3uiv; 1097848b8605Smrg 1098848b8605Smrg vfmt->VertexAttribP1ui = vbo_VertexAttribP1ui; 1099848b8605Smrg vfmt->VertexAttribP1uiv = vbo_VertexAttribP1uiv; 1100848b8605Smrg vfmt->VertexAttribP2ui = vbo_VertexAttribP2ui; 1101848b8605Smrg vfmt->VertexAttribP2uiv = vbo_VertexAttribP2uiv; 1102848b8605Smrg vfmt->VertexAttribP3ui = vbo_VertexAttribP3ui; 1103848b8605Smrg vfmt->VertexAttribP3uiv = vbo_VertexAttribP3uiv; 1104848b8605Smrg vfmt->VertexAttribP4ui = vbo_VertexAttribP4ui; 1105848b8605Smrg vfmt->VertexAttribP4uiv = vbo_VertexAttribP4uiv; 1106b8e80941Smrg 1107b8e80941Smrg vfmt->VertexAttribL1d = vbo_VertexAttribL1d; 1108b8e80941Smrg vfmt->VertexAttribL2d = vbo_VertexAttribL2d; 1109b8e80941Smrg vfmt->VertexAttribL3d = vbo_VertexAttribL3d; 1110b8e80941Smrg vfmt->VertexAttribL4d = vbo_VertexAttribL4d; 1111b8e80941Smrg 1112b8e80941Smrg vfmt->VertexAttribL1dv = vbo_VertexAttribL1dv; 1113b8e80941Smrg vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv; 1114b8e80941Smrg vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv; 1115b8e80941Smrg vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv; 1116b8e80941Smrg 1117b8e80941Smrg vfmt->VertexAttribL1ui64ARB = vbo_VertexAttribL1ui64ARB; 1118b8e80941Smrg vfmt->VertexAttribL1ui64vARB = vbo_VertexAttribL1ui64vARB; 1119848b8605Smrg} 1120848b8605Smrg 1121848b8605Smrg 1122848b8605Smrg/** 1123848b8605Smrg * Tell the VBO module to use a real OpenGL vertex buffer object to 1124848b8605Smrg * store accumulated immediate-mode vertex data. 1125848b8605Smrg * This replaces the malloced buffer which was created in 1126848b8605Smrg * vb_exec_vtx_init() below. 1127848b8605Smrg */ 1128b8e80941Smrgvoid 1129b8e80941Smrgvbo_use_buffer_objects(struct gl_context *ctx) 1130848b8605Smrg{ 1131848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 1132848b8605Smrg /* Any buffer name but 0 can be used here since this bufferobj won't 1133848b8605Smrg * go into the bufferobj hashtable. 1134848b8605Smrg */ 1135848b8605Smrg GLuint bufName = IMM_BUFFER_NAME; 1136848b8605Smrg GLenum target = GL_ARRAY_BUFFER_ARB; 1137848b8605Smrg GLenum usage = GL_STREAM_DRAW_ARB; 1138848b8605Smrg GLsizei size = VBO_VERT_BUFFER_SIZE; 1139848b8605Smrg 1140848b8605Smrg /* Make sure this func is only used once */ 1141848b8605Smrg assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); 1142848b8605Smrg 1143848b8605Smrg _mesa_align_free(exec->vtx.buffer_map); 1144848b8605Smrg exec->vtx.buffer_map = NULL; 1145848b8605Smrg exec->vtx.buffer_ptr = NULL; 1146848b8605Smrg 1147848b8605Smrg /* Allocate a real buffer object now */ 1148848b8605Smrg _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); 1149b8e80941Smrg exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName); 1150848b8605Smrg if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, 1151848b8605Smrg GL_MAP_WRITE_BIT | 1152848b8605Smrg GL_DYNAMIC_STORAGE_BIT | 1153848b8605Smrg GL_CLIENT_STORAGE_BIT, 1154848b8605Smrg exec->vtx.bufferobj)) { 1155848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); 1156848b8605Smrg } 1157848b8605Smrg} 1158848b8605Smrg 1159848b8605Smrg 1160848b8605Smrg/** 1161848b8605Smrg * If this function is called, all VBO buffers will be unmapped when 1162848b8605Smrg * we flush. 1163848b8605Smrg * Otherwise, if a simple command like glColor3f() is called and we flush, 1164848b8605Smrg * the current VBO may be left mapped. 1165848b8605Smrg */ 1166848b8605Smrgvoid 1167848b8605Smrgvbo_always_unmap_buffers(struct gl_context *ctx) 1168848b8605Smrg{ 1169848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 1170848b8605Smrg exec->begin_vertices_flags |= FLUSH_STORED_VERTICES; 1171848b8605Smrg} 1172848b8605Smrg 1173848b8605Smrg 1174b8e80941Smrgvoid 1175b8e80941Smrgvbo_exec_vtx_init(struct vbo_exec_context *exec) 1176848b8605Smrg{ 1177848b8605Smrg struct gl_context *ctx = exec->ctx; 1178848b8605Smrg GLuint i; 1179848b8605Smrg 1180848b8605Smrg /* Allocate a buffer object. Will just reuse this object 1181848b8605Smrg * continuously, unless vbo_use_buffer_objects() is called to enable 1182848b8605Smrg * use of real VBOs. 1183848b8605Smrg */ 1184848b8605Smrg _mesa_reference_buffer_object(ctx, 1185848b8605Smrg &exec->vtx.bufferobj, 1186848b8605Smrg ctx->Shared->NullBufferObj); 1187848b8605Smrg 1188b8e80941Smrg assert(!exec->vtx.buffer_map); 1189848b8605Smrg exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); 1190848b8605Smrg exec->vtx.buffer_ptr = exec->vtx.buffer_map; 1191848b8605Smrg 1192b8e80941Smrg vbo_exec_vtxfmt_init(exec); 1193848b8605Smrg _mesa_noop_vtxfmt_init(&exec->vtxfmt_noop); 1194848b8605Smrg 1195b8e80941Smrg exec->vtx.enabled = 0; 1196848b8605Smrg for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { 1197b8e80941Smrg assert(i < ARRAY_SIZE(exec->vtx.attrsz)); 1198848b8605Smrg exec->vtx.attrsz[i] = 0; 1199b8e80941Smrg assert(i < ARRAY_SIZE(exec->vtx.attrtype)); 1200848b8605Smrg exec->vtx.attrtype[i] = GL_FLOAT; 1201b8e80941Smrg assert(i < ARRAY_SIZE(exec->vtx.active_sz)); 1202848b8605Smrg exec->vtx.active_sz[i] = 0; 1203848b8605Smrg } 1204848b8605Smrg 1205848b8605Smrg exec->vtx.vertex_size = 0; 1206848b8605Smrg 1207848b8605Smrg exec->begin_vertices_flags = FLUSH_UPDATE_CURRENT; 1208848b8605Smrg} 1209848b8605Smrg 1210848b8605Smrg 1211b8e80941Smrgvoid 1212b8e80941Smrgvbo_exec_vtx_destroy(struct vbo_exec_context *exec) 1213848b8605Smrg{ 1214848b8605Smrg /* using a real VBO for vertex data */ 1215848b8605Smrg struct gl_context *ctx = exec->ctx; 1216848b8605Smrg 1217848b8605Smrg /* True VBOs should already be unmapped 1218848b8605Smrg */ 1219848b8605Smrg if (exec->vtx.buffer_map) { 1220b8e80941Smrg assert(exec->vtx.bufferobj->Name == 0 || 1221848b8605Smrg exec->vtx.bufferobj->Name == IMM_BUFFER_NAME); 1222848b8605Smrg if (exec->vtx.bufferobj->Name == 0) { 1223848b8605Smrg _mesa_align_free(exec->vtx.buffer_map); 1224848b8605Smrg exec->vtx.buffer_map = NULL; 1225848b8605Smrg exec->vtx.buffer_ptr = NULL; 1226848b8605Smrg } 1227848b8605Smrg } 1228848b8605Smrg 1229848b8605Smrg /* Free the vertex buffer. Unmap first if needed. 1230848b8605Smrg */ 1231848b8605Smrg if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) { 1232848b8605Smrg ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); 1233848b8605Smrg } 1234848b8605Smrg _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); 1235848b8605Smrg} 1236848b8605Smrg 1237848b8605Smrg 1238848b8605Smrg/** 1239b8e80941Smrg * If inside glBegin()/glEnd(), it should assert(0). Otherwise, if 1240b8e80941Smrg * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered 1241b8e80941Smrg * vertices, if FLUSH_UPDATE_CURRENT bit is set updates 1242b8e80941Smrg * __struct gl_contextRec::Current and gl_light_attrib::Material 1243b8e80941Smrg * 1244b8e80941Smrg * Note that the default T&L engine never clears the 1245b8e80941Smrg * FLUSH_UPDATE_CURRENT bit, even after performing the update. 1246b8e80941Smrg * 1247848b8605Smrg * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT 1248848b8605Smrg */ 1249b8e80941Smrgvoid 1250b8e80941Smrgvbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags) 1251848b8605Smrg{ 1252848b8605Smrg struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 1253848b8605Smrg 1254848b8605Smrg#ifdef DEBUG 1255848b8605Smrg /* debug check: make sure we don't get called recursively */ 1256848b8605Smrg exec->flush_call_depth++; 1257848b8605Smrg assert(exec->flush_call_depth == 1); 1258848b8605Smrg#endif 1259848b8605Smrg 1260848b8605Smrg if (_mesa_inside_begin_end(ctx)) { 1261848b8605Smrg /* We've had glBegin but not glEnd! */ 1262848b8605Smrg#ifdef DEBUG 1263848b8605Smrg exec->flush_call_depth--; 1264848b8605Smrg assert(exec->flush_call_depth == 0); 1265848b8605Smrg#endif 1266848b8605Smrg return; 1267848b8605Smrg } 1268848b8605Smrg 1269848b8605Smrg /* Flush (draw), and make sure VBO is left unmapped when done */ 1270848b8605Smrg vbo_exec_FlushVertices_internal(exec, GL_TRUE); 1271848b8605Smrg 1272b8e80941Smrg /* Need to do this to ensure vbo_exec_begin_vertices gets called again: 1273848b8605Smrg */ 1274848b8605Smrg ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); 1275848b8605Smrg 1276848b8605Smrg#ifdef DEBUG 1277848b8605Smrg exec->flush_call_depth--; 1278848b8605Smrg assert(exec->flush_call_depth == 0); 1279848b8605Smrg#endif 1280848b8605Smrg} 1281848b8605Smrg 1282848b8605Smrg 1283b8e80941Smrg/** 1284b8e80941Smrg * Reset the vertex attribute by setting its size to zero. 1285b8e80941Smrg */ 1286b8e80941Smrgstatic void 1287b8e80941Smrgvbo_reset_attr(struct vbo_exec_context *exec, GLuint attr) 1288b8e80941Smrg{ 1289b8e80941Smrg exec->vtx.attrsz[attr] = 0; 1290b8e80941Smrg exec->vtx.attrtype[attr] = GL_FLOAT; 1291b8e80941Smrg exec->vtx.active_sz[attr] = 0; 1292b8e80941Smrg} 1293848b8605Smrg 1294b8e80941Smrg 1295b8e80941Smrgstatic void 1296b8e80941Smrgvbo_reset_all_attr(struct vbo_exec_context *exec) 1297b8e80941Smrg{ 1298b8e80941Smrg while (exec->vtx.enabled) { 1299b8e80941Smrg const int i = u_bit_scan64(&exec->vtx.enabled); 1300b8e80941Smrg vbo_reset_attr(exec, i); 1301848b8605Smrg } 1302848b8605Smrg 1303848b8605Smrg exec->vtx.vertex_size = 0; 1304848b8605Smrg} 1305b8e80941Smrg 1306848b8605Smrg 1307848b8605Smrgvoid GLAPIENTRY 1308848b8605Smrg_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) 1309848b8605Smrg{ 1310848b8605Smrg vbo_Color4f(r, g, b, a); 1311848b8605Smrg} 1312848b8605Smrg 1313848b8605Smrg 1314848b8605Smrgvoid GLAPIENTRY 1315848b8605Smrg_es_Normal3f(GLfloat x, GLfloat y, GLfloat z) 1316848b8605Smrg{ 1317848b8605Smrg vbo_Normal3f(x, y, z); 1318848b8605Smrg} 1319848b8605Smrg 1320848b8605Smrg 1321848b8605Smrgvoid GLAPIENTRY 1322848b8605Smrg_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) 1323848b8605Smrg{ 1324848b8605Smrg vbo_MultiTexCoord4f(target, s, t, r, q); 1325848b8605Smrg} 1326848b8605Smrg 1327848b8605Smrg 1328848b8605Smrgvoid GLAPIENTRY 1329848b8605Smrg_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params) 1330848b8605Smrg{ 1331848b8605Smrg vbo_Materialfv(face, pname, params); 1332848b8605Smrg} 1333848b8605Smrg 1334848b8605Smrg 1335848b8605Smrgvoid GLAPIENTRY 1336848b8605Smrg_es_Materialf(GLenum face, GLenum pname, GLfloat param) 1337848b8605Smrg{ 1338848b8605Smrg GLfloat p[4]; 1339848b8605Smrg p[0] = param; 1340848b8605Smrg p[1] = p[2] = p[3] = 0.0F; 1341848b8605Smrg vbo_Materialfv(face, pname, p); 1342848b8605Smrg} 1343848b8605Smrg 1344848b8605Smrg 1345848b8605Smrg/** 1346848b8605Smrg * A special version of glVertexAttrib4f that does not treat index 0 as 1347848b8605Smrg * VBO_ATTRIB_POS. 1348848b8605Smrg */ 1349848b8605Smrgstatic void 1350848b8605SmrgVertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) 1351848b8605Smrg{ 1352848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1353848b8605Smrg if (index < MAX_VERTEX_GENERIC_ATTRIBS) 1354b8e80941Smrg ATTRF(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w); 1355848b8605Smrg else 1356848b8605Smrg ERROR(GL_INVALID_VALUE); 1357848b8605Smrg} 1358848b8605Smrg 1359848b8605Smrgvoid GLAPIENTRY 1360848b8605Smrg_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) 1361848b8605Smrg{ 1362848b8605Smrg VertexAttrib4f_nopos(index, x, y, z, w); 1363848b8605Smrg} 1364848b8605Smrg 1365848b8605Smrg 1366848b8605Smrgvoid GLAPIENTRY 1367848b8605Smrg_es_VertexAttrib1f(GLuint indx, GLfloat x) 1368848b8605Smrg{ 1369848b8605Smrg VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f); 1370848b8605Smrg} 1371848b8605Smrg 1372848b8605Smrg 1373848b8605Smrgvoid GLAPIENTRY 1374848b8605Smrg_es_VertexAttrib1fv(GLuint indx, const GLfloat* values) 1375848b8605Smrg{ 1376848b8605Smrg VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f); 1377848b8605Smrg} 1378848b8605Smrg 1379848b8605Smrg 1380848b8605Smrgvoid GLAPIENTRY 1381848b8605Smrg_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) 1382848b8605Smrg{ 1383848b8605Smrg VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f); 1384848b8605Smrg} 1385848b8605Smrg 1386848b8605Smrg 1387848b8605Smrgvoid GLAPIENTRY 1388848b8605Smrg_es_VertexAttrib2fv(GLuint indx, const GLfloat* values) 1389848b8605Smrg{ 1390848b8605Smrg VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f); 1391848b8605Smrg} 1392848b8605Smrg 1393848b8605Smrg 1394848b8605Smrgvoid GLAPIENTRY 1395848b8605Smrg_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) 1396848b8605Smrg{ 1397848b8605Smrg VertexAttrib4f_nopos(indx, x, y, z, 1.0f); 1398848b8605Smrg} 1399848b8605Smrg 1400848b8605Smrg 1401848b8605Smrgvoid GLAPIENTRY 1402848b8605Smrg_es_VertexAttrib3fv(GLuint indx, const GLfloat* values) 1403848b8605Smrg{ 1404848b8605Smrg VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f); 1405848b8605Smrg} 1406848b8605Smrg 1407848b8605Smrg 1408848b8605Smrgvoid GLAPIENTRY 1409848b8605Smrg_es_VertexAttrib4fv(GLuint indx, const GLfloat* values) 1410848b8605Smrg{ 1411848b8605Smrg VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]); 1412848b8605Smrg} 1413