diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c index 3bf353e8b2d..d11ac6b0a9d 100644 --- a/source/blender/gpu/gawain/batch.c +++ b/source/blender/gpu/gawain/batch.c @@ -12,6 +12,10 @@ #include "batch.h" #include +// necessary functions from matrix API +extern void gpuBindMatrices(GLuint program); +extern bool gpuMatricesDirty(void); // how best to use this here? + Batch* Batch_create(GLenum prim_type, VertexBuffer* verts, ElementList* elem) { #if TRUST_NO_ONE @@ -30,30 +34,54 @@ Batch* Batch_create(GLenum prim_type, VertexBuffer* verts, ElementList* elem) return batch; } +void Batch_discard(Batch* batch) + { + // TODO: clean up + } + +void Batch_discard_all(Batch* batch) + { + VertexBuffer_discard(batch->verts); + if (batch->elem) + ElementList_discard(batch->elem); + Batch_discard(batch); + } + void Batch_set_program(Batch* batch, GLuint program) { +#if TRUST_NO_ONE + assert(glIsProgram(program)); +#endif + batch->program = program; batch->program_dirty = true; } static void Batch_update_program_bindings(Batch* batch) { -#if TRUST_NO_ONE - assert(glIsProgram(batch->program)); -#endif - const VertexFormat* format = &batch->verts->format; const unsigned attrib_ct = format->attrib_ct; const unsigned stride = format->stride; + // disable all as a precaution + // why are we not using prev_attrib_enabled_bits?? see immediate.c + for (unsigned a_idx = 0; a_idx < MAX_VERTEX_ATTRIBS; ++a_idx) + glDisableVertexAttribArray(a_idx); + + VertexBuffer_use(batch->verts); + for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx) { const Attrib* a = format->attribs + a_idx; const GLvoid* pointer = (const GLubyte*)0 + a->offset; - const unsigned loc = glGetAttribLocation(batch->program, a->name); + const GLint loc = glGetAttribLocation(batch->program, a->name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif glEnableVertexAttribArray(loc); @@ -74,6 +102,60 @@ static void Batch_update_program_bindings(Batch* batch) batch->program_dirty = false; } +static void Batch_use_program(Batch* batch) + { + if (!batch->program_in_use) + { + glUseProgram(batch->program); + batch->program_in_use = true; + } + } + +static void Batch_done_using_program(Batch* batch) + { + if (batch->program_in_use) + { + glUseProgram(0); + batch->program_in_use = false; + } + } + +void Batch_Uniform1b(Batch* batch, const char* name, bool value) + { + int loc = glGetUniformLocation(batch->program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + Batch_use_program(batch); + glUniform1i(loc, value ? GL_TRUE : GL_FALSE); + } + +void Batch_Uniform3fv(Batch* batch, const char* name, const float data[3]) + { + int loc = glGetUniformLocation(batch->program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + Batch_use_program(batch); + glUniform3fv(loc, 1, data); + } + +void Batch_Uniform4fv(Batch* batch, const char* name, const float data[4]) + { + int loc = glGetUniformLocation(batch->program, name); + +#if TRUST_NO_ONE + assert(loc != -1); +#endif + + Batch_use_program(batch); + glUniform4fv(loc, 1, data); + } + static void Batch_prime(Batch* batch) { glGenVertexArrays(1, &batch->vao_id); @@ -91,6 +173,7 @@ void Batch_draw(Batch* batch) { #if TRUST_NO_ONE assert(batch->phase == READY_TO_DRAW); + assert(glIsProgram(batch->program)); #endif if (batch->vao_id) @@ -101,7 +184,9 @@ void Batch_draw(Batch* batch) if (batch->program_dirty) Batch_update_program_bindings(batch); - glUseProgram(batch->program); + Batch_use_program(batch); + + gpuBindMatrices(batch->program); if (batch->elem) { @@ -119,6 +204,6 @@ void Batch_draw(Batch* batch) else glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); - glUseProgram(0); + Batch_done_using_program(batch); glBindVertexArray(0); } diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h index 8b132aa3c02..c0f0e93ce9a 100644 --- a/source/blender/gpu/gawain/batch.h +++ b/source/blender/gpu/gawain/batch.h @@ -31,6 +31,7 @@ typedef struct { GLuint vao_id; // remembers all geometry state (vertex attrib bindings & element buffer) BatchPhase phase; bool program_dirty; + bool program_in_use; // state GLuint program; @@ -38,13 +39,19 @@ typedef struct { Batch* Batch_create(GLenum prim_type, VertexBuffer*, ElementList*); -// TODO: void Batch_discard(Batch*); -// must first decide how sharing of vertex buffers & index buffers should work +void Batch_discard(Batch*); // verts & elem are not discarded +void Batch_discard_all(Batch*); // including verts & elem void Batch_set_program(Batch*, GLuint program); // Entire batch draws with one shader program, but can be redrawn later with another program. // Vertex shader's inputs must be compatible with the batch's vertex format. +void Batch_Uniform1b(Batch*, const char* name, bool value); +// void Batch_Uniform1f(Batch*, float value); +// void Batch_Uniform4f(Batch*, float x, float y, float z, float w); +void Batch_Uniform3fv(Batch*, const char* name, const float data[3]); +void Batch_Uniform4fv(Batch*, const char* name, const float data[4]); + void Batch_draw(Batch*); diff --git a/source/blender/gpu/gawain/element.c b/source/blender/gpu/gawain/element.c index 953042ba110..699b416e9d8 100644 --- a/source/blender/gpu/gawain/element.c +++ b/source/blender/gpu/gawain/element.c @@ -204,7 +204,14 @@ static void squeeze_indices_short(const unsigned values[], ElementList* elem) #endif // TRACK_INDEX_RANGE -void ElementList_build(ElementListBuilder* builder, ElementList* elem) +ElementList* ElementList_build(ElementListBuilder* builder) + { + ElementList* elem = calloc(1, sizeof(ElementList)); + ElementList_build_in_place(builder, elem); + return elem; + } + +void ElementList_build_in_place(ElementListBuilder* builder, ElementList* elem) { #if TRUST_NO_ONE assert(builder->data != NULL); @@ -260,3 +267,8 @@ void ElementList_build(ElementListBuilder* builder, ElementList* elem) builder->data = NULL; // other fields are safe to leave } + +void ElementList_discard(ElementList* elem) + { + // TODO: clean up + } diff --git a/source/blender/gpu/gawain/element.h b/source/blender/gpu/gawain/element.h index 9ba2ed2a5b1..6a07b70228c 100644 --- a/source/blender/gpu/gawain/element.h +++ b/source/blender/gpu/gawain/element.h @@ -52,4 +52,7 @@ void add_point_vertex(ElementListBuilder*, unsigned v); void add_line_vertices(ElementListBuilder*, unsigned v1, unsigned v2); void add_triangle_vertices(ElementListBuilder*, unsigned v1, unsigned v2, unsigned v3); -void ElementList_build(ElementListBuilder*, ElementList*); +ElementList* ElementList_build(ElementListBuilder*); +void ElementList_build_in_place(ElementListBuilder*, ElementList*); + +void ElementList_discard(ElementList*); diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/source/blender/gpu/gawain/vertex_buffer.c index 93d0facdf7c..403df3cb669 100644 --- a/source/blender/gpu/gawain/vertex_buffer.c +++ b/source/blender/gpu/gawain/vertex_buffer.c @@ -47,6 +47,11 @@ void VertexBuffer_init_with_format(VertexBuffer* verts, const VertexFormat* form VertexFormat_pack(&verts->format); } +void VertexBuffer_discard(VertexBuffer* verts) + { + // TODO: clean up + } + unsigned VertexBuffer_size(const VertexBuffer* verts) { return vertex_buffer_size(&verts->format, verts->vertex_ct); diff --git a/source/blender/gpu/gawain/vertex_buffer.h b/source/blender/gpu/gawain/vertex_buffer.h index 7128ec4b1af..6a72cfe6ff3 100644 --- a/source/blender/gpu/gawain/vertex_buffer.h +++ b/source/blender/gpu/gawain/vertex_buffer.h @@ -32,6 +32,8 @@ typedef struct { VertexBuffer* VertexBuffer_create(void); VertexBuffer* VertexBuffer_create_with_format(const VertexFormat*); +void VertexBuffer_discard(VertexBuffer*); + void VertexBuffer_init(VertexBuffer*); void VertexBuffer_init_with_format(VertexBuffer*, const VertexFormat*);