X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fvbo%2Fvbo_exec_api.c;h=2f9f3ec7c465797ffde23b81317a7c4726860b2e;hb=1f9a0a4e6e5566c36c781add5f1e62af3efdfb58;hp=f0a7eeadd0f8194a05d34929c0833ff52a066b63;hpb=0c75854cc1650dc870e042aa66a053e70b3d4556;p=mesa.git diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index f0a7eeadd0f..2f9f3ec7c46 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -34,6 +34,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/bufferobj.h" #include "main/context.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "main/vtxfmt.h" #include "main/dlist.h" #include "main/eval.h" @@ -41,7 +42,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/light.h" #include "main/api_arrayelt.h" #include "main/api_noop.h" -#include "glapi/dispatch.h" +#include "main/dispatch.h" #include "vbo_context.h" @@ -126,8 +127,8 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { - _mesa_memcpy( exec->vtx.buffer_ptr, data, - exec->vtx.vertex_size * sizeof(GLfloat)); + memcpy( exec->vtx.buffer_ptr, data, + exec->vtx.vertex_size * sizeof(GLfloat)); exec->vtx.buffer_ptr += exec->vtx.vertex_size; data += exec->vtx.vertex_size; exec->vtx.vert_count++; @@ -142,7 +143,7 @@ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) */ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; + struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLuint i; @@ -158,8 +159,7 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) exec->vtx.attrsz[i], exec->vtx.attrptr[i]); - if (memcmp(current, tmp, sizeof(tmp)) != 0) - { + if (memcmp(current, tmp, sizeof(tmp)) != 0) { memcpy(current, tmp, sizeof(tmp)); /* Given that we explicitly state size here, there is no need @@ -191,14 +191,18 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) } -static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) +/** + * Copy current vertex attribute values into the current vertex. + */ +static void +vbo_exec_copy_from_current(struct vbo_exec_context *exec) { - GLcontext *ctx = exec->ctx; + struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLint i; - for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { - const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { + const GLfloat *current = (GLfloat *) vbo->currval[i].Ptr; switch (exec->vtx.attrsz[i]) { case 4: exec->vtx.attrptr[i][3] = current[3]; case 3: exec->vtx.attrptr[i][2] = current[2]; @@ -212,16 +216,21 @@ static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) /** * 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 newsz ) +static void +vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, + GLuint attr, GLuint newSize ) { - GLcontext *ctx = exec->ctx; + struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); - GLint lastcount = exec->vtx.vert_count; - GLfloat *tmp; - GLuint oldsz; + 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 @@ -229,86 +238,103 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, */ 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)); + } - /* 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 ); - + 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 && - exec->vtx.attrsz[attr] == 0 && - lastcount > 8 && - exec->vtx.vertex_size) { + !oldSize && lastcount > 8 && exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ - oldsz = exec->vtx.attrsz[attr]; - exec->vtx.attrsz[attr] = newsz; - - exec->vtx.vertex_size += newsz - oldsz; + 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; - - /* 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]; + 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 */ } - 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 ); + /* 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 (exec->vtx.copied.nr) - { + 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++) { - if (exec->vtx.attrsz[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 (oldsz) { - COPY_CLEAN_4V( dest, oldsz, data ); - data += oldsz; - dest += newsz; + if (oldSize) { + GLfloat tmp[4]; + COPY_CLEAN_4V(tmp, oldSize, data + old_offset); + COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { - const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; - COPY_SZ_4V( dest, newsz, current ); - dest += newsz; + GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; + COPY_SZ_4V(dest + new_offset, sz, current); } } else { - GLuint sz = exec->vtx.attrsz[j]; - COPY_SZ_4V( dest, sz, data ); - dest += sz; - data += sz; + COPY_SZ_4V(dest + new_offset, sz, data + old_offset); } } } + + data += old_vtx_size; + dest += exec->vtx.vertex_size; } exec->vtx.buffer_ptr = dest; @@ -318,70 +344,82 @@ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, } -static void vbo_exec_fixup_vertex( GLcontext *ctx, - GLuint attr, GLuint sz ) +/** + * This is when a vertex attribute transitions to a different size. + * For example, we saw a bunch of glTexCoord2f() calls and now we got a + * glTexCoord4f() call. We promote the array from size=2 to size=4. + */ +static void +vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint newSize) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - int i; - if (sz > exec->vtx.attrsz[attr]) { + if (newSize > exec->vtx.attrsz[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ - vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); + vbo_exec_wrap_upgrade_vertex( exec, attr, newSize ); } - else if (sz < exec->vtx.active_sz[attr]) { + else if (newSize < exec->vtx.active_sz[attr]) { static const GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; /* New size is smaller - just need to fill in some * zeros. Don't need to flush or wrap. */ - for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) + for (i = newSize; i <= exec->vtx.attrsz[attr]; i++) exec->vtx.attrptr[attr][i-1] = id[i-1]; } - exec->vtx.active_sz[attr] = sz; + exec->vtx.active_sz[attr] = newSize; /* Does setting NeedFlush belong here? Necessitates resetting * vtxfmt on each flush (otherwise flags won't get reset * afterwards). */ if (attr == 0) - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } -#if FEATURE_beginend - -/* +/** + * This macro is used to implement all the glVertex, glColor, glTexCoord, + * glVertexAttrib, etc functions. */ -#define ATTR( A, N, V0, V1, V2, V3 ) \ -do { \ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ - \ - if (exec->vtx.active_sz[A] != N) \ - vbo_exec_fixup_vertex(ctx, A, N); \ - \ - { \ - GLfloat *dest = exec->vtx.attrptr[A]; \ - if (N>0) dest[0] = V0; \ - if (N>1) dest[1] = V1; \ - if (N>2) dest[2] = V2; \ - if (N>3) dest[3] = V3; \ - } \ - \ - if ((A) == 0) { \ - GLuint i; \ - \ - for (i = 0; i < exec->vtx.vertex_size; i++) \ - exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ - \ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ + \ + if (unlikely(!(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \ + ctx->Driver.BeginVertices( ctx ); \ + \ + if (unlikely(exec->vtx.active_sz[A] != N)) \ + vbo_exec_fixup_vertex(ctx, A, N); \ + \ + { \ + GLfloat *dest = exec->vtx.attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + /* This is a glVertex call */ \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \ + \ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \ - exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ - \ - if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ - vbo_exec_vtx_wrap( exec ); \ - } \ + \ + /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ + /* something to draw (not just updating a color or texcoord).*/ \ + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ } while (0) @@ -391,7 +429,7 @@ do { \ #include "vbo_attrib_tmp.h" - +#if FEATURE_beginend #if FEATURE_evaluators @@ -414,13 +452,13 @@ static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) } - _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, - exec->vtx.vertex_size * sizeof(GLfloat)); + memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); vbo_exec_do_EvalCoord1f( exec, u ); - _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, - exec->vtx.vertex_size * sizeof(GLfloat)); + memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); } static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) @@ -444,13 +482,13 @@ static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); } - _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, - exec->vtx.vertex_size * sizeof(GLfloat)); + memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); vbo_exec_do_EvalCoord2f( exec, u, v ); - _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, - exec->vtx.vertex_size * sizeof(GLfloat)); + memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); } static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u ) @@ -494,6 +532,24 @@ static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) #endif /* FEATURE_evaluators */ +/** + * Flush (draw) vertices. + * \param unmap - leave VBO unmapped after flushing? + */ +static void +vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, GLboolean unmap) +{ + if (exec->vtx.vert_count || unmap) { + vbo_exec_vtx_flush( exec, unmap ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } +} + + /** * Called via glBegin. */ @@ -520,7 +576,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) * begin/end pairs. */ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) - vbo_exec_FlushVertices_internal( ctx, GL_FALSE ); + vbo_exec_FlushVertices_internal(exec, GL_FALSE); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; @@ -531,6 +587,7 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) exec->vtx.prim[i].pad = 0; exec->vtx.prim[i].start = exec->vtx.vert_count; exec->vtx.prim[i].count = 0; + exec->vtx.prim[i].num_instances = 1; ctx->Driver.CurrentExecPrimitive = mode; } @@ -565,6 +622,28 @@ static void GLAPIENTRY vbo_exec_End( void ) } +/** + * Called via glPrimitiveRestartNV() + */ +static void GLAPIENTRY +vbo_exec_PrimitiveRestartNV(void) +{ + GLenum curPrim; + GET_CURRENT_CONTEXT( ctx ); + + curPrim = ctx->Driver.CurrentExecPrimitive; + + if (curPrim == PRIM_OUTSIDE_BEGIN_END) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" ); + } + else { + vbo_exec_End(); + vbo_exec_Begin(curPrim); + } +} + + + static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) { GLvertexformat *vfmt = &exec->vtxfmt; @@ -573,6 +652,7 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) vfmt->Begin = vbo_exec_Begin; vfmt->End = vbo_exec_End; + vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV; _MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_); _MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_); @@ -632,6 +712,24 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; + /* integer-valued */ + vfmt->VertexAttribI1i = vbo_VertexAttribI1i; + vfmt->VertexAttribI2i = vbo_VertexAttribI2i; + vfmt->VertexAttribI3i = vbo_VertexAttribI3i; + vfmt->VertexAttribI4i = vbo_VertexAttribI4i; + vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv; + vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv; + vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv; + + /* unsigned integer-valued */ + vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui; + vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui; + vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui; + vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui; + vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv; + vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv; + vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv; + vfmt->Materialfv = vbo_Materialfv; vfmt->EdgeFlag = vbo_EdgeFlag; @@ -644,30 +742,6 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) #else /* FEATURE_beginend */ -#define ATTR( A, N, V0, V1, V2, V3 ) \ -do { \ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ - \ - /* FLUSH_UPDATE_CURRENT needs to be set manually */ \ - exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ - \ - if (exec->vtx.active_sz[A] != N) \ - vbo_exec_fixup_vertex(ctx, A, N); \ - \ - { \ - GLfloat *dest = exec->vtx.attrptr[A]; \ - if (N>0) dest[0] = V0; \ - if (N>1) dest[1] = V1; \ - if (N>2) dest[2] = V2; \ - if (N>3) dest[3] = V3; \ - } \ -} while (0) - -#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ) -#define TAG(x) vbo_##x - -#include "vbo_attrib_tmp.h" - static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) { /* silence warnings */ @@ -739,7 +813,7 @@ static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) * This replaces the malloced buffer which was created in * vb_exec_vtx_init() below. */ -void vbo_use_buffer_objects(GLcontext *ctx) +void vbo_use_buffer_objects(struct gl_context *ctx) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; /* Any buffer name but 0 can be used here since this bufferobj won't @@ -759,6 +833,7 @@ void vbo_use_buffer_objects(GLcontext *ctx) } /* Allocate a real buffer object now */ + _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj); } @@ -767,7 +842,7 @@ void vbo_use_buffer_objects(GLcontext *ctx) void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; + struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLuint i; @@ -780,14 +855,14 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) ctx->Shared->NullBufferObj); ASSERT(!exec->vtx.buffer_map); - exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64); + exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); exec->vtx.buffer_ptr = exec->vtx.buffer_map; vbo_exec_vtxfmt_init( exec ); /* Hook our functions into the dispatch table. */ - _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { ASSERT(i < Elements(exec->vtx.attrsz)); @@ -803,8 +878,19 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) { struct gl_client_array *arrays = exec->vtx.arrays; + unsigned i; + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + + for (i = 0; i < 16; ++i) { + arrays[i ].BufferObj = NULL; + arrays[i + 16].BufferObj = NULL; + _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj, + vbo->legacy_currval[i].BufferObj); + _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj, + vbo->generic_currval[i].BufferObj); + } } exec->vtx.vertex_size = 0; @@ -814,7 +900,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) { /* using a real VBO for vertex data */ - GLcontext *ctx = exec->ctx; + struct gl_context *ctx = exec->ctx; unsigned i; /* True VBOs should already be unmapped @@ -823,7 +909,7 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) ASSERT(exec->vtx.bufferobj->Name == 0 || exec->vtx.bufferobj->Name == IMM_BUFFER_NAME); if (exec->vtx.bufferobj->Name == 0) { - ALIGN_FREE(exec->vtx.buffer_map); + _mesa_align_free(exec->vtx.buffer_map); exec->vtx.buffer_map = NULL; exec->vtx.buffer_ptr = NULL; } @@ -837,40 +923,34 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) NULL); } - /* Free the vertex buffer: + /* Free the vertex buffer. Unmap first if needed. */ + if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) { + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj); + } _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); } -void vbo_exec_BeginVertices( GLcontext *ctx ) -{ - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (0) _mesa_printf("%s\n", __FUNCTION__); - vbo_exec_vtx_map( exec ); - - assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); - exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; -} -void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap ) +/** + * Called upon first glVertex, glColor, glTexCoord, etc. + */ +void vbo_exec_BeginVertices( struct gl_context *ctx ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - if (exec->vtx.vert_count || unmap) { - vbo_exec_vtx_flush( exec, unmap ); - } + vbo_exec_vtx_map( exec ); - if (exec->vtx.vertex_size) { - vbo_exec_copy_to_current( exec ); - reset_attrfv( exec ); - } + assert((ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0); + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; } /** + * Called via ctx->Driver.FlushVertices() * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT */ -void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) +void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; @@ -880,10 +960,8 @@ void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) assert(exec->flush_call_depth == 1); #endif - if (0) _mesa_printf("%s\n", __FUNCTION__); - - if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { - if (0) _mesa_printf("%s - inside begin/end\n", __FUNCTION__); + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { + /* We've had glBegin but not glEnd! */ #ifdef DEBUG exec->flush_call_depth--; assert(exec->flush_call_depth == 0); @@ -891,16 +969,12 @@ void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) return; } - vbo_exec_FlushVertices_internal( ctx, GL_TRUE ); + /* Flush (draw), and make sure VBO is left unmapped when done */ + vbo_exec_FlushVertices_internal(exec, GL_TRUE); /* Need to do this to ensure BeginVertices gets called again: */ - if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { - _mesa_restore_exec_vtxfmt( ctx ); - exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; - } - - exec->ctx->Driver.NeedFlush &= ~flags; + ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); #ifdef DEBUG exec->flush_call_depth--; @@ -923,34 +997,108 @@ static void reset_attrfv( struct vbo_exec_context *exec ) void GLAPIENTRY -_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) +_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { vbo_Color4f(r, g, b, a); } void GLAPIENTRY -_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z) +_es_Normal3f(GLfloat x, GLfloat y, GLfloat z) { vbo_Normal3f(x, y, z); } void GLAPIENTRY -_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { vbo_MultiTexCoord4f(target, s, t, r, q); } + void GLAPIENTRY -_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params) +_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params) { vbo_Materialfv(face, pname, params); } void GLAPIENTRY -_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +_es_Materialf(GLenum face, GLenum pname, GLfloat param) +{ + GLfloat p[4]; + p[0] = param; + p[1] = p[2] = p[3] = 0.0F; + vbo_Materialfv(face, pname, p); +} + + +/** + * A special version of glVertexAttrib4f that does not treat index 0 as + * VBO_ATTRIB_POS. + */ +static void +VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < MAX_VERTEX_GENERIC_ATTRIBS) + ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w); + else + ERROR(); +} + +void GLAPIENTRY +_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + VertexAttrib4f_nopos(index, x, y, z, w); +} + + +void GLAPIENTRY +_es_VertexAttrib1f(GLuint indx, GLfloat x) +{ + VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib1fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib2fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + VertexAttrib4f_nopos(indx, x, y, z, 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib3fv(GLuint indx, const GLfloat* values) +{ + VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f); +} + + +void GLAPIENTRY +_es_VertexAttrib4fv(GLuint indx, const GLfloat* values) { - vbo_VertexAttrib4fARB(index, x, y, z, w); + VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]); }