/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End( void ) { GET_CURRENT_CONTEXT( ctx ); if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (exec->vtx.prim_count > 0) { /* close off current primitive */ int idx = exec->vtx.vert_count; int i = exec->vtx.prim_count - 1; exec->vtx.prim[i].end = 1; exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush( exec, GL_FALSE ); } else _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Close off the last primitive, execute the buffer, restart the * primitive. This is called when we fill a vertex buffer before * hitting glEnd. */ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) { if (exec->vtx.prim_count == 0) { exec->vtx.copied.nr = 0; exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; } else { struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; const GLuint last_begin = last_prim->begin; GLuint last_count; if (_mesa_inside_begin_end(exec->ctx)) { last_prim->count = exec->vtx.vert_count - last_prim->start; } last_count = last_prim->count; /* Special handling for wrapping GL_LINE_LOOP */ if (last_prim->mode == GL_LINE_LOOP && last_count > 0 && !last_prim->end) { /* draw this section of the incomplete line loop as a line strip */ last_prim->mode = GL_LINE_STRIP; if (!last_prim->begin) { /* This is not the first section of the line loop, so don't * draw the 0th vertex. We're saving it until we draw the * very last section of the loop. */ last_prim->start++; last_prim->count--; } } /* Execute the buffer and save copied vertices. */ if (exec->vtx.vert_count) vbo_exec_vtx_flush( exec, GL_FALSE ); else { exec->vtx.prim_count = 0; exec->vtx.copied.nr = 0; } /* Emit a glBegin to start the new list. */ assert(exec->vtx.prim_count == 0); if (_mesa_inside_begin_end(exec->ctx)) { exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; exec->vtx.prim[0].begin = 0; exec->vtx.prim[0].end = 0; exec->vtx.prim[0].start = 0; exec->vtx.prim[0].count = 0; exec->vtx.prim_count++; if (exec->vtx.copied.nr == last_count) exec->vtx.prim[0].begin = last_begin; } } }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End(void) { GET_CURRENT_CONTEXT(ctx); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentClientDispatch == ctx->BeginEnd) { ctx->CurrentClientDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentClientDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; last_prim->end = 1; last_prim->count = exec->vtx.vert_count - last_prim->start; /* Special handling for GL_LINE_LOOP */ if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) { /* We're finishing drawing a line loop. Append 0th vertex onto * end of vertex buffer so we can draw it as a line strip. */ const fi_type *src = exec->vtx.buffer_map + last_prim->start * exec->vtx.vertex_size; fi_type *dst = exec->vtx.buffer_map + exec->vtx.vert_count * exec->vtx.vertex_size; /* copy 0th vertex to end of buffer */ memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type)); last_prim->start++; /* skip vertex0 */ /* note that last_prim->count stays unchanged */ last_prim->mode = GL_LINE_STRIP; /* Increment the vertex count so the next primitive doesn't * overwrite the last vertex which we just added. */ exec->vtx.vert_count++; exec->vtx.buffer_ptr += exec->vtx.vertex_size; } try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush(exec, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * 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 ); } }
void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap ) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 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 ); } }
/** * Close off the last primitive, execute the buffer, restart the * primitive. */ static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) { if (exec->vtx.prim_count == 0) { exec->vtx.copied.nr = 0; exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; } else { GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; GLuint last_count; if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { GLint i = exec->vtx.prim_count - 1; assert(i >= 0); exec->vtx.prim[i].count = (exec->vtx.vert_count - exec->vtx.prim[i].start); } last_count = exec->vtx.prim[exec->vtx.prim_count-1].count; /* Execute the buffer and save copied vertices. */ if (exec->vtx.vert_count) vbo_exec_vtx_flush( exec, GL_FALSE ); else { exec->vtx.prim_count = 0; exec->vtx.copied.nr = 0; } /* Emit a glBegin to start the new list. */ assert(exec->vtx.prim_count == 0); if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; exec->vtx.prim[0].start = 0; exec->vtx.prim[0].count = 0; exec->vtx.prim_count++; if (exec->vtx.copied.nr == last_count) exec->vtx.prim[0].begin = last_begin; } } }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End( void ) { GET_CURRENT_CONTEXT( ctx ); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentDispatch == ctx->BeginEnd) { ctx->CurrentDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ int idx = exec->vtx.vert_count; int i = exec->vtx.prim_count - 1; exec->vtx.prim[i].end = 1; exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush( exec, GL_FALSE ); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }