diff --git a/src/rendering/twn_gl_15_rendering.c b/src/rendering/twn_gl_15_rendering.c index 82e0c9f..c685139 100644 --- a/src/rendering/twn_gl_15_rendering.c +++ b/src/rendering/twn_gl_15_rendering.c @@ -118,7 +118,6 @@ typedef struct { bool textured, texture_repeat; TextureKey texture; - TextureMode texture_mode; GLuint element_buffer; GLsizei element_count; @@ -134,19 +133,6 @@ typedef struct { } DeferredCommandClear; -typedef struct { - enum DeferredCommandType { - DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS, - DEFERRED_COMMAND_TYPE_CLEAR, - } type; - - union { - DeferredCommandDrawElements draw_elements; - DeferredCommandClear clear; - }; -} DeferredCommand; - - typedef enum { PIPELINE_NO, PIPELINE_SPACE, @@ -154,6 +140,33 @@ typedef enum { } Pipeline; +typedef struct { + Pipeline pipeline; +} DeferredCommandUsePipeline; + + +typedef struct { + TextureMode mode; +} DeferredCommandUseTextureMode; + + +typedef struct { + enum DeferredCommandType { + DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS, + DEFERRED_COMMAND_TYPE_CLEAR, + DEFERRED_COMMAND_TYPE_USE_PIPIELINE, + DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE, + } type; + + union { + DeferredCommandDrawElements draw_elements; + DeferredCommandClear clear; + DeferredCommandUsePipeline use_pipeline; + DeferredCommandUseTextureMode use_texture_mode; + }; +} DeferredCommand; + + static Pipeline pipeline_last_used = PIPELINE_NO; @@ -165,13 +178,15 @@ static Pipeline pipeline_last_used = PIPELINE_NO; static size_t scratch_va_front_used, scratch_va_back_used; static GLuint *front_scratch_vertex_arrays, *back_scratch_vertex_arrays; static GLuint **current_scratch_vertex_array = &front_scratch_vertex_arrays; + static void restart_scratch_vertex_arrays(void) { scratch_va_front_used = 0; scratch_va_back_used = 0; - if (ctx.render_double_buffered) + if (ctx.render_double_buffered) { current_scratch_vertex_array = current_scratch_vertex_array == &front_scratch_vertex_arrays ? &back_scratch_vertex_arrays : &front_scratch_vertex_arrays; + } } @@ -186,14 +201,17 @@ GLuint get_scratch_vertex_array(void) { } (*used)++; - return (*current_scratch_vertex_array)[arrlenu(*current_scratch_vertex_array) - 1]; + return (*current_scratch_vertex_array)[*used - 1]; } -static DeferredCommand *deferred_commands; -static void issue_deferred_draw_commands(void) { - use_2d_pipeline(); +static void finally_use_2d_pipeline(void); +static void finally_use_space_pipeline(void); +static void finally_use_texture_mode(TextureMode mode); +static DeferredCommand *deferred_commands; + +static void issue_deferred_draw_commands(void) { for (size_t i = 0; i < arrlenu(deferred_commands); ++i) { switch (deferred_commands[i].type) { case DEFERRED_COMMAND_TYPE_CLEAR: { @@ -230,8 +248,6 @@ static void issue_deferred_draw_commands(void) { command.vertices.stride, (void *)command.vertices.offset); - use_texture_mode(command.texture_mode); - if (command.texcoords.arity != 0) { SDL_assert(command.texcoords.buffer == command.vertices.buffer); @@ -293,6 +309,27 @@ static void issue_deferred_draw_commands(void) { break; } + case DEFERRED_COMMAND_TYPE_USE_PIPIELINE: { + switch (deferred_commands[i].use_pipeline.pipeline) { + case PIPELINE_2D: + finally_use_2d_pipeline(); + break; + case PIPELINE_SPACE: + finally_use_space_pipeline(); + break; + case PIPELINE_NO: + default: + SDL_assert(false); + } + + break; + } + + case DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE: { + finally_use_texture_mode(deferred_commands[i].use_texture_mode.mode); + break; + } + default: SDL_assert(false); } @@ -318,7 +355,6 @@ void clear_draw_buffer(void) { void start_render_frame(void) { - restart_scratch_vertex_arrays(); clear_draw_buffer(); } @@ -328,12 +364,14 @@ void end_render_frame(void) { issue_deferred_draw_commands(); SDL_GL_SwapWindow(ctx.window); arrsetlen(deferred_commands, 0); + restart_scratch_vertex_arrays(); } else { /* instead of waiting for frame to finish for the swap, we continue */ /* while issuing new state for the next call, but deferring any fragment emitting calls for later */ /* actual swap will happen when next frame is fully finished, introducing a delay */ SDL_GL_SwapWindow(ctx.window); issue_deferred_draw_commands(); + restart_scratch_vertex_arrays(); glFlush(); arrsetlen(deferred_commands, 0); } @@ -341,6 +379,16 @@ void end_render_frame(void) { void use_space_pipeline(void) { + DeferredCommand const command = { + .type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE, + .use_pipeline = { PIPELINE_SPACE } + }; + + arrpush(deferred_commands, command); +} + + +static void finally_use_space_pipeline(void) { if (pipeline_last_used == PIPELINE_SPACE) return; @@ -378,6 +426,16 @@ void use_space_pipeline(void) { void use_2d_pipeline(void) { + DeferredCommand const command = { + .type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE, + .use_pipeline = { PIPELINE_2D } + }; + + arrpush(deferred_commands, command); +} + + +static void finally_use_2d_pipeline(void) { if (pipeline_last_used == PIPELINE_SPACE) { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glFlush(); @@ -453,6 +511,16 @@ void render_circle(const CirclePrimitive *circle) { void use_texture_mode(TextureMode mode) { + DeferredCommand const command = { + .type = DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE, + .use_texture_mode = { mode } + }; + + arrpush(deferred_commands, command); +} + + +static void finally_use_texture_mode(TextureMode mode) { static GLuint lists = 0; if (!lists) { lists = glGenLists(3); @@ -596,7 +664,7 @@ void finally_render_quads(const Primitive2D primitives[], command.element_count = 6 * (GLsizei)batch.size; command.range_end = 6 * (GLsizei)batch.size; - command.texture_mode = batch.mode; + use_texture_mode(batch.mode); DeferredCommand final_command = { .type = DEFERRED_COMMAND_TYPE_DRAW_ELEMENTS,