From 2209b7178988f059b6039de3d870bd76dbcb0874 Mon Sep 17 00:00:00 2001 From: Ivan Epifanov Date: Tue, 24 Nov 2020 18:12:38 +0300 Subject: [PATCH] Refactor render state --- src/render/vitagxm/SDL_render_vita_gxm.c | 325 ++++++++++-------- .../vitagxm/SDL_render_vita_gxm_tools.c | 3 +- .../vitagxm/SDL_render_vita_gxm_tools.h | 3 + .../vitagxm/SDL_render_vita_gxm_types.h | 9 + 4 files changed, 190 insertions(+), 150 deletions(-) diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index 925df80eb..866bb5c53 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -357,9 +357,8 @@ VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) } static void -VITA_GXM_SetBlendMode(SDL_Renderer *renderer, int blendMode) +VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode) { - VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; if (blendMode != data->currentBlendMode) { fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; @@ -534,16 +533,6 @@ VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; - Uint8 r, g, b, a; - SDL_GetTextureColorMod(texture, &r, &g, &b); - SDL_GetTextureAlphaMod(texture, &a); - - cmd->data.draw.r = r; - cmd->data.draw.g = g; - cmd->data.draw.b = b; - cmd->data.draw.a = a; - cmd->data.draw.blend = renderer->blendMode; - cmd->data.draw.count = 1; texture_vertex *vertices = (texture_vertex *)pool_memalign( @@ -593,16 +582,6 @@ VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Textur { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; - Uint8 r, g, b, a; - SDL_GetTextureColorMod(texture, &r, &g, &b); - SDL_GetTextureAlphaMod(texture, &a); - - cmd->data.draw.r = r; - cmd->data.draw.g = g; - cmd->data.draw.b = b; - cmd->data.draw.a = a; - cmd->data.draw.blend = renderer->blendMode; - cmd->data.draw.count = 1; texture_vertex *vertices = (texture_vertex *)pool_memalign( @@ -705,22 +684,6 @@ VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; - if (data->drawstate.fragment_program != data->colorFragmentProgram || data->drawstate.vertex_program != data->colorVertexProgram) { - data->drawstate.fragment_program = data->colorFragmentProgram; - data->drawstate.vertex_program = data->colorVertexProgram; - - sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); - sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); - - - void *vertexDefaultBuffer; - sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); - sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); - } - - - sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); - sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT); sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_POINTS, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count); sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); @@ -733,19 +696,6 @@ VITA_GXM_RenderDrawLines(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; - if (data->drawstate.fragment_program != data->colorFragmentProgram || data->drawstate.vertex_program != data->colorVertexProgram) { - data->drawstate.fragment_program = data->colorFragmentProgram; - data->drawstate.vertex_program = data->colorVertexProgram; - - sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); - sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); - - - void *vertexDefaultBuffer; - sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); - sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); - } - sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE); sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_LINES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count); sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); @@ -758,19 +708,6 @@ VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) { VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; - if (data->drawstate.fragment_program != data->colorFragmentProgram || data->drawstate.vertex_program != data->colorVertexProgram) { - data->drawstate.fragment_program = data->colorFragmentProgram; - data->drawstate.vertex_program = data->colorVertexProgram; - - sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); - sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); - - - void *vertexDefaultBuffer; - sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); - sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); - } - sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count); @@ -778,6 +715,157 @@ VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) } +static int +SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool solid) +{ + SDL_Texture *texture = cmd->data.draw.texture; + const SDL_BlendMode blend = cmd->data.draw.blend; + SceGxmFragmentProgram *fragment_program; + SceGxmVertexProgram *vertex_program; + SDL_bool matrix_updated = SDL_FALSE; + SDL_bool program_updated = SDL_FALSE; + + Uint8 r, g, b, a; + r = cmd->data.draw.r; + g = cmd->data.draw.g; + b = cmd->data.draw.b; + a = cmd->data.draw.a; + + if (data->drawstate.viewport_dirty) { + // TODO: this isn't right + /* + const SDL_Rect *viewport = &data->drawstate.viewport; + + float x_scale = (int)(viewport->w) >> 1; + float x_off = viewport->x + x_scale; + float y_scale = -((int)(viewport->h) >> 1); + float y_off = -1.0 * (viewport->y + y_scale); + + sceGxmSetViewport(data->gxm_context, x_off, x_scale, y_off, y_scale, 0.f, 1.f); + + if (viewport->w && viewport->h) { + init_orthographic_matrix(data->ortho_matrix, viewport->x, viewport->x + viewport->w, viewport->y + viewport->h, viewport->y, 0.0f, 1.0f); + matrix_updated = SDL_TRUE; + } + */ + data->drawstate.viewport_dirty = SDL_FALSE; + } + + if (data->drawstate.cliprect_enabled_dirty) { + if (!data->drawstate.cliprect_enabled) { + unset_clip_rectangle(data); + } + data->drawstate.cliprect_enabled_dirty = SDL_FALSE; + } + + if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { + const SDL_Rect *viewport = &data->drawstate.viewport; + const SDL_Rect *rect = &data->drawstate.cliprect; + set_clip_rectangle(data, viewport->x + rect->x, + data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h, + rect->w, rect->h); + data->drawstate.cliprect_dirty = SDL_FALSE; + } + + VITA_GXM_SetBlendMode(data, blend); // do that first, to select appropriate shaders + + if (texture) { + vertex_program = data->textureVertexProgram; + if(cmd->data.draw.r == 255 && cmd->data.draw.g == 255 && cmd->data.draw.b == 255 && cmd->data.draw.a == 255) { + fragment_program = data->textureFragmentProgram; + } else { + fragment_program = data->textureTintFragmentProgram; + } + } else { + vertex_program = data->colorVertexProgram; + fragment_program = data->colorFragmentProgram; + } + + if (data->drawstate.vertex_program != vertex_program) { + data->drawstate.vertex_program = vertex_program; + sceGxmSetVertexProgram(data->gxm_context, vertex_program); + program_updated = SDL_TRUE; + } + + if (data->drawstate.fragment_program != fragment_program) { + data->drawstate.fragment_program = fragment_program; + sceGxmSetFragmentProgram(data->gxm_context, fragment_program); + program_updated = SDL_TRUE; + } + + Uint32 texture_color = ((a << 24) | (b << 16) | (g << 8) | r); + + if (program_updated || matrix_updated) { + if (data->drawstate.fragment_program == data->textureFragmentProgram) { + void *vertex_wvp_buffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer); + sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix); + } else if (data->drawstate.fragment_program == data->textureTintFragmentProgram) { + void *vertex_wvp_buffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer); + sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix); + + void *texture_tint_color_buffer; + sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer); + + float *tint_color = pool_memalign( + data, + 4 * sizeof(float), // RGBA + sizeof(float) + ); + + tint_color[0] = r / 255.0f; + tint_color[1] = g / 255.0f; + tint_color[2] = b / 255.0f; + tint_color[3] = a / 255.0f; + sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color); + data->drawstate.texture_color = texture_color; + } else { // color + void *vertexDefaultBuffer; + sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); + sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); + } + } else { + if (data->drawstate.fragment_program == data->textureTintFragmentProgram && data->drawstate.texture_color != texture_color) { + void *texture_tint_color_buffer; + sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer); + + float *tint_color = pool_memalign( + data, + 4 * sizeof(float), // RGBA + sizeof(float) + ); + + tint_color[0] = r / 255.0f; + tint_color[1] = g / 255.0f; + tint_color[2] = b / 255.0f; + tint_color[3] = a / 255.0f; + sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color); + data->drawstate.texture_color = texture_color; + } + } + + if (texture != data->drawstate.texture) { + if (texture) { + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) cmd->data.draw.texture->driverdata; + sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); + } + data->drawstate.texture = texture; + } + + /* all drawing commands use this */ + sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + + return 0; +} + +static int +SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) +{ + VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + + return SetDrawState(data, cmd, SDL_FALSE); +} static int VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) @@ -785,126 +873,67 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void * StartDrawing(renderer); VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata; + data->drawstate.target = renderer->target; + if (!data->drawstate.target) { + SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh); + } + while (cmd) { switch (cmd->command) { - case SDL_RENDERCMD_SETDRAWCOLOR: { - break; - } case SDL_RENDERCMD_SETVIEWPORT: { - // TODO + SDL_Rect *viewport = &data->drawstate.viewport; + if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) { + SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)); + data->drawstate.viewport_dirty = SDL_TRUE; + } break; } case SDL_RENDERCMD_SETCLIPRECT: { const SDL_Rect *rect = &cmd->data.cliprect.rect; - if (cmd->data.cliprect.enabled) - { - set_clip_rectangle(data, rect->x, rect->y, rect->w, rect->h); + if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) { + data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled; + data->drawstate.cliprect_enabled_dirty = SDL_TRUE; } - else - { - unset_clip_rectangle(data); + + if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) { + SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)); + data->drawstate.cliprect_dirty = SDL_TRUE; } break; } + case SDL_RENDERCMD_SETDRAWCOLOR: { + break; + } + case SDL_RENDERCMD_CLEAR: { VITA_GXM_RenderClear(renderer, cmd); break; } case SDL_RENDERCMD_DRAW_POINTS: { - VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + SetDrawState(data, cmd, SDL_FALSE); VITA_GXM_RenderDrawPoints(renderer, cmd); break; } case SDL_RENDERCMD_DRAW_LINES: { - VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + SetDrawState(data, cmd, SDL_FALSE); VITA_GXM_RenderDrawLines(renderer, cmd); break; } case SDL_RENDERCMD_FILL_RECTS: { - VITA_GXM_SetBlendMode(renderer, cmd->data.draw.blend); + SetDrawState(data, cmd, SDL_FALSE); VITA_GXM_RenderFillRects(renderer, cmd); break; } case SDL_RENDERCMD_COPY: case SDL_RENDERCMD_COPY_EX: { - SDL_BlendMode blend; - SDL_GetTextureBlendMode(cmd->data.draw.texture, &blend); - VITA_GXM_SetBlendMode(renderer, blend); - - Uint8 r, g, b, a; - r = cmd->data.draw.r; - g = cmd->data.draw.g; - b = cmd->data.draw.b; - a = cmd->data.draw.a; - - if (data->drawstate.vertex_program != data->textureVertexProgram) { - data->drawstate.vertex_program = data->textureVertexProgram; - sceGxmSetVertexProgram(data->gxm_context, data->textureVertexProgram); - } - - if(r == 255 && g == 255 && b == 255 && a == 255) - { - if (data->drawstate.fragment_program != data->textureFragmentProgram) { - data->drawstate.fragment_program = data->textureFragmentProgram; - sceGxmSetFragmentProgram(data->gxm_context, data->textureFragmentProgram); - } - } - else - { - if (data->drawstate.fragment_program != data->textureTintFragmentProgram) { - data->drawstate.fragment_program = data->textureTintFragmentProgram; - sceGxmSetFragmentProgram(data->gxm_context, data->textureTintFragmentProgram); - } - - Uint32 texture_color = ((a << 24) | (b << 16) | (g << 8) | r); - - if ( - (data->drawstate.last_command != SDL_RENDERCMD_COPY && data->drawstate.last_command != SDL_RENDERCMD_COPY_EX) - || data->drawstate.texture_color != texture_color - ) { - data->drawstate.texture_color = texture_color; - void *texture_tint_color_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer); - - float *tint_color = pool_memalign( - data, - 4 * sizeof(float), // RGBA - sizeof(float) - ); - - tint_color[0] = r / 255.0f; - tint_color[1] = g / 255.0f; - tint_color[2] = b / 255.0f; - tint_color[3] = a / 255.0f; - - sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color); - } - - } - - if (data->drawstate.last_command != SDL_RENDERCMD_COPY && data->drawstate.last_command != SDL_RENDERCMD_COPY_EX) { - void *vertex_wvp_buffer; - sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer); - sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix); - } - - if (data->drawstate.texture != cmd->data.draw.texture) { - data->drawstate.texture = cmd->data.draw.texture; - // TODO: check if texture changed - VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) cmd->data.draw.texture->driverdata; - - sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); - } - - - sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first); + SetCopyState(renderer, cmd); sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count); break; diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c index 757f1f495..f410595cb 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c @@ -44,7 +44,7 @@ #include "SDL_render_vita_gxm_memory.h" #include "SDL_render_vita_gxm_shaders.h" -static void +void init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far) { m[0x0] = 2.0f/(right-left); @@ -68,7 +68,6 @@ init_orthographic_matrix(float *m, float left, float right, float bottom, float m[0xF] = 1.0f; } - static void * patcher_host_alloc(void *user_data, unsigned int size) { diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h index 5787e4d3a..c1dfc6c0e 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h @@ -36,6 +36,9 @@ #include "SDL_render_vita_gxm_types.h" +void +init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far); + void *pool_malloc(VITA_GXM_RenderData *data, unsigned int size); void *pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment); diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h index af4c3316d..64a323e35 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_types.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h @@ -108,6 +108,15 @@ typedef struct SceGxmFragmentProgram *fragment_program; SceGxmVertexProgram *vertex_program; int last_command; + + SDL_bool cliprect_enabled_dirty; + SDL_bool cliprect_enabled; + SDL_bool cliprect_dirty; + SDL_Rect cliprect; + SDL_bool texturing; + Uint32 clear_color; + int drawablew; + int drawableh; } gxm_drawstate_cache; typedef struct