/* Material */ void GLAPIENTRY _mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) { GET_CURRENT_CONTEXT(ctx); GLint i, nr; struct gl_material *mat = &ctx->Light.Material; GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0, "_mesa_noop_Materialfv" ); if (ctx->Light.ColorMaterialEnabled) bitmask &= ~ctx->Light.ColorMaterialBitmask; if (bitmask == 0) return; switch (pname) { case GL_SHININESS: nr = 1; break; case GL_COLOR_INDEXES: nr = 3; break; default: nr = 4 ; break; } for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) if (bitmask & (1<<i)) COPY_SZ_4V( mat->Attrib[i], nr, params ); _mesa_update_material( ctx, bitmask ); }
static void _playback_copy_to_current( GLcontext *ctx, const struct tnl_vertex_list *node ) { TNLcontext *tnl = TNL_CONTEXT(ctx); const GLfloat *data; GLuint i; if (node->count) data = node->buffer + (node->count-1) * node->vertex_size; else data = node->buffer; for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) { if (node->attrsz[i]) { ASSIGN_4V(tnl->vtx.current[i], 0, 0, 0, 1); COPY_SZ_4V(tnl->vtx.current[i], node->attrsz[i], data); data += node->attrsz[i]; } } /* Edgeflag requires special treatment: */ if (node->attrsz[_TNL_ATTRIB_EDGEFLAG]) { ctx->Current.EdgeFlag = (data[0] == 1.0); } /* Colormaterial -- this kindof sucks. */ if (ctx->Light.ColorMaterialEnabled) { _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); } if (node->have_materials) { tnl->Driver.NotifyMaterialChange( ctx ); } /* CurrentExecPrimitive */ if (node->prim_count) { GLenum mode = node->prim[node->prim_count - 1].mode; if (mode & PRIM_END) ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; else ctx->Driver.CurrentExecPrimitive = (mode & PRIM_MODE_MASK); } }
void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u) { GLuint attr; for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { struct gl_1d_map *map = exec->eval.map1[attr].map; if (map) { GLfloat uu = (u - map->u1) * map->du; GLfloat data[4]; ASSIGN_4V(data, 0, 0, 0, 1); _math_horner_bezier_curve(map->Points, data, uu, exec->eval.map1[attr].sz, map->Order); COPY_SZ_4V( exec->vtx.attrptr[attr], exec->vtx.attrsz[attr], data ); } } /** Vertex -- EvalCoord1f is a noop if this map not enabled: **/ if (exec->eval.map1[0].map) { struct gl_1d_map *map = exec->eval.map1[0].map; GLfloat uu = (u - map->u1) * map->du; GLfloat vertex[4]; ASSIGN_4V(vertex, 0, 0, 0, 1); _math_horner_bezier_curve(map->Points, vertex, uu, exec->eval.map1[0].sz, map->Order); if (exec->eval.map1[0].sz == 4) CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); else CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); } }
static void feedback_vertex( GLcontext *ctx, GLuint v, GLuint pv ) { GLfloat win[4]; GLfloat color[4]; GLfloat tc[4]; GLuint texUnit = ctx->Texture.CurrentTransformUnit; const struct vertex_buffer *VB = ctx->VB; GLuint index; win[0] = VB->Win.data[v][0]; win[1] = VB->Win.data[v][1]; win[2] = VB->Win.data[v][2] / ctx->Visual->DepthMaxF; win[3] = 1.0 / VB->Win.data[v][3]; if (ctx->Light.ShadeModel == GL_SMOOTH) pv = v; UBYTE_RGBA_TO_FLOAT_RGBA( color, VB->ColorPtr->data[pv] ); if (VB->TexCoordPtr[texUnit]->size == 4 && VB->TexCoordPtr[texUnit]->data[v][3] != 0.0) { GLfloat invq = 1.0F / VB->TexCoordPtr[texUnit]->data[v][3]; tc[0] = VB->TexCoordPtr[texUnit]->data[v][0] * invq; tc[1] = VB->TexCoordPtr[texUnit]->data[v][1] * invq; tc[2] = VB->TexCoordPtr[texUnit]->data[v][2] * invq; tc[3] = VB->TexCoordPtr[texUnit]->data[v][3]; } else { ASSIGN_4V(tc, 0,0,0,1); COPY_SZ_4V(tc, VB->TexCoordPtr[texUnit]->size, VB->TexCoordPtr[texUnit]->data[v]); } if (VB->IndexPtr) index = VB->IndexPtr->data[v]; else index = 0; gl_feedback_vertex( ctx, win, color, index, tc ); }
static void _save_copy_to_current( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint i; for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) { if (tnl->save.attrsz[i]) { tnl->save.currentsz[i][0] = tnl->save.attrsz[i]; ASSIGN_4V(tnl->save.current[i], 0, 0, 0, 1); COPY_SZ_4V(tnl->save.current[i], tnl->save.attrsz[i], tnl->save.attrptr[i]); } } /* Edgeflag requires special treatment: */ if (tnl->save.attrsz[_TNL_ATTRIB_EDGEFLAG]) { ctx->ListState.ActiveEdgeFlag = 1; ctx->ListState.CurrentEdgeFlag = (tnl->save.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0); } }
/* Flush existing data, set new attrib size, replay copied vertices. */ static void _save_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint oldsz; GLuint i; GLfloat *tmp; /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ if (save->vert_count) _save_wrap_buffers( ctx ); else assert( save->copied.nr == 0 ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _save_copy_to_current( ctx ); /* Fix up sizes: */ oldsz = save->attrsz[attr]; save->attrsz[attr] = newsz; save->vertex_size += newsz - oldsz; save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / save->vertex_size); save->vert_count = 0; /* Recalculate all the attrptr[] values: */ for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) { if (save->attrsz[i]) { save->attrptr[i] = tmp; tmp += save->attrsz[i]; } else save->attrptr[i] = NULL; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ _save_copy_from_current( ctx ); /* Replay stored vertices to translate them to new format here. * * If there are copied vertices and the new (upgraded) attribute * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ if (save->copied.nr) { GLfloat *data = save->copied.buffer; GLfloat *dest = save->buffer; GLuint j; /* Need to note this and fix up at runtime (or loopback): */ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { assert(oldsz == 0); save->dangling_attr_ref = GL_TRUE; } for (i = 0 ; i < save->copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { if (save->attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, save->current[attr] ); dest += newsz; } } else { GLint sz = save->attrsz[j]; COPY_SZ_4V( dest, sz, data ); data += sz; dest += sz; } } } } save->vbptr = dest; save->vert_count += save->copied.nr; } }
/** * Flush existing data, set new attrib size, replay copied vertices. * This is called when we transition from a small vertex attribute size * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. * We need to go back over the previous 2-component texcoords and insert * zero and one values. */ static void vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); const GLint lastcount = exec->vtx.vert_count; fi_type *old_attrptr[VBO_ATTRIB_MAX]; const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (unlikely(exec->vtx.copied.nr)) { /* We're in the middle of a primitive, keep the old vertex * format around to be able to translate the copied vertices to * the new format. */ memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } if (unlikely(oldSize)) { /* Do a COPY_TO_CURRENT to ensure back-copying works for the * case when the attribute already exists in the vertex and is * having its size increased. */ vbo_exec_copy_to_current( exec ); } /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (!_mesa_inside_begin_end(ctx) && !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ exec->vtx.attrsz[attr] = newSize; exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = vbo_compute_max_verts(exec); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.enabled |= BITFIELD64_BIT(attr); if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ fi_type *tmp = exec->vtx.vertex; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct * values. */ vbo_exec_copy_from_current( exec ); } else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (unlikely(exec->vtx.copied.nr)) { fi_type *data = exec->vtx.copied.buffer; fi_type *dest = exec->vtx.buffer_ptr; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { GLbitfield64 enabled = exec->vtx.enabled; while (enabled) { const int j = u_bit_scan64(&enabled); GLuint sz = exec->vtx.attrsz[j]; GLint old_offset = old_attrptr[j] - exec->vtx.vertex; GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; assert(sz); if (j == attr) { if (oldSize) { fi_type tmp[4]; COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize, data + old_offset, exec->vtx.attrtype[j]); COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { fi_type *current = (fi_type *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); } } else { COPY_SZ_4V(dest + new_offset, sz, data + old_offset); } } data += old_vtx_size; dest += exec->vtx.vertex_size; } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }
/** * Flush existing data, set new attrib size, replay copied vertices. * This is called when we transition from a small vertex attribute size * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. * We need to go back over the previous 2-component texcoords and insert * zero and one values. */ static void vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); const GLint lastcount = exec->vtx.vert_count; GLfloat *old_attrptr[VBO_ATTRIB_MAX]; const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (unlikely(exec->vtx.copied.nr)) { /* We're in the middle of a primitive, keep the old vertex * format around to be able to translate the copied vertices to * the new format. */ memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } if (unlikely(oldSize)) { /* Do a COPY_TO_CURRENT to ensure back-copying works for the * case when the attribute already exists in the vertex and is * having its size increased. */ vbo_exec_copy_to_current( exec ); } /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ exec->vtx.attrsz[attr] = newSize; exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ GLfloat *tmp = exec->vtx.vertex; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct * values. */ vbo_exec_copy_from_current( exec ); } else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (unlikely(exec->vtx.copied.nr)) { GLfloat *data = exec->vtx.copied.buffer; GLfloat *dest = exec->vtx.buffer_ptr; GLuint j; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { GLuint sz = exec->vtx.attrsz[j]; if (sz) { GLint old_offset = old_attrptr[j] - exec->vtx.vertex; GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; if (j == attr) { if (oldSize) { GLfloat tmp[4]; COPY_CLEAN_4V(tmp, oldSize, data + old_offset); COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); } } else { COPY_SZ_4V(dest + new_offset, sz, data + old_offset); } } } data += old_vtx_size; dest += exec->vtx.vertex_size; } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }
/* Flush existing data, set new attrib size, replay copied vertices. */ static void _tnl_wrap_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint oldsz; GLuint i; GLfloat *tmp; GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter; /* Run pipeline on current vertices, copy wrapped vertices * to tnl->vtx.copied. */ _tnl_wrap_buffers( ctx ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _tnl_copy_to_current( ctx ); /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && tnl->vtx.attrsz[attr] == 0 && lastcount > 8 && tnl->vtx.vertex_size) { reset_attrfv( tnl ); } /* Fix up sizes: */ oldsz = tnl->vtx.attrsz[attr]; tnl->vtx.attrsz[attr] = newsz; tnl->vtx.vertex_size += newsz - oldsz; tnl->vtx.counter = MIN2( VERT_BUFFER_SIZE / tnl->vtx.vertex_size, ctx->Const.MaxArrayLockSize ); tnl->vtx.initial_counter = tnl->vtx.counter; tnl->vtx.vbptr = tnl->vtx.buffer; /* Recalculate all the attrptr[] values */ for (i = 0, tmp = tnl->vtx.vertex ; i < _TNL_ATTRIB_MAX ; i++) { if (tnl->vtx.attrsz[i]) { tnl->vtx.attrptr[i] = tmp; tmp += tnl->vtx.attrsz[i]; } else tnl->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct values. */ _tnl_copy_from_current( ctx ); /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (tnl->vtx.copied.nr) { GLfloat *data = tnl->vtx.copied.buffer; GLfloat *dest = tnl->vtx.buffer; GLuint j; for (i = 0 ; i < tnl->vtx.copied.nr ; i++) { for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { if (tnl->vtx.attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] ); dest += newsz; } } else { GLuint sz = tnl->vtx.attrsz[j]; COPY_SZ_4V( dest, sz, data ); dest += sz; data += sz; } } } } tnl->vtx.vbptr = dest; tnl->vtx.counter -= tnl->vtx.copied.nr; tnl->vtx.copied.nr = 0; } /* For codegen - attrptr's may have changed, so need to redo * codegen. Might be a reasonable place to try & detect attributes * in the vertex which aren't being submitted any more. */ for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) if (tnl->vtx.attrsz[i]) { GLuint j = tnl->vtx.attrsz[i] - 1; if (i < _TNL_MAX_ATTR_CODEGEN) tnl->vtx.tabfv[i][j] = choose[i][j]; } }
/* Flush existing data, set new attrib size, replay copied vertices. */ static void _save_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint oldsz; GLuint i; GLfloat *tmp; /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ if (tnl->save.initial_counter != tnl->save.counter) _save_wrap_buffers( ctx ); else assert( tnl->save.copied.nr == 0 ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _save_copy_to_current( ctx ); /* Fix up sizes: */ oldsz = tnl->save.attrsz[attr]; tnl->save.attrsz[attr] = newsz; tnl->save.vertex_size += newsz - oldsz; tnl->save.counter = ((SAVE_BUFFER_SIZE - tnl->save.vertex_store->used) / tnl->save.vertex_size); if (tnl->save.counter > ctx->Const.MaxArrayLockSize ) tnl->save.counter = ctx->Const.MaxArrayLockSize; tnl->save.initial_counter = tnl->save.counter; /* Recalculate all the attrptr[] values: */ for (i = 0, tmp = tnl->save.vertex ; i < _TNL_ATTRIB_MAX ; i++) { if (tnl->save.attrsz[i]) { tnl->save.attrptr[i] = tmp; tmp += tnl->save.attrsz[i]; } else tnl->save.attrptr[i] = 0; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ _save_copy_from_current( ctx ); /* Replay stored vertices to translate them to new format here. * * If there are copied vertices and the new (upgraded) attribute * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ if (tnl->save.copied.nr) { GLfloat *data = tnl->save.copied.buffer; GLfloat *dest = tnl->save.buffer; GLuint j; /* Need to note this and fix up at runtime (or loopback): */ if (tnl->save.currentsz[attr][0] == 0) { assert(oldsz == 0); tnl->save.dangling_attr_ref = GL_TRUE; _mesa_debug(0, "_save_upgrade_vertex: dangling reference attr %d\n", attr); #if 0 /* The current strategy is to punt these degenerate cases * through _tnl_loopback_vertex_list(), a lower-performance * option. To minimize the impact of this, artificially * reduce the size of this vertex_list. */ if (t->save.counter > 10) { t->save.initial_counter = 10; t->save.counter = 10; } #endif } for (i = 0 ; i < tnl->save.copied.nr ; i++) { for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { if (tnl->save.attrsz[j]) { if (j == attr) { if (oldsz) { ASSIGN_4V( dest, 0, 0, 0, 1 ); COPY_SZ_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, tnl->save.current[attr] ); dest += newsz; } } else { GLint sz = tnl->save.attrsz[j]; COPY_SZ_4V( dest, sz, data ); data += sz; dest += sz; } } } } tnl->save.vbptr = dest; tnl->save.counter -= tnl->save.copied.nr; } }
void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, GLfloat u, GLfloat v ) { GLuint attr; for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { struct gl_2d_map *map = exec->eval.map2[attr].map; if (map) { GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat data[4]; ASSIGN_4V(data, 0, 0, 0, 1); _math_horner_bezier_surf(map->Points, data, uu, vv, exec->eval.map2[attr].sz, map->Uorder, map->Vorder); COPY_SZ_4V( exec->vtx.attrptr[attr], exec->vtx.attrsz[attr], data ); } } /** Vertex -- EvalCoord2f is a noop if this map not enabled: **/ if (exec->eval.map2[0].map) { struct gl_2d_map *map = exec->eval.map2[0].map; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat vertex[4]; ASSIGN_4V(vertex, 0, 0, 0, 1); if (exec->ctx->Eval.AutoNormal) { GLfloat normal[4]; GLfloat du[4], dv[4]; _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); if (exec->eval.map2[0].sz == 4) { du[0] = du[0]*vertex[3] - du[3]*vertex[0]; du[1] = du[1]*vertex[3] - du[3]*vertex[1]; du[2] = du[2]*vertex[3] - du[3]*vertex[2]; dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; } CROSS3(normal, du, dv); NORMALIZE_3FV(normal); normal[3] = 1.0; COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL], exec->vtx.attrsz[VBO_ATTRIB_NORMAL], normal ); } else { _math_horner_bezier_surf(map->Points, vertex, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); } if (exec->vtx.attrsz[0] == 4) CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); else CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); } }
/** * Flush existing data, set new attrib size, replay copied vertices. */ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, GLuint attr, GLuint newsz ) { GLcontext *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLint lastcount = exec->vtx.vert_count; GLfloat *tmp; GLuint oldsz; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ vbo_exec_copy_to_current( exec ); /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && exec->vtx.attrsz[attr] == 0 && lastcount > 8 && exec->vtx.vertex_size) { reset_attrfv( exec ); } /* Fix up sizes: */ oldsz = exec->vtx.attrsz[attr]; exec->vtx.attrsz[attr] = newsz; exec->vtx.vertex_size += newsz - oldsz; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; /* Recalculate all the attrptr[] values */ for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct values. */ vbo_exec_copy_from_current( exec ); /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (exec->vtx.copied.nr) { GLfloat *data = exec->vtx.copied.buffer; GLfloat *dest = exec->vtx.buffer_ptr; GLuint j; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { if (exec->vtx.attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V( dest, newsz, current ); dest += newsz; } } else { GLuint sz = exec->vtx.attrsz[j]; COPY_SZ_4V( dest, sz, data ); dest += sz; data += sz; } } } } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }