From 2209b7178988f059b6039de3d870bd76dbcb0874 Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Tue, 24 Nov 2020 18:12:38 +0300
Subject: [PATCH] Refactor render state
---
src/render/vitagxm/SDL_render_vita_gxm.c | 317 ++++++++++--------
.../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, 186 insertions(+), 146 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,26 +708,164 @@ 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;
+ 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);
+
+ return 0;
+}
+
+
+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;
+ }
- sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram);
- sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram);
+ 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
- void *vertexDefaultBuffer;
- sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer);
- sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix);
+ 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);
- sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count);
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