SDL: Implement blend modes

From fb1a205e70e7f3a1ae59c0f4f09b340fc4e8e7af Mon Sep 17 00:00:00 2001
From: Francisco Javier Trujillo Mata <[EMAIL REDACTED]>
Date: Mon, 1 Aug 2022 11:44:05 +0200
Subject: [PATCH] Implement blend modes

---
 src/render/ps2/SDL_render_ps2.c | 42 +++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c
index de31a2598e7..2ebf2744741 100644
--- a/src/render/ps2/SDL_render_ps2.c
+++ b/src/render/ps2/SDL_render_ps2.c
@@ -379,6 +379,42 @@ PS2_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
     return 0;
 }
 
+static void
+PS2_SetBlendMode(PS2_RenderData *data, int blendMode)
+{
+    #define A_COLOR_SOURCE 0
+    #define A_COLOR_DEST 1
+    #define A_COLOR_NULL 2
+    #define A_ALPHA_SOURCE 0
+    #define A_ALPHA_DEST 1
+    #define A_ALPHA_FIX 2
+
+    switch (blendMode)
+    {
+        case SDL_BLENDMODE_NONE: {
+            data->gsGlobal->PrimAlphaEnable = GS_SETTING_OFF;
+            break;
+        }
+        case SDL_BLENDMODE_BLEND:{
+            gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_SOURCE, A_COLOR_DEST, A_ALPHA_SOURCE, A_COLOR_DEST, 0), 0);
+            data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
+            break;
+        }
+        case SDL_BLENDMODE_ADD: {
+            gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_SOURCE, A_COLOR_NULL, A_ALPHA_FIX, A_COLOR_DEST, 0x80), 0);
+            data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
+            break;
+        }
+        case SDL_BLENDMODE_MUL: 
+        case SDL_BLENDMODE_MOD: {
+            /* We don't fully support MOD and MUL, however this is the best we can do */
+            gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_DEST, A_COLOR_NULL, A_ALPHA_SOURCE, A_COLOR_SOURCE, 0x80), 0);
+            data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
+            break;
+        }
+    }
+}
+
 static int
 PS2_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand *cmd)
 {
@@ -391,6 +427,8 @@ PS2_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand *cm
     
     const size_t count = cmd->data.draw.count;
 
+    PS2_SetBlendMode(data, cmd->data.draw.blend);
+
     if (cmd->data.draw.texture) {
         const texture_vertex *verts = (texture_vertex *) (vertices + cmd->data.draw.first);
         GSTEXTURE *ps2_tex = (GSTEXTURE *) cmd->data.draw.texture->driverdata;
@@ -476,6 +514,8 @@ PS2_RenderLines(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand * cmd)
 
     const color_vertex *verts = (color_vertex *) (vertices + cmd->data.draw.first);
 
+    PS2_SetBlendMode(data, cmd->data.draw.blend);
+
     for (i = 0; i < count-1; i++, verts++) {
         x1 = verts[i*2].x;
         y1 = verts[i*2].y;
@@ -505,6 +545,8 @@ PS2_RenderPoints(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand * cmd
     const uint8_t ColorB = cmd->data.draw.b >> 1;
     const uint8_t ColorA = cmd->data.draw.a >> 1;
 
+    PS2_SetBlendMode(data, cmd->data.draw.blend);
+
     color = GS_SETREG_RGBAQ(ColorR, ColorG, ColorB, ColorA, 0x00);
 
     const clear_vertex *verts = (clear_vertex *) (vertices + cmd->data.draw.first);