diff options
-rw-r--r-- | source/blender/gpu/GPU_immediate.h | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_immediate.c | 73 |
2 files changed, 54 insertions, 22 deletions
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h index 6bcfdc74ef6..ffd0a6d5afc 100644 --- a/source/blender/gpu/GPU_immediate.h +++ b/source/blender/gpu/GPU_immediate.h @@ -63,7 +63,8 @@ VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready f void immBindProgram(GLuint program); void immUnbindProgram(void); -void immBegin(GLenum primitive, unsigned vertex_ct); +void immBegin(GLenum primitive, unsigned vertex_ct); // must supply exactly vertex_ct vertices +void immBeginAtMost(GLenum primitive, unsigned max_vertex_ct); // can supply fewer vertices void immEnd(void); void immAttrib1f(unsigned attrib_id, float x); diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index 88a147959a3..98568d14482 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -242,6 +242,7 @@ typedef struct { unsigned buffer_offset; unsigned buffer_bytes_mapped; unsigned vertex_ct; + bool strict_vertex_ct; GLenum primitive; VertexFormat vertex_format; @@ -285,7 +286,8 @@ void immInit() #endif imm.primitive = PRIM_NONE; - + imm.strict_vertex_ct = true; + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); initialized = true; @@ -334,36 +336,38 @@ void immUnbindProgram() imm.bound_program = 0; } -void immBegin(GLenum primitive, unsigned vertex_ct) +static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, GLenum primitive) { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun - // does vertex_ct make sense for this primitive type? - assert(vertex_ct > 0); + if (vertex_ct == 0) + return false; + switch (primitive) { case GL_POINTS: - break; + return true; case GL_LINES: - assert(vertex_ct % 2 == 0); - break; + return vertex_ct % 2 == 0; case GL_LINE_STRIP: case GL_LINE_LOOP: - assert(vertex_ct > 2); // otherwise why bother? - break; + return vertex_ct > 2; // otherwise why bother? case GL_TRIANGLES: - assert(vertex_ct % 3 == 0); - break; + return vertex_ct % 3 == 0; #ifdef WITH_GL_PROFILE_COMPAT case GL_QUADS: - assert(vertex_ct % 4 == 0); - break; + return vertex_ct % 4 == 0; #endif default: - assert(false); + return false; } + } + +void immBegin(GLenum primitive, unsigned vertex_ct) + { +#if TRUST_NO_ONE + assert(initialized); + assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun + assert(vertex_count_makes_sense_for_primitive(vertex_ct, primitive)); #endif imm.primitive = primitive; @@ -417,17 +421,43 @@ void immBegin(GLenum primitive, unsigned vertex_ct) imm.vertex_data = imm.buffer_data; } +void immBeginAtMost(GLenum primitive, unsigned vertex_ct) + { + imm.strict_vertex_ct = false; + immBegin(primitive, vertex_ct); + } + void immEnd() { #if TRUST_NO_ONE assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair - assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined #endif + unsigned buffer_bytes_used; + if (imm.strict_vertex_ct) + { +#if TRUST_NO_ONE + assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined +#endif + buffer_bytes_used = imm.buffer_bytes_mapped; + } + else + { +#if TRUST_NO_ONE + assert(imm.vertex_idx <= imm.vertex_ct); + assert(vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive)); +#endif + // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct); + imm.vertex_ct = imm.vertex_idx; + buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct); + // unused buffer bytes are available to the next immBegin + // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped); + } + #if APPLE_LEGACY // tell OpenGL what range was modified so it doesn't copy the whole buffer - glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, imm.buffer_bytes_mapped); -// printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + imm.buffer_bytes_mapped - 1); + glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used); +// printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1); #endif glUnmapBuffer(GL_ARRAY_BUFFER); @@ -490,8 +520,9 @@ void immEnd() glBindVertexArray(0); // prep for next immBegin - imm.buffer_offset += imm.buffer_bytes_mapped; + imm.buffer_offset += buffer_bytes_used; imm.primitive = PRIM_NONE; + imm.strict_vertex_ct = true; // further optional cleanup imm.buffer_bytes_mapped = 0; |