1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci * Authors: 25bf215546Sopenharmony_ci * Keith Whitwell <keithw@vmware.com> 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "main/glheader.h" 30bf215546Sopenharmony_ci#include "main/arrayobj.h" 31bf215546Sopenharmony_ci#include "main/api_arrayelt.h" 32bf215546Sopenharmony_ci#include "vbo_private.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ciconst GLubyte 35bf215546Sopenharmony_ci_vbo_attribute_alias_map[VP_MODE_MAX][VERT_ATTRIB_MAX] = { 36bf215546Sopenharmony_ci /* VP_MODE_FF: */ 37bf215546Sopenharmony_ci { 38bf215546Sopenharmony_ci VBO_ATTRIB_POS, /* VERT_ATTRIB_POS */ 39bf215546Sopenharmony_ci VBO_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 40bf215546Sopenharmony_ci VBO_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 41bf215546Sopenharmony_ci VBO_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 42bf215546Sopenharmony_ci VBO_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 43bf215546Sopenharmony_ci VBO_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 44bf215546Sopenharmony_ci VBO_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 45bf215546Sopenharmony_ci VBO_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 46bf215546Sopenharmony_ci VBO_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 47bf215546Sopenharmony_ci VBO_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 48bf215546Sopenharmony_ci VBO_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 49bf215546Sopenharmony_ci VBO_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 50bf215546Sopenharmony_ci VBO_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 51bf215546Sopenharmony_ci VBO_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 52bf215546Sopenharmony_ci VBO_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 53bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 54bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 55bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 56bf215546Sopenharmony_ci VBO_ATTRIB_SELECT_RESULT_OFFSET,/* VERT_ATTRIB_GENERIC3 */ 57bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_AMBIENT, /* VERT_ATTRIB_GENERIC4 */ 58bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_AMBIENT, /* VERT_ATTRIB_GENERIC5 */ 59bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_DIFFUSE, /* VERT_ATTRIB_GENERIC6 */ 60bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_DIFFUSE, /* VERT_ATTRIB_GENERIC7 */ 61bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_SPECULAR, /* VERT_ATTRIB_GENERIC8 */ 62bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_SPECULAR, /* VERT_ATTRIB_GENERIC9 */ 63bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_EMISSION, /* VERT_ATTRIB_GENERIC10 */ 64bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_EMISSION, /* VERT_ATTRIB_GENERIC11 */ 65bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_SHININESS, /* VERT_ATTRIB_GENERIC12 */ 66bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_SHININESS, /* VERT_ATTRIB_GENERIC13 */ 67bf215546Sopenharmony_ci VBO_ATTRIB_MAT_FRONT_INDEXES, /* VERT_ATTRIB_GENERIC14 */ 68bf215546Sopenharmony_ci VBO_ATTRIB_MAT_BACK_INDEXES, /* VERT_ATTRIB_GENERIC15 */ 69bf215546Sopenharmony_ci VBO_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 70bf215546Sopenharmony_ci }, 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci /* VP_MODE_SHADER: */ 73bf215546Sopenharmony_ci { 74bf215546Sopenharmony_ci VBO_ATTRIB_POS, /* VERT_ATTRIB_POS */ 75bf215546Sopenharmony_ci VBO_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 76bf215546Sopenharmony_ci VBO_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 77bf215546Sopenharmony_ci VBO_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 78bf215546Sopenharmony_ci VBO_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 79bf215546Sopenharmony_ci VBO_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 80bf215546Sopenharmony_ci VBO_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 81bf215546Sopenharmony_ci VBO_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 82bf215546Sopenharmony_ci VBO_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 83bf215546Sopenharmony_ci VBO_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 84bf215546Sopenharmony_ci VBO_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 85bf215546Sopenharmony_ci VBO_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 86bf215546Sopenharmony_ci VBO_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 87bf215546Sopenharmony_ci VBO_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 88bf215546Sopenharmony_ci VBO_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 89bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 90bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 91bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 92bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 93bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 94bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 95bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 96bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 97bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 98bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 99bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 100bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 101bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 102bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 103bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 104bf215546Sopenharmony_ci VBO_ATTRIB_GENERIC15, /* VERT_ATTRIB_GENERIC15 */ 105bf215546Sopenharmony_ci VBO_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci}; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_civoid 111bf215546Sopenharmony_civbo_exec_init(struct gl_context *ctx) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci vbo_exec_vtx_init(exec); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci ctx->Driver.NeedFlush = 0; 118bf215546Sopenharmony_ci ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci exec->eval.recalculate_maps = GL_TRUE; 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_civoid vbo_exec_destroy( struct gl_context *ctx ) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci vbo_exec_vtx_destroy( exec ); 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci/** 133bf215546Sopenharmony_ci * In some degenarate cases we can improve our ability to merge 134bf215546Sopenharmony_ci * consecutive primitives. For example: 135bf215546Sopenharmony_ci * glBegin(GL_LINE_STRIP); 136bf215546Sopenharmony_ci * glVertex(1); 137bf215546Sopenharmony_ci * glVertex(1); 138bf215546Sopenharmony_ci * glEnd(); 139bf215546Sopenharmony_ci * glBegin(GL_LINE_STRIP); 140bf215546Sopenharmony_ci * glVertex(1); 141bf215546Sopenharmony_ci * glVertex(1); 142bf215546Sopenharmony_ci * glEnd(); 143bf215546Sopenharmony_ci * Can be merged as a GL_LINES prim with four vertices. 144bf215546Sopenharmony_ci * 145bf215546Sopenharmony_ci * This function converts 2-vertex line strips/loops into GL_LINES, etc. 146bf215546Sopenharmony_ci */ 147bf215546Sopenharmony_civoid 148bf215546Sopenharmony_civbo_try_prim_conversion(GLubyte *mode, unsigned *count) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci if (*mode == GL_LINE_STRIP && *count == 2) { 151bf215546Sopenharmony_ci /* convert 2-vertex line strip to a separate line */ 152bf215546Sopenharmony_ci *mode = GL_LINES; 153bf215546Sopenharmony_ci } else if ((*mode == GL_TRIANGLE_STRIP || *mode == GL_TRIANGLE_FAN) && 154bf215546Sopenharmony_ci *count == 3) { 155bf215546Sopenharmony_ci /* convert 3-vertex tri strip or fan to a separate triangle */ 156bf215546Sopenharmony_ci *mode = GL_TRIANGLES; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci /* Note: we can't convert a 4-vertex quad strip to a separate quad 160bf215546Sopenharmony_ci * because the vertex ordering is different. We'd have to muck 161bf215546Sopenharmony_ci * around in the vertex data to make it work. 162bf215546Sopenharmony_ci */ 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci/** 167bf215546Sopenharmony_ci * Function for merging two subsequent glBegin/glEnd draws. 168bf215546Sopenharmony_ci * Return true if p1 was concatenated onto p0 (to discard p1 in the caller). 169bf215546Sopenharmony_ci */ 170bf215546Sopenharmony_cibool 171bf215546Sopenharmony_civbo_merge_draws(struct gl_context *ctx, bool in_dlist, 172bf215546Sopenharmony_ci GLubyte mode0, GLubyte mode1, 173bf215546Sopenharmony_ci unsigned start0, unsigned start1, 174bf215546Sopenharmony_ci unsigned *count0, unsigned count1, 175bf215546Sopenharmony_ci unsigned basevertex0, unsigned basevertex1, 176bf215546Sopenharmony_ci bool *end0, bool begin1, bool end1) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci /* The prim mode must match (ex: both GL_TRIANGLES) */ 179bf215546Sopenharmony_ci if (mode0 != mode1) 180bf215546Sopenharmony_ci return false; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci /* p1's vertices must come right after p0 */ 183bf215546Sopenharmony_ci if (start0 + *count0 != start1) 184bf215546Sopenharmony_ci return false; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* This checks whether mode is equal to any line primitive type, taking 187bf215546Sopenharmony_ci * advantage of the fact that primitives types go from 0 to 14. 188bf215546Sopenharmony_ci * 189bf215546Sopenharmony_ci * Lines and lines with adjacency reset the line stipple pattern for every 190bf215546Sopenharmony_ci * primitive, so draws can be merged even if line stippling is enabled. 191bf215546Sopenharmony_ci */ 192bf215546Sopenharmony_ci if ((1 << mode0) & 193bf215546Sopenharmony_ci ((1 << GL_LINE_LOOP) | 194bf215546Sopenharmony_ci (1 << GL_LINE_STRIP) | 195bf215546Sopenharmony_ci (1 << GL_LINE_STRIP_ADJACENCY))) { 196bf215546Sopenharmony_ci /* "begin" resets the line stipple pattern during line stipple emulation 197bf215546Sopenharmony_ci * in tnl. 198bf215546Sopenharmony_ci * 199bf215546Sopenharmony_ci * StippleFlag can be unknown when compiling a display list. 200bf215546Sopenharmony_ci * 201bf215546Sopenharmony_ci * Other uses of "begin" are internal to the vbo module, and in those 202bf215546Sopenharmony_ci * cases, "begin" is not used after merging draws. 203bf215546Sopenharmony_ci */ 204bf215546Sopenharmony_ci if (begin1 == 1 && (in_dlist || ctx->Line.StippleFlag)) 205bf215546Sopenharmony_ci return false; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci /* _mesa_prim::end is irrelevant at this point and is only used 208bf215546Sopenharmony_ci * before this function is called. 209bf215546Sopenharmony_ci */ 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci assert(basevertex0 == basevertex1); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci switch (mode0) { 215bf215546Sopenharmony_ci case GL_POINTS: 216bf215546Sopenharmony_ci /* can always merge subsequent GL_POINTS primitives */ 217bf215546Sopenharmony_ci break; 218bf215546Sopenharmony_ci /* check independent primitives with no extra vertices */ 219bf215546Sopenharmony_ci case GL_LINES: 220bf215546Sopenharmony_ci if (*count0 % 2) 221bf215546Sopenharmony_ci return false; 222bf215546Sopenharmony_ci break; 223bf215546Sopenharmony_ci case GL_TRIANGLES: 224bf215546Sopenharmony_ci if (*count0 % 3) 225bf215546Sopenharmony_ci return false; 226bf215546Sopenharmony_ci break; 227bf215546Sopenharmony_ci case GL_QUADS: 228bf215546Sopenharmony_ci case GL_LINES_ADJACENCY: 229bf215546Sopenharmony_ci if (*count0 % 4) 230bf215546Sopenharmony_ci return false; 231bf215546Sopenharmony_ci break; 232bf215546Sopenharmony_ci case GL_TRIANGLES_ADJACENCY: 233bf215546Sopenharmony_ci if (*count0 % 6) 234bf215546Sopenharmony_ci return false; 235bf215546Sopenharmony_ci break; 236bf215546Sopenharmony_ci case GL_PATCHES: 237bf215546Sopenharmony_ci /* "patch_vertices" can be unknown when compiling a display list. */ 238bf215546Sopenharmony_ci if (in_dlist || 239bf215546Sopenharmony_ci *count0 % ctx->TessCtrlProgram.patch_vertices) 240bf215546Sopenharmony_ci return false; 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci default: 243bf215546Sopenharmony_ci return false; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci /* Merge draws. */ 247bf215546Sopenharmony_ci *count0 += count1; 248bf215546Sopenharmony_ci *end0 = end1; 249bf215546Sopenharmony_ci return true; 250bf215546Sopenharmony_ci} 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci/** 253bf215546Sopenharmony_ci * Copy zero, one or two vertices from the current vertex buffer into 254bf215546Sopenharmony_ci * the temporary "copy" buffer. 255bf215546Sopenharmony_ci * This is used when a single primitive overflows a vertex buffer and 256bf215546Sopenharmony_ci * we need to continue the primitive in a new vertex buffer. 257bf215546Sopenharmony_ci * The temporary "copy" buffer holds the vertices which need to get 258bf215546Sopenharmony_ci * copied from the old buffer to the new one. 259bf215546Sopenharmony_ci */ 260bf215546Sopenharmony_ciunsigned 261bf215546Sopenharmony_civbo_copy_vertices(struct gl_context *ctx, 262bf215546Sopenharmony_ci GLenum mode, 263bf215546Sopenharmony_ci unsigned start, unsigned *pcount, bool begin, 264bf215546Sopenharmony_ci unsigned vertex_size, 265bf215546Sopenharmony_ci bool in_dlist, 266bf215546Sopenharmony_ci fi_type *dst, 267bf215546Sopenharmony_ci const fi_type *src) 268bf215546Sopenharmony_ci{ 269bf215546Sopenharmony_ci const unsigned count = *pcount; 270bf215546Sopenharmony_ci unsigned copy = 0; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci switch (mode) { 273bf215546Sopenharmony_ci case GL_POINTS: 274bf215546Sopenharmony_ci return 0; 275bf215546Sopenharmony_ci case GL_LINES: 276bf215546Sopenharmony_ci copy = count % 2; 277bf215546Sopenharmony_ci break; 278bf215546Sopenharmony_ci case GL_TRIANGLES: 279bf215546Sopenharmony_ci copy = count % 3; 280bf215546Sopenharmony_ci break; 281bf215546Sopenharmony_ci case GL_QUADS: 282bf215546Sopenharmony_ci case GL_LINES_ADJACENCY: 283bf215546Sopenharmony_ci copy = count % 4; 284bf215546Sopenharmony_ci break; 285bf215546Sopenharmony_ci case GL_TRIANGLES_ADJACENCY: 286bf215546Sopenharmony_ci copy = count % 6; 287bf215546Sopenharmony_ci break; 288bf215546Sopenharmony_ci case GL_LINE_STRIP: 289bf215546Sopenharmony_ci copy = MIN2(1, count); 290bf215546Sopenharmony_ci break; 291bf215546Sopenharmony_ci case GL_LINE_STRIP_ADJACENCY: 292bf215546Sopenharmony_ci /* We need to copy 3 vertices, because: 293bf215546Sopenharmony_ci * Last strip: ---o---o---x (last line) 294bf215546Sopenharmony_ci * Next strip: x---o---o--- (next line) 295bf215546Sopenharmony_ci */ 296bf215546Sopenharmony_ci copy = MIN2(3, count); 297bf215546Sopenharmony_ci break; 298bf215546Sopenharmony_ci case GL_PATCHES: 299bf215546Sopenharmony_ci if (in_dlist) { 300bf215546Sopenharmony_ci /* We don't know the value of GL_PATCH_VERTICES when compiling 301bf215546Sopenharmony_ci * a display list. 302bf215546Sopenharmony_ci * 303bf215546Sopenharmony_ci * Fail an assertion in debug builds and use the value of 3 304bf215546Sopenharmony_ci * in release builds, which is more likely than any other value. 305bf215546Sopenharmony_ci */ 306bf215546Sopenharmony_ci assert(!"patch_vertices is unknown"); 307bf215546Sopenharmony_ci copy = count % 3; 308bf215546Sopenharmony_ci } else { 309bf215546Sopenharmony_ci copy = count % ctx->TessCtrlProgram.patch_vertices; 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci break; 312bf215546Sopenharmony_ci case GL_LINE_LOOP: 313bf215546Sopenharmony_ci if (!in_dlist && begin == 0) { 314bf215546Sopenharmony_ci /* We're dealing with the second or later section of a split/wrapped 315bf215546Sopenharmony_ci * GL_LINE_LOOP. Since we're converting line loops to line strips, 316bf215546Sopenharmony_ci * we've already incremented the last_prim->start counter by one to 317bf215546Sopenharmony_ci * skip the 0th vertex in the loop. We need to undo that (effectively 318bf215546Sopenharmony_ci * subtract one from last_prim->start) so that we copy the 0th vertex 319bf215546Sopenharmony_ci * to the next vertex buffer. 320bf215546Sopenharmony_ci */ 321bf215546Sopenharmony_ci assert(start > 0); 322bf215546Sopenharmony_ci src -= vertex_size; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci FALLTHROUGH; 325bf215546Sopenharmony_ci case GL_TRIANGLE_FAN: 326bf215546Sopenharmony_ci case GL_POLYGON: 327bf215546Sopenharmony_ci if (count == 0) { 328bf215546Sopenharmony_ci return 0; 329bf215546Sopenharmony_ci } else if (count == 1) { 330bf215546Sopenharmony_ci memcpy(dst, src + 0, vertex_size * sizeof(GLfloat)); 331bf215546Sopenharmony_ci return 1; 332bf215546Sopenharmony_ci } else { 333bf215546Sopenharmony_ci memcpy(dst, src + 0, vertex_size * sizeof(GLfloat)); 334bf215546Sopenharmony_ci memcpy(dst + vertex_size, src + (count - 1) * vertex_size, 335bf215546Sopenharmony_ci vertex_size * sizeof(GLfloat)); 336bf215546Sopenharmony_ci return 2; 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci case GL_TRIANGLE_STRIP: 339bf215546Sopenharmony_ci /* Draw an even number of triangles to keep front/back facing the same. */ 340bf215546Sopenharmony_ci *pcount -= count % 2; 341bf215546Sopenharmony_ci FALLTHROUGH; 342bf215546Sopenharmony_ci case GL_QUAD_STRIP: 343bf215546Sopenharmony_ci if (count <= 1) 344bf215546Sopenharmony_ci copy = count; 345bf215546Sopenharmony_ci else 346bf215546Sopenharmony_ci copy = 2 + (count % 2); 347bf215546Sopenharmony_ci break; 348bf215546Sopenharmony_ci case PRIM_OUTSIDE_BEGIN_END: 349bf215546Sopenharmony_ci return 0; 350bf215546Sopenharmony_ci case GL_TRIANGLE_STRIP_ADJACENCY: 351bf215546Sopenharmony_ci /* TODO: Splitting tri strips with adjacency is too complicated. */ 352bf215546Sopenharmony_ci default: 353bf215546Sopenharmony_ci unreachable("Unexpected primitive type"); 354bf215546Sopenharmony_ci return 0; 355bf215546Sopenharmony_ci } 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci memcpy(dst, src + (count - copy) * vertex_size, 358bf215546Sopenharmony_ci copy * vertex_size * sizeof(GLfloat)); 359bf215546Sopenharmony_ci return copy; 360bf215546Sopenharmony_ci} 361