/* Treat the vertex storage as a VBO, define vertex arrays pointing * into it: */ static void vbo_bind_vertex_list( GLcontext *ctx, const struct vbo_save_vertex_list *node ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; struct gl_client_array *arrays = save->arrays; GLuint data = node->buffer_offset; const GLuint *map; GLuint attr; /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(ctx)) { case VP_NONE: memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); map = vbo->map_vp_none; break; case VP_NV: case VP_ARB: /* The aliasing of attributes for NV vertex programs has already * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); map = vbo->map_vp_arb; break; } for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { GLuint src = map[attr]; if (node->attrsz[src]) { arrays[attr].Ptr = (const GLubyte *)data; arrays[attr].Size = node->attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Enabled = 1; arrays[attr].BufferObj = node->vertex_store->bufferobj; arrays[attr]._MaxElement = node->count; /* ??? */ assert(arrays[attr].BufferObj->Name); data += node->attrsz[src] * sizeof(GLfloat); } } }
static void bind_arrays( GLcontext *ctx ) { #if 0 if (ctx->Array.ArrayObj.Name != exec->array.array_obj) { bind_array_obj(ctx); recalculate_input_bindings(ctx); } else if (exec->array.program_mode != get_program_mode(ctx) || exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) { recalculate_input_bindings(ctx); } #else bind_array_obj(ctx); recalculate_input_bindings(ctx); #endif }
/** * Set the vbo->exec->inputs[] pointers to point to the enabled * vertex arrays. This depends on the current vertex program/shader * being executed because of whether or not generic vertex arrays * alias the conventional vertex arrays. * For arrays that aren't enabled, we set the input[attrib] pointer * to point at a zero-stride current value "array". */ static void recalculate_input_bindings(struct gl_context *ctx) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib; const struct gl_client_array **inputs = &exec->array.inputs[0]; GLbitfield64 const_inputs = 0x0; GLuint i; switch (get_program_mode(ctx)) { case VP_NONE: /* When no vertex program is active (or the vertex program is generated * from fixed-function state). We put the material values into the * generic slots. This is the only situation where material values * are available as per-vertex attributes. */ for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; else { inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; const_inputs |= VERT_BIT(i); } } for (i = 0; i < MAT_ATTRIB_MAX; i++) { inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i]; const_inputs |= VERT_BIT_GENERIC(i); } /* Could use just about anything, just to fill in the empty * slots: */ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) { inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; const_inputs |= VERT_BIT_GENERIC(i); } break; case VP_ARB: /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0] * attribute array aliases and overrides the legacy position array. * * Otherwise, legacy attributes available in the legacy slots, * generic attributes in the generic slots and materials are not * available as per-vertex attributes. */ if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; else if (vertexAttrib[VERT_ATTRIB_POS].Enabled) inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; else { inputs[0] = &vbo->currval[VBO_ATTRIB_POS]; const_inputs |= VERT_BIT_POS; } for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; else { inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; const_inputs |= VERT_BIT_FF(i); } } for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; else { inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; const_inputs |= VERT_BIT_GENERIC(i); } } inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; break; } _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) ); ctx->NewDriverState |= ctx->DriverFlags.NewArray; }
/* TODO: populate these as the vertex is defined: */ static void vbo_exec_bind_arrays( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *arrays = exec->vtx.arrays; const GLuint count = exec->vtx.vert_count; const GLuint *map; GLuint attr; GLbitfield64 varying_inputs = 0x0; /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(exec->ctx)) { case VP_NONE: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->mat_currval[attr]; } map = vbo->map_vp_none; break; case VP_NV: case VP_ARB: /* The aliasing of attributes for NV vertex programs has already * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; } for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->generic_currval[attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { exec->vtx.inputs[VERT_ATTRIB_GENERIC0] = exec->vtx.inputs[0]; exec->vtx.attrsz[VERT_ATTRIB_GENERIC0] = exec->vtx.attrsz[0]; exec->vtx.attrptr[VERT_ATTRIB_GENERIC0] = exec->vtx.attrptr[0]; exec->vtx.attrsz[0] = 0; } break; default: assert(0); } /* Make all active attributes (including edgeflag) available as * arrays of floats. */ for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { const GLuint src = map[attr]; if (exec->vtx.attrsz[src]) { GLsizeiptr offset = (GLbyte *)exec->vtx.attrptr[src] - (GLbyte *)exec->vtx.vertex; /* override the default array set above */ ASSERT(attr < Elements(exec->vtx.inputs)); ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */ exec->vtx.inputs[attr] = &arrays[attr]; if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ assert(offset >= 0); arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset; } else { /* Ptr into ordinary app memory */ arrays[attr].Ptr = (GLubyte *)exec->vtx.buffer_map + offset; } arrays[attr].Size = exec->vtx.attrsz[src]; arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Format = GL_RGBA; arrays[attr].Enabled = 1; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, exec->vtx.bufferobj); arrays[attr]._MaxElement = count; /* ??? */ varying_inputs |= VERT_BIT(attr); ctx->NewState |= _NEW_ARRAY; } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); }
static void recalculate_input_bindings( GLcontext *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; const struct gl_client_array **inputs = &exec->array.inputs[0]; GLuint i; exec->array.program_mode = get_program_mode(ctx); exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; switch (exec->array.program_mode) { case VP_NONE: /* When no vertex program is active, we put the material values * into the generic slots. This is the only situation where * material values are available as per-vertex attributes. */ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else inputs[i] = &vbo->legacy_currval[i]; } for (i = 0; i < MAT_ATTRIB_MAX; i++) { inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; } /* Could use just about anything, just to fill in the empty * slots: */ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; break; case VP_NV: /* NV_vertex_program - attribute arrays alias and override * conventional, legacy arrays. No materials, and the generic * slots are vacant. */ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.generic_array[i]->Enabled) inputs[i] = exec->array.generic_array[i]; else if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else inputs[i] = &vbo->legacy_currval[i]; } /* Could use just about anything, just to fill in the empty * slots: */ for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; break; case VP_ARB: /* ARB_vertex_program - Only the attribute zero (position) array * aliases and overrides the legacy position array. * * Otherwise, legacy attributes available in the legacy slots, * generic attributes in the generic slots and materials are not * available as per-vertex attributes. */ if (exec->array.generic_array[0]->Enabled) inputs[0] = exec->array.generic_array[0]; else if (exec->array.legacy_array[0]->Enabled) inputs[0] = exec->array.legacy_array[0]; else inputs[0] = &vbo->legacy_currval[0]; for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; else inputs[i] = &vbo->legacy_currval[i]; } for (i = 0; i < 16; i++) { if (exec->array.generic_array[i]->Enabled) inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; else inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; } break; } }
/** * Treat the vertex storage as a VBO, define vertex arrays pointing * into it: */ static void vbo_bind_vertex_list(struct gl_context *ctx, const struct vbo_save_vertex_list *node) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; struct gl_client_array *arrays = save->arrays; GLuint buffer_offset = node->buffer_offset; const GLuint *map; GLuint attr; GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */ GLenum node_attrtype[VBO_ATTRIB_MAX]; /* copy of node->attrtype[] */ GLbitfield64 varying_inputs = 0x0; memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype)); /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(ctx)) { case VP_NONE: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr]; } map = vbo->map_vp_none; break; case VP_ARB: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) { save->inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_GENERIC0+attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { save->inputs[VERT_ATTRIB_GENERIC0] = save->inputs[0]; node_attrsz[VERT_ATTRIB_GENERIC0] = node_attrsz[0]; node_attrtype[VERT_ATTRIB_GENERIC0] = node_attrtype[0]; node_attrsz[0] = 0; } break; default: assert(0); } for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { const GLuint src = map[attr]; if (node_attrsz[src]) { /* override the default array set above */ save->inputs[attr] = &arrays[attr]; arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; arrays[attr].Size = node_attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = node_attrtype[src]; arrays[attr].Integer = vbo_attrtype_to_integer_flag(node_attrtype[src]); arrays[attr].Format = GL_RGBA; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, node->vertex_store->bufferobj); assert(arrays[attr].BufferObj->Name); buffer_offset += node_attrsz[src] * sizeof(GLfloat); varying_inputs |= VERT_BIT(attr); } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); ctx->NewDriverState |= ctx->DriverFlags.NewArray; }
/** * Treat the vertex storage as a VBO, define vertex arrays pointing * into it: */ static void vbo_bind_vertex_list(struct gl_context *ctx, const struct vbo_save_vertex_list *node) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; struct gl_client_array *arrays = save->arrays; GLuint buffer_offset = node->buffer_offset; const GLuint *map; GLuint attr; GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */ GLbitfield varying_inputs = 0x0; memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz)); /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(ctx)) { case VP_NONE: for (attr = 0; attr < 16; attr++) { save->inputs[attr] = &vbo->legacy_currval[attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { save->inputs[attr + 16] = &vbo->mat_currval[attr]; } map = vbo->map_vp_none; break; case VP_NV: case VP_ARB: /* The aliasing of attributes for NV vertex programs has already * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ for (attr = 0; attr < 16; attr++) { save->inputs[attr] = &vbo->legacy_currval[attr]; save->inputs[attr + 16] = &vbo->generic_currval[attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { save->inputs[16] = save->inputs[0]; node_attrsz[16] = node_attrsz[0]; node_attrsz[0] = 0; } break; default: assert(0); } for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { const GLuint src = map[attr]; if (node_attrsz[src]) { /* override the default array set above */ save->inputs[attr] = &arrays[attr]; arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset; arrays[attr].Size = node->attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Format = GL_RGBA; arrays[attr].Enabled = 1; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, node->vertex_store->bufferobj); arrays[attr]._MaxElement = node->count; /* ??? */ assert(arrays[attr].BufferObj->Name); buffer_offset += node->attrsz[src] * sizeof(GLfloat); varying_inputs |= 1<<attr; ctx->NewState |= _NEW_ARRAY; } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); }
/* TODO: populate these as the vertex is defined: */ static void vbo_exec_bind_arrays( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct gl_client_array *arrays = exec->vtx.arrays; const GLuint *map; GLuint attr; GLbitfield64 varying_inputs = 0x0; /* Install the default (ie Current) attributes first, then overlay * all active ones. */ switch (get_program_mode(exec->ctx)) { case VP_NONE: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr]; } map = vbo->map_vp_none; break; case VP_ARB: for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) { exec->vtx.inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr]; } for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) { ASSERT(VERT_ATTRIB_GENERIC(attr) < Elements(exec->vtx.inputs)); exec->vtx.inputs[VERT_ATTRIB_GENERIC(attr)] = &vbo->currval[VBO_ATTRIB_GENERIC0+attr]; } map = vbo->map_vp_arb; /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read. * In that case we effectively need to route the data from * glVertexAttrib(0, val) calls to feed into the GENERIC0 input. */ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 && (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) { exec->vtx.inputs[VERT_ATTRIB_GENERIC0] = exec->vtx.inputs[0]; exec->vtx.attrsz[VERT_ATTRIB_GENERIC0] = exec->vtx.attrsz[0]; exec->vtx.attrptr[VERT_ATTRIB_GENERIC0] = exec->vtx.attrptr[0]; exec->vtx.attrsz[0] = 0; } break; default: assert(0); } for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { const GLuint src = map[attr]; if (exec->vtx.attrsz[src]) { GLsizeiptr offset = (GLbyte *)exec->vtx.attrptr[src] - (GLbyte *)exec->vtx.vertex; /* override the default array set above */ ASSERT(attr < Elements(exec->vtx.inputs)); ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */ exec->vtx.inputs[attr] = &arrays[attr]; if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ assert(exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Pointer); assert(offset >= 0); arrays[attr].Ptr = (GLubyte *) exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Offset + offset; } else { /* Ptr into ordinary app memory */ arrays[attr].Ptr = (GLubyte *)exec->vtx.buffer_map + offset; } arrays[attr].Size = exec->vtx.attrsz[src]; arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = exec->vtx.attrtype[src]; arrays[attr].Integer = vbo_attrtype_to_integer_flag(exec->vtx.attrtype[src]); arrays[attr].Format = GL_RGBA; arrays[attr].Enabled = 1; arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat); _mesa_reference_buffer_object(ctx, &arrays[attr].BufferObj, exec->vtx.bufferobj); varying_inputs |= VERT_BIT(attr); } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); ctx->NewDriverState |= ctx->DriverFlags.NewArray; }