Browse Source

Implemented more flexible blending modes for accelerated renderers

This fixes bug 2594 - Propose new blend mode, SDL_BLENDMODE_BLEND_DSTA

	blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA,
	                                       SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
	                                       SDL_BLENDOPERATION_ADD,
	                                       SDL_BLENDFACTOR_ZERO,
	                                       SDL_BLENDFACTOR_ONE,
	                                       SDL_BLENDOPERATION_ADD);

This fixes bug 2828 - Subtractive Blending

	blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA,
	                                       SDL_BLENDFACTOR_ONE,
	                                       SDL_BLENDOPERATION_SUBTRACT,
	                                       SDL_BLENDFACTOR_ZERO,
	                                       SDL_BLENDFACTOR_ONE,
	                                       SDL_BLENDOPERATION_SUBTRACT);


This goes partway to fixing bug 3684 - Add support for a pre-multiplied alpha blending mode

	blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE,
	                                       SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
	                                       SDL_BLENDOPERATION_ADD,
	                                       SDL_BLENDFACTOR_ONE,
	                                       SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
	                                       SDL_BLENDOPERATION_ADD);
Sam Lantinga 7 years ago
parent
commit
c59d9923b3

+ 58 - 1
include/SDL_blendmode.h

@@ -47,11 +47,68 @@ typedef enum
     SDL_BLENDMODE_ADD = 0x00000002,      /**< additive blending
                                               dstRGB = (srcRGB * srcA) + dstRGB
                                               dstA = dstA */
-    SDL_BLENDMODE_MOD = 0x00000004       /**< color modulate
+    SDL_BLENDMODE_MOD = 0x00000004,      /**< color modulate
                                               dstRGB = srcRGB * dstRGB
                                               dstA = dstA */
+    SDL_BLENDMODE_INVALID = 0x7FFFFFFF
+
+    /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
+
 } SDL_BlendMode;
 
+/**
+ *  \brief The blend operation used when combining source and destination pixel components
+ */
+typedef enum
+{
+    SDL_BLENDOPERATION_ADD              = 0x1,  /**< dst + src: supported by all renderers */
+    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D11 */
+    SDL_BLENDOPERATION_MAXIMUM          = 0x5,  /**< max(dst, src) : supported by D3D11 */
+
+} SDL_BlendOperation;
+
+/**
+ *  \brief The normalized factor used to multiply pixel components
+ */
+typedef enum
+{
+    SDL_BLENDFACTOR_ZERO                = 0x1,  /**< 0, 0, 0, 0 */
+    SDL_BLENDFACTOR_ONE                 = 0x2,  /**< 1, 1, 1, 1 */
+    SDL_BLENDFACTOR_SRC_COLOR           = 0x3,  /**< srcR, srcG, srcB, srcA */
+    SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4,  /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
+    SDL_BLENDFACTOR_SRC_ALPHA           = 0x5,  /**< srcA, srcA, srcA, srcA */
+    SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6,  /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
+    SDL_BLENDFACTOR_DST_COLOR           = 0x7,  /**< dstR, dstG, dstB, dstA */
+    SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8,  /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
+    SDL_BLENDFACTOR_DST_ALPHA           = 0x9,  /**< dstA, dstA, dstA, dstA */
+    SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA,  /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
+
+} SDL_BlendFactor;
+
+/**
+ *  \brief Create a custom blend mode, which may or may not be supported by a given renderer
+ *
+ *  \param srcColorFactor
+ *  \param dstColorFactor
+ *  \param colorOperation
+ *  \param srcAlphaFactor
+ *  \param dstAlphaFactor
+ *  \param alphaOperation
+ *
+ *  The result of the blend mode operation will be:
+ *      dstRGB = dstRGB * dstColorFactor colorOperation srcRGB * srcColorFactor
+ *  and
+ *      dstA = dstA * dstAlphaFactor alphaOperation srcA * srcAlphaFactor
+ */
+extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
+                                                                 SDL_BlendFactor dstColorFactor,
+                                                                 SDL_BlendOperation colorOperation,
+                                                                 SDL_BlendFactor srcAlphaFactor,
+                                                                 SDL_BlendFactor dstAlphaFactor,
+                                                                 SDL_BlendOperation alphaOperation);
+
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -627,3 +627,4 @@
 #define SDL_utf8strlen SDL_utf8strlen_REAL
 #define SDL_LoadFile_RW SDL_LoadFile_RW_REAL
 #define SDL_wcscmp SDL_wcscmp_REAL
+#define SDL_ComposeCustomBlendMode SDL_ComposeCustomBlendMode_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -659,3 +659,4 @@ SDL_DYNAPI_PROC(SDL_JoystickID,SDL_JoystickGetDeviceInstanceID,(int a),(a),retur
 SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return)
 SDL_DYNAPI_PROC(void*,SDL_LoadFile_RW,(SDL_RWops *a, size_t *b, int c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_wcscmp,(const wchar_t *a, const wchar_t *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_BlendMode,SDL_ComposeCustomBlendMode,(SDL_BlendFactor a, SDL_BlendFactor b, SDL_BlendOperation c, SDL_BlendFactor d, SDL_BlendFactor e, SDL_BlendOperation f),(a,b,c,d,e,f),return)

+ 135 - 0
src/render/SDL_render.c

@@ -44,6 +44,31 @@
         return retval; \
     }
 
+/* Predefined blend modes */
+#define SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, \
+                              srcAlphaFactor, dstAlphaFactor, alphaOperation) \
+    (SDL_BlendMode)(((Uint32)colorOperation << 0) | \
+                    ((Uint32)srcColorFactor << 4) | \
+                    ((Uint32)dstColorFactor << 8) | \
+                    ((Uint32)alphaOperation << 16) | \
+                    ((Uint32)srcAlphaFactor << 20) | \
+                    ((Uint32)dstAlphaFactor << 24))
+
+#define SDL_BLENDMODE_NONE_FULL \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ZERO, SDL_BLENDOPERATION_ADD)
+
+#define SDL_BLENDMODE_BLEND_FULL \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)
+
+#define SDL_BLENDMODE_ADD_FULL \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
+
+#define SDL_BLENDMODE_MOD_FULL \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
 
 #if !SDL_RENDER_DISABLED
 static const SDL_RenderDriver *render_drivers[] = {
@@ -379,6 +404,23 @@ SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
     }
 }
 
+static SDL_bool
+IsSupportedBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    switch (blendMode)
+    {
+    /* These are required to be supported by all renderers */
+    case SDL_BLENDMODE_NONE:
+    case SDL_BLENDMODE_BLEND:
+    case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_MOD:
+        return SDL_TRUE;
+
+    default:
+        return renderer->SupportsBlendMode && renderer->SupportsBlendMode(renderer, blendMode);
+    }
+}
+
 static SDL_bool
 IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
 {
@@ -706,6 +748,9 @@ SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
     CHECK_TEXTURE_MAGIC(texture, -1);
 
     renderer = texture->renderer;
+    if (!IsSupportedBlendMode(renderer, blendMode)) {
+        return SDL_Unsupported();
+    }
     texture->blendMode = blendMode;
     if (texture->native) {
         return SDL_SetTextureBlendMode(texture->native, blendMode);
@@ -1452,6 +1497,9 @@ SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
 {
     CHECK_RENDERER_MAGIC(renderer, -1);
 
+    if (!IsSupportedBlendMode(renderer, blendMode)) {
+        return SDL_Unsupported();
+    }
     renderer->blendMode = blendMode;
     return 0;
 }
@@ -2042,4 +2090,91 @@ int SDL_GL_UnbindTexture(SDL_Texture *texture)
     return SDL_Unsupported();
 }
 
+static SDL_BlendMode
+SDL_GetShortBlendMode(SDL_BlendMode blendMode)
+{
+    switch (blendMode) {
+    case SDL_BLENDMODE_NONE_FULL:
+        return SDL_BLENDMODE_NONE;
+    case SDL_BLENDMODE_BLEND_FULL:
+        return SDL_BLENDMODE_BLEND;
+    case SDL_BLENDMODE_ADD_FULL:
+        return SDL_BLENDMODE_ADD;
+    case SDL_BLENDMODE_MOD_FULL:
+        return SDL_BLENDMODE_MOD;
+    default:
+        return blendMode;
+    }
+}
+
+static SDL_BlendMode
+SDL_GetLongBlendMode(SDL_BlendMode blendMode)
+{
+    switch (blendMode) {
+    case SDL_BLENDMODE_NONE:
+        return SDL_BLENDMODE_NONE_FULL;
+    case SDL_BLENDMODE_BLEND:
+        return SDL_BLENDMODE_BLEND_FULL;
+    case SDL_BLENDMODE_ADD:
+        return SDL_BLENDMODE_ADD_FULL;
+    case SDL_BLENDMODE_MOD:
+        return SDL_BLENDMODE_MOD_FULL;
+    default:
+        return blendMode;
+    }
+}
+
+SDL_BlendMode
+SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor,
+                           SDL_BlendOperation colorOperation,
+                           SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor,
+                           SDL_BlendOperation alphaOperation)
+{
+    SDL_BlendMode blendMode = SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation,
+                                                    srcAlphaFactor, dstAlphaFactor, alphaOperation);
+    return SDL_GetShortBlendMode(blendMode);
+}
+
+SDL_BlendFactor
+SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendFactor)(((Uint32)blendMode >> 4) & 0xF);
+}
+
+SDL_BlendFactor
+SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendFactor)(((Uint32)blendMode >> 8) & 0xF);
+}
+
+SDL_BlendOperation
+SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendOperation)(((Uint32)blendMode >> 0) & 0xF);
+}
+
+SDL_BlendFactor
+SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendFactor)(((Uint32)blendMode >> 20) & 0xF);
+}
+
+SDL_BlendFactor
+SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendFactor)(((Uint32)blendMode >> 24) & 0xF);
+}
+
+SDL_BlendOperation
+SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
+{
+    blendMode = SDL_GetLongBlendMode(blendMode);
+    return (SDL_BlendFactor)(((Uint32)blendMode >> 16) & 0xF);
+}
+
 /* vi: set ts=4 sw=4 expandtab: */

+ 9 - 0
src/render/SDL_sysrender.h

@@ -79,6 +79,7 @@ struct SDL_Renderer
 
     void (*WindowEvent) (SDL_Renderer * renderer, const SDL_WindowEvent *event);
     int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
+    SDL_bool (*SupportsBlendMode)(SDL_Renderer * renderer, SDL_BlendMode blendMode);
     int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
     int (*SetTextureColorMod) (SDL_Renderer * renderer,
                                SDL_Texture * texture);
@@ -186,6 +187,14 @@ extern SDL_RenderDriver DirectFB_RenderDriver;
 extern SDL_RenderDriver PSP_RenderDriver;
 extern SDL_RenderDriver SW_RenderDriver;
 
+/* Blend mode functions */
+extern SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode);
+extern SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode);
+extern SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode);
+extern SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode);
+extern SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode);
+extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode);
+
 #endif /* SDL_sysrender_h_ */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 63 - 42
src/render/direct3d/SDL_render_d3d.c

@@ -125,6 +125,7 @@ static void PrintShaderData(LPDWORD shader_data, DWORD shader_size)
 static SDL_Renderer *D3D_CreateRenderer(SDL_Window * window, Uint32 flags);
 static void D3D_WindowEvent(SDL_Renderer * renderer,
                             const SDL_WindowEvent *event);
+static SDL_bool D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
 static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
@@ -542,6 +543,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
     }
 
     renderer->WindowEvent = D3D_WindowEvent;
+    renderer->SupportsBlendMode = D3D_SupportsBlendMode;
     renderer->CreateTexture = D3D_CreateTexture;
     renderer->UpdateTexture = D3D_UpdateTexture;
     renderer->UpdateTextureYUV = D3D_UpdateTextureYUV;
@@ -802,6 +804,58 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
     }
 }
 
+static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return D3DBLEND_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return D3DBLEND_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return D3DBLEND_SRCCOLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return D3DBLEND_INVSRCCOLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return D3DBLEND_SRCALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return D3DBLEND_INVSRCALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return D3DBLEND_DESTCOLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return D3DBLEND_INVDESTCOLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return D3DBLEND_DESTALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return D3DBLEND_INVDESTALPHA;
+    default:
+        return (D3DBLEND)0;
+    }
+}
+
+static SDL_bool
+D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
+        !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
+        return SDL_FALSE;
+    }
+    if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
+        return SDL_FALSE;
+    }
+    if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 static D3DTEXTUREFILTERTYPE
 GetScaleQuality(void)
 {
@@ -1353,55 +1407,22 @@ D3D_RenderClear(SDL_Renderer * renderer)
 }
 
 static void
-D3D_SetBlendMode(D3D_RenderData * data, int blendMode)
+D3D_SetBlendMode(D3D_RenderData * data, SDL_BlendMode blendMode)
 {
-    switch (blendMode) {
-    case SDL_BLENDMODE_NONE:
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
-                                        FALSE);
-        break;
-    case SDL_BLENDMODE_BLEND:
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
-                                        TRUE);
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
-                                        D3DBLEND_SRCALPHA);
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
-                                        D3DBLEND_INVSRCALPHA);
-        if (data->enableSeparateAlphaBlend) {
-            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
-                                            D3DBLEND_ONE);
-            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
-                                            D3DBLEND_INVSRCALPHA);
-        }
-        break;
-    case SDL_BLENDMODE_ADD:
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
-                                        TRUE);
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
-                                        D3DBLEND_SRCALPHA);
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
-                                        D3DBLEND_ONE);
-        if (data->enableSeparateAlphaBlend) {
-            IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
-                                            D3DBLEND_ZERO);
-            IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
-                                            D3DBLEND_ONE);
-        }
-        break;
-    case SDL_BLENDMODE_MOD:
-        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,
-                                        TRUE);
+    if (blendMode == SDL_BLENDMODE_NONE) {
+        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
+    } else {
+        IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, TRUE);
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,
-                                        D3DBLEND_ZERO);
+                                        GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)));
         IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
-                                        D3DBLEND_SRCCOLOR);
+                                        GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
         if (data->enableSeparateAlphaBlend) {
             IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
-                                            D3DBLEND_ZERO);
+                                            GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)));
             IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
-                                            D3DBLEND_ONE);
+                                            GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
         }
-        break;
     }
 }
 

+ 135 - 72
src/render/direct3d11/SDL_render_d3d11.c

@@ -93,6 +93,13 @@ typedef struct
     SDL_Rect locked_rect;
 } D3D11_TextureData;
 
+/* Blend mode data */
+typedef struct
+{
+    SDL_BlendMode blendMode;
+    ID3D11BlendState *blendState;
+} D3D11_BlendMode;
+
 /* Private renderer data */
 typedef struct
 {
@@ -112,9 +119,8 @@ typedef struct
     ID3D11PixelShader *colorPixelShader;
     ID3D11PixelShader *texturePixelShader;
     ID3D11PixelShader *yuvPixelShader;
-    ID3D11BlendState *blendModeBlend;
-    ID3D11BlendState *blendModeAdd;
-    ID3D11BlendState *blendModeMod;
+    int blendModesCount;
+    D3D11_BlendMode *blendModes;
     ID3D11SamplerState *nearestPixelSampler;
     ID3D11SamplerState *linearSampler;
     D3D_FEATURE_LEVEL featureLevel;
@@ -716,6 +722,7 @@ static const DWORD D3D11_VertexShader[] = {
 static SDL_Renderer *D3D11_CreateRenderer(SDL_Window * window, Uint32 flags);
 static void D3D11_WindowEvent(SDL_Renderer * renderer,
                             const SDL_WindowEvent *event);
+static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
 static int D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                              const SDL_Rect * rect, const void *srcPixels,
@@ -826,6 +833,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
     }
 
     renderer->WindowEvent = D3D11_WindowEvent;
+    renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
     renderer->CreateTexture = D3D11_CreateTexture;
     renderer->UpdateTexture = D3D11_UpdateTexture;
     renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV;
@@ -898,6 +906,8 @@ D3D11_ReleaseAll(SDL_Renderer * renderer)
 
     /* Release/reset everything else */
     if (data) {
+        int i;
+
         SAFE_RELEASE(data->dxgiFactory);
         SAFE_RELEASE(data->dxgiAdapter);
         SAFE_RELEASE(data->d3dDevice);
@@ -911,9 +921,14 @@ D3D11_ReleaseAll(SDL_Renderer * renderer)
         SAFE_RELEASE(data->colorPixelShader);
         SAFE_RELEASE(data->texturePixelShader);
         SAFE_RELEASE(data->yuvPixelShader);
-        SAFE_RELEASE(data->blendModeBlend);
-        SAFE_RELEASE(data->blendModeAdd);
-        SAFE_RELEASE(data->blendModeMod);
+        if (data->blendModesCount > 0) {
+            for (i = 0; i < data->blendModesCount; ++i) {
+                SAFE_RELEASE(data->blendModes[i].blendState);
+            }
+            SDL_free(data->blendModes);
+
+            data->blendModesCount = 0;
+        }
         SAFE_RELEASE(data->nearestPixelSampler);
         SAFE_RELEASE(data->linearSampler);
         SAFE_RELEASE(data->mainRasterizer);
@@ -954,37 +969,96 @@ D3D11_DestroyRenderer(SDL_Renderer * renderer)
     SDL_free(renderer);
 }
 
-static HRESULT
-D3D11_CreateBlendMode(SDL_Renderer * renderer,
-                      BOOL enableBlending,
-                      D3D11_BLEND srcBlend,
-                      D3D11_BLEND destBlend,
-                      D3D11_BLEND srcBlendAlpha,
-                      D3D11_BLEND destBlendAlpha,
-                      ID3D11BlendState ** blendStateOutput)
+static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return D3D11_BLEND_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return D3D11_BLEND_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return D3D11_BLEND_SRC_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return D3D11_BLEND_INV_SRC_COLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return D3D11_BLEND_SRC_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return D3D11_BLEND_INV_SRC_ALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return D3D11_BLEND_DEST_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return D3D11_BLEND_INV_DEST_COLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return D3D11_BLEND_DEST_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return D3D11_BLEND_INV_DEST_ALPHA;
+    default:
+        return (D3D11_BLEND)0;
+    }
+}
+
+static D3D11_BLEND_OP GetBlendEquation(SDL_BlendOperation operation)
+{
+    switch (operation) {
+    case SDL_BLENDOPERATION_ADD:
+        return D3D11_BLEND_OP_ADD;
+    case SDL_BLENDOPERATION_SUBTRACT:
+        return D3D11_BLEND_OP_SUBTRACT;
+    case SDL_BLENDOPERATION_REV_SUBTRACT:
+        return D3D11_BLEND_OP_REV_SUBTRACT;
+    case SDL_BLENDOPERATION_MINIMUM:
+        return D3D11_BLEND_OP_MIN;
+    case SDL_BLENDOPERATION_MAXIMUM:
+        return D3D11_BLEND_OP_MAX;
+    default:
+        return (D3D11_BLEND_OP)0;
+    }
+}
+
+static SDL_bool
+D3D11_CreateBlendState(SDL_Renderer * renderer, SDL_BlendMode blendMode)
 {
     D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+    ID3D11BlendState *blendState = NULL;
+    D3D11_BlendMode *blendModes;
     HRESULT result = S_OK;
 
     D3D11_BLEND_DESC blendDesc;
     SDL_zero(blendDesc);
     blendDesc.AlphaToCoverageEnable = FALSE;
     blendDesc.IndependentBlendEnable = FALSE;
-    blendDesc.RenderTarget[0].BlendEnable = enableBlending;
-    blendDesc.RenderTarget[0].SrcBlend = srcBlend;
-    blendDesc.RenderTarget[0].DestBlend = destBlend;
-    blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
-    blendDesc.RenderTarget[0].SrcBlendAlpha = srcBlendAlpha;
-    blendDesc.RenderTarget[0].DestBlendAlpha = destBlendAlpha;
-    blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+    blendDesc.RenderTarget[0].BlendEnable = TRUE;
+    blendDesc.RenderTarget[0].SrcBlend = GetBlendFunc(srcColorFactor);
+    blendDesc.RenderTarget[0].DestBlend = GetBlendFunc(dstColorFactor);
+    blendDesc.RenderTarget[0].BlendOp = GetBlendEquation(colorOperation);
+    blendDesc.RenderTarget[0].SrcBlendAlpha = GetBlendFunc(srcAlphaFactor);
+    blendDesc.RenderTarget[0].DestBlendAlpha = GetBlendFunc(dstAlphaFactor);
+    blendDesc.RenderTarget[0].BlendOpAlpha = GetBlendEquation(alphaOperation);
     blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
-    result = ID3D11Device_CreateBlendState(data->d3dDevice, &blendDesc, blendStateOutput);
+    result = ID3D11Device_CreateBlendState(data->d3dDevice, &blendDesc, &blendState);
     if (FAILED(result)) {
         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBlendState"), result);
-        return result;
+        return SDL_FALSE;
     }
 
-    return S_OK;
+    blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes));
+    if (!blendModes) {
+        SAFE_RELEASE(blendState);
+        SDL_OutOfMemory();
+        return SDL_FALSE;
+    }
+    blendModes[data->blendModesCount].blendMode = blendMode;
+    blendModes[data->blendModesCount].blendState = blendState;
+    data->blendModes = blendModes;
+    ++data->blendModesCount;
+
+    return SDL_TRUE;
 }
 
 /* Create resources that depend on the device. */
@@ -1286,41 +1360,9 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
     }
 
     /* Create blending states: */
-    result = D3D11_CreateBlendMode(
-        renderer,
-        TRUE,
-        D3D11_BLEND_SRC_ALPHA,          /* srcBlend */
-        D3D11_BLEND_INV_SRC_ALPHA,      /* destBlend */
-        D3D11_BLEND_ONE,                /* srcBlendAlpha */
-        D3D11_BLEND_INV_SRC_ALPHA,      /* destBlendAlpha */
-        &data->blendModeBlend);
-    if (FAILED(result)) {
-        /* D3D11_CreateBlendMode will set the SDL error, if it fails */
-        goto done;
-    }
-
-    result = D3D11_CreateBlendMode(
-        renderer,
-        TRUE,
-        D3D11_BLEND_SRC_ALPHA,          /* srcBlend */
-        D3D11_BLEND_ONE,                /* destBlend */
-        D3D11_BLEND_ZERO,               /* srcBlendAlpha */
-        D3D11_BLEND_ONE,                /* destBlendAlpha */
-        &data->blendModeAdd);
-    if (FAILED(result)) {
-        /* D3D11_CreateBlendMode will set the SDL error, if it fails */
-        goto done;
-    }
-
-    result = D3D11_CreateBlendMode(
-        renderer,
-        TRUE,
-        D3D11_BLEND_ZERO,               /* srcBlend */
-        D3D11_BLEND_SRC_COLOR,          /* destBlend */
-        D3D11_BLEND_ZERO,               /* srcBlendAlpha */
-        D3D11_BLEND_ONE,                /* destBlendAlpha */
-        &data->blendModeMod);
-    if (FAILED(result)) {
+    if (!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_BLEND) ||
+        !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_ADD) ||
+        !D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD)) {
         /* D3D11_CreateBlendMode will set the SDL error, if it fails */
         goto done;
     }
@@ -1694,6 +1736,25 @@ D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
     }
 }
 
+static SDL_bool
+D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
+        !GetBlendEquation(colorOperation) ||
+        !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
+        !GetBlendEquation(alphaOperation)) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 static D3D11_FILTER
 GetScaleQuality(void)
 {
@@ -2443,19 +2504,21 @@ D3D11_RenderSetBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
 {
     D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
     ID3D11BlendState *blendState = NULL;
-    switch (blendMode) {
-    case SDL_BLENDMODE_BLEND:
-        blendState = rendererData->blendModeBlend;
-        break;
-    case SDL_BLENDMODE_ADD:
-        blendState = rendererData->blendModeAdd;
-        break;
-    case SDL_BLENDMODE_MOD:
-        blendState = rendererData->blendModeMod;
-        break;
-    case SDL_BLENDMODE_NONE:
-        blendState = NULL;
-        break;
+    if (blendMode != SDL_BLENDMODE_NONE) {
+        int i;
+        for (i = 0; i < rendererData->blendModesCount; ++i) {
+            if (blendMode == rendererData->blendModes[i].blendMode) {
+                blendState = rendererData->blendModes[i].blendState;
+                break;
+            }
+        }
+        if (!blendState) {
+            if (D3D11_CreateBlendState(renderer, blendMode)) {
+                /* Successfully created the blend state, try again */
+                D3D11_RenderSetBlendMode(renderer, blendMode);
+            }
+            return;
+        }
     }
     if (blendState != rendererData->currentBlendState) {
         ID3D11DeviceContext_OMSetBlendState(rendererData->d3dContext, blendState, 0, 0xFFFFFFFF);

+ 2 - 1
src/render/opengl/SDL_glfuncs.h

@@ -35,7 +35,8 @@ SDL_PROC(void, glBindTexture, (GLenum, GLuint))
 SDL_PROC_UNUSED(void, glBitmap,
                 (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat,
                  const GLubyte *))
-SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC(void, glBlendEquation, (GLenum))
+SDL_PROC_UNUSED(void, glBlendFunc, (GLenum, GLenum))
 SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC_UNUSED(void, glCallList, (GLuint))
 SDL_PROC_UNUSED(void, glCallLists, (GLsizei, GLenum, const GLvoid *))

+ 79 - 17
src/render/opengl/SDL_render_gl.c

@@ -55,6 +55,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
 static void GL_WindowEvent(SDL_Renderer * renderer,
                            const SDL_WindowEvent *event);
 static int GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
+static SDL_bool GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                             const SDL_Rect * rect, const void *pixels,
@@ -126,7 +127,7 @@ typedef struct
     struct {
         GL_Shader shader;
         Uint32 color;
-        int blendMode;
+        SDL_BlendMode blendMode;
     } current;
 
     SDL_bool GL_EXT_framebuffer_object_supported;
@@ -321,7 +322,7 @@ GL_ResetState(SDL_Renderer *renderer)
 
     data->current.shader = SHADER_NONE;
     data->current.color = 0xffffffff;
-    data->current.blendMode = -1;
+    data->current.blendMode = SDL_BLENDMODE_INVALID;
 
     data->glDisable(GL_DEPTH_TEST);
     data->glDisable(GL_CULL_FACE);
@@ -428,6 +429,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
 
     renderer->WindowEvent = GL_WindowEvent;
     renderer->GetOutputSize = GL_GetOutputSize;
+    renderer->SupportsBlendMode = GL_SupportsBlendMode;
     renderer->CreateTexture = GL_CreateTexture;
     renderer->UpdateTexture = GL_UpdateTexture;
     renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
@@ -595,6 +597,73 @@ GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
     return 0;
 }
 
+static GLenum GetBlendFunc(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return GL_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return GL_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return GL_SRC_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return GL_ONE_MINUS_SRC_COLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return GL_SRC_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return GL_ONE_MINUS_SRC_ALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return GL_DST_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return GL_ONE_MINUS_DST_COLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return GL_DST_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return GL_ONE_MINUS_DST_ALPHA;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static GLenum GetBlendEquation(SDL_BlendOperation operation)
+{
+    switch (operation) {
+    case SDL_BLENDOPERATION_ADD:
+        return GL_FUNC_ADD;
+    case SDL_BLENDOPERATION_SUBTRACT:
+        return GL_FUNC_SUBTRACT;
+    case SDL_BLENDOPERATION_REV_SUBTRACT:
+        return GL_FUNC_REVERSE_SUBTRACT;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static SDL_bool
+GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
+        return SDL_FALSE;
+    }
+    if (colorOperation != alphaOperation) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 SDL_FORCE_INLINE int
 power_of_2(int input)
 {
@@ -1092,25 +1161,18 @@ GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 }
 
 static void
-GL_SetBlendMode(GL_RenderData * data, int blendMode)
+GL_SetBlendMode(GL_RenderData * data, SDL_BlendMode blendMode)
 {
     if (blendMode != data->current.blendMode) {
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
+        if (blendMode == SDL_BLENDMODE_NONE) {
             data->glDisable(GL_BLEND);
-            break;
-        case SDL_BLENDMODE_BLEND:
-            data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            break;
-        case SDL_BLENDMODE_ADD:
-            data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
-            break;
-        case SDL_BLENDMODE_MOD:
+        } else {
             data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
-            break;
+            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
+            data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
         }
         data->current.blendMode = blendMode;
     }

+ 2 - 0
src/render/opengles/SDL_glesfuncs.h

@@ -21,6 +21,8 @@
 
 SDL_PROC(void, glBindTexture, (GLenum, GLuint))
 SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
+SDL_PROC_OES(void, glBlendEquationOES, (GLenum))
+SDL_PROC_OES(void, glBlendEquationSeparateOES, (GLenum, GLenum))
 SDL_PROC_OES(void, glBlendFuncSeparateOES, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC(void, glClear, (GLbitfield))
 SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))

+ 99 - 25
src/render/opengles/SDL_render_gles.c

@@ -56,6 +56,7 @@ static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
 static void GLES_WindowEvent(SDL_Renderer * renderer,
                              const SDL_WindowEvent *event);
 static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
+static SDL_bool GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
 static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                               const SDL_Rect * rect, const void *pixels,
@@ -116,7 +117,7 @@ typedef struct
     SDL_GLContext context;
     struct {
         Uint32 color;
-        int blendMode;
+        SDL_BlendMode blendMode;
         SDL_bool tex_coords;
     } current;
 
@@ -130,6 +131,8 @@ typedef struct
     GLuint window_framebuffer;
 
     SDL_bool GL_OES_blend_func_separate_supported;
+    SDL_bool GL_OES_blend_equation_separate_supported;
+    SDL_bool GL_OES_blend_subtract_supported;
 } GLES_RenderData;
 
 typedef struct
@@ -262,7 +265,7 @@ GLES_ResetState(SDL_Renderer *renderer)
     }
 
     data->current.color = 0xffffffff;
-    data->current.blendMode = -1;
+    data->current.blendMode = SDL_BLENDMODE_INVALID;
     data->current.tex_coords = SDL_FALSE;
 
     data->glDisable(GL_DEPTH_TEST);
@@ -319,6 +322,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
 
     renderer->WindowEvent = GLES_WindowEvent;
     renderer->GetOutputSize = GLES_GetOutputSize;
+    renderer->SupportsBlendMode = GLES_SupportsBlendMode;
     renderer->CreateTexture = GLES_CreateTexture;
     renderer->UpdateTexture = GLES_UpdateTexture;
     renderer->LockTexture = GLES_LockTexture;
@@ -388,6 +392,12 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
     if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
         data->GL_OES_blend_func_separate_supported = SDL_TRUE;
     }
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
+        data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
+    }
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
+        data->GL_OES_blend_subtract_supported = SDL_TRUE;
+    }
 
     /* Set up parameters for rendering */
     GLES_ResetState(renderer);
@@ -430,6 +440,79 @@ GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
     return 0;
 }
 
+static GLenum GetBlendFunc(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return GL_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return GL_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return GL_SRC_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return GL_ONE_MINUS_SRC_COLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return GL_SRC_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return GL_ONE_MINUS_SRC_ALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return GL_DST_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return GL_ONE_MINUS_DST_COLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return GL_DST_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return GL_ONE_MINUS_DST_ALPHA;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static GLenum GetBlendEquation(SDL_BlendOperation operation)
+{
+    switch (operation) {
+    case SDL_BLENDOPERATION_ADD:
+        return GL_FUNC_ADD_OES;
+    case SDL_BLENDOPERATION_SUBTRACT:
+        return GL_FUNC_SUBTRACT_OES;
+    case SDL_BLENDOPERATION_REV_SUBTRACT:
+        return GL_FUNC_REVERSE_SUBTRACT_OES;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static SDL_bool
+GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
+        return SDL_FALSE;
+    }
+    if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
+        return SDL_FALSE;
+    }
+    if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
+        return SDL_FALSE;
+    }
+    if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 static SDL_INLINE int
 power_of_2(int input)
 {
@@ -739,37 +822,28 @@ GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 }
 
 static void
-GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
+GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode)
 {
     if (blendMode != data->current.blendMode) {
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
+        if (blendMode == SDL_BLENDMODE_NONE) {
             data->glDisable(GL_BLEND);
-            break;
-        case SDL_BLENDMODE_BLEND:
-            data->glEnable(GL_BLEND);
-            if (data->GL_OES_blend_func_separate_supported) {
-                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            } else {
-                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-            }
-            break;
-        case SDL_BLENDMODE_ADD:
+        } else {
             data->glEnable(GL_BLEND);
             if (data->GL_OES_blend_func_separate_supported) {
-                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
+                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
+                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
+                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
+                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
             } else {
-                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
+                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
             }
-            break;
-        case SDL_BLENDMODE_MOD:
-            data->glEnable(GL_BLEND);
-            if (data->GL_OES_blend_func_separate_supported) {
-                data->glBlendFuncSeparateOES(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
-            } else {
-                data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            if (data->GL_OES_blend_equation_separate_supported) {
+                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
+                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
+            } else if (data->GL_OES_blend_subtract_supported) {
+                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
             }
-            break;
         }
         data->current.blendMode = blendMode;
     }

+ 1 - 0
src/render/opengles2/SDL_gles2funcs.h

@@ -23,6 +23,7 @@ SDL_PROC(void, glActiveTexture, (GLenum))
 SDL_PROC(void, glAttachShader, (GLuint, GLuint))
 SDL_PROC(void, glBindAttribLocation, (GLuint, GLuint, const char *))
 SDL_PROC(void, glBindTexture, (GLenum, GLuint))
+SDL_PROC(void, glBlendEquationSeparate, (GLenum, GLenum))
 SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum))
 SDL_PROC(void, glClear, (GLbitfield))
 SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))

+ 112 - 62
src/render/opengles2/SDL_render_gles2.c

@@ -122,7 +122,6 @@ typedef struct GLES2_ShaderCache
 typedef struct GLES2_ProgramCacheEntry
 {
     GLuint id;
-    SDL_BlendMode blend_mode;
     GLES2_ShaderCacheEntry *vertex_shader;
     GLES2_ShaderCacheEntry *fragment_shader;
     GLuint uniform_locations[16];
@@ -177,7 +176,7 @@ typedef struct GLES2_DriverContext
     SDL_bool debug_enabled;
 
     struct {
-        int blendMode;
+        SDL_BlendMode blendMode;
         SDL_bool tex_coords;
     } current;
 
@@ -372,6 +371,70 @@ GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
     return 0;
 }
 
+static GLenum GetBlendFunc(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return GL_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return GL_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return GL_SRC_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return GL_ONE_MINUS_SRC_COLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return GL_SRC_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return GL_ONE_MINUS_SRC_ALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return GL_DST_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return GL_ONE_MINUS_DST_COLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return GL_DST_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return GL_ONE_MINUS_DST_ALPHA;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static GLenum GetBlendEquation(SDL_BlendOperation operation)
+{
+    switch (operation) {
+    case SDL_BLENDOPERATION_ADD:
+        return GL_FUNC_ADD;
+    case SDL_BLENDOPERATION_SUBTRACT:
+        return GL_FUNC_SUBTRACT;
+    case SDL_BLENDOPERATION_REV_SUBTRACT:
+        return GL_FUNC_REVERSE_SUBTRACT;
+    default:
+        return GL_INVALID_ENUM;
+    }
+}
+
+static SDL_bool
+GLES2_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
+{
+    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
+        GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
+        GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 static int
 GLES2_UpdateViewport(SDL_Renderer * renderer)
 {
@@ -882,19 +945,16 @@ GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  * Shader management functions                                                                   *
  *************************************************************************************************/
 
-static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type,
-                                                 SDL_BlendMode blendMode);
+static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type);
 static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
 static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
                                                    GLES2_ShaderCacheEntry *vertex,
-                                                   GLES2_ShaderCacheEntry *fragment,
-                                                   SDL_BlendMode blendMode);
-static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source,
-                               SDL_BlendMode blendMode);
+                                                   GLES2_ShaderCacheEntry *fragment);
+static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source);
 
 static GLES2_ProgramCacheEntry *
 GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
-                   GLES2_ShaderCacheEntry *fragment, SDL_BlendMode blendMode)
+                   GLES2_ShaderCacheEntry *fragment)
 {
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     GLES2_ProgramCacheEntry *entry;
@@ -933,7 +993,6 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
     }
     entry->vertex_shader = vertex;
     entry->fragment_shader = fragment;
-    entry->blend_mode = blendMode;
 
     /* Create the program and link it */
     entry->id = data->glCreateProgram();
@@ -1011,7 +1070,7 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
 }
 
 static GLES2_ShaderCacheEntry *
-GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode blendMode)
+GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type)
 {
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     const GLES2_Shader *shader;
@@ -1021,7 +1080,7 @@ GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode b
     int i, j;
 
     /* Find the corresponding shader */
-    shader = GLES2_GetShader(type, blendMode);
+    shader = GLES2_GetShader(type);
     if (!shader) {
         SDL_SetError("No shader matching the requested characteristics was found");
         return NULL;
@@ -1130,7 +1189,7 @@ GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
 }
 
 static int
-GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode)
+GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source)
 {
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     GLES2_ShaderCacheEntry *vertex = NULL;
@@ -1170,11 +1229,11 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
     }
 
     /* Load the requested shaders */
-    vertex = GLES2_CacheShader(renderer, vtype, blendMode);
+    vertex = GLES2_CacheShader(renderer, vtype);
     if (!vertex) {
         goto fault;
     }
-    fragment = GLES2_CacheShader(renderer, ftype, blendMode);
+    fragment = GLES2_CacheShader(renderer, ftype);
     if (!fragment) {
         goto fault;
     }
@@ -1187,7 +1246,7 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
     }
 
     /* Generate a matching program */
-    program = GLES2_CacheProgram(renderer, vertex, fragment, blendMode);
+    program = GLES2_CacheProgram(renderer, vertex, fragment);
     if (!program) {
         goto fault;
     }
@@ -1341,26 +1400,19 @@ GLES2_RenderClear(SDL_Renderer * renderer)
 }
 
 static void
-GLES2_SetBlendMode(GLES2_DriverContext *data, int blendMode)
+GLES2_SetBlendMode(GLES2_DriverContext *data, SDL_BlendMode blendMode)
 {
     if (blendMode != data->current.blendMode) {
-        switch (blendMode) {
-        default:
-        case SDL_BLENDMODE_NONE:
+        if (blendMode == SDL_BLENDMODE_NONE) {
             data->glDisable(GL_BLEND);
-            break;
-        case SDL_BLENDMODE_BLEND:
-            data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-            break;
-        case SDL_BLENDMODE_ADD:
-            data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
-            break;
-        case SDL_BLENDMODE_MOD:
+        } else {
             data->glEnable(GL_BLEND);
-            data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
-            break;
+            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
+                                      GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
+            data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
+                                          GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
         }
         data->current.blendMode = blendMode;
     }
@@ -1383,18 +1435,17 @@ static int
 GLES2_SetDrawingState(SDL_Renderer * renderer)
 {
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
-    const int blendMode = renderer->blendMode;
     GLES2_ProgramCacheEntry *program;
     Uint8 r, g, b, a;
 
     GLES2_ActivateRenderer(renderer);
 
-    GLES2_SetBlendMode(data, blendMode);
+    GLES2_SetBlendMode(data, renderer->blendMode);
 
     GLES2_SetTexCoords(data, SDL_FALSE);
 
     /* Activate an appropriate shader and set the projection matrix */
-    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) {
+    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID) < 0) {
         return -1;
     }
 
@@ -1555,12 +1606,10 @@ GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
     GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
-    SDL_BlendMode blendMode;
     GLES2_ProgramCacheEntry *program;
     Uint8 r, g, b, a;
 
     /* Activate an appropriate shader and set the projection matrix */
-    blendMode = texture->blendMode;
     if (renderer->target) {
         /* Check if we need to do color mapping between the source and render target textures */
         if (renderer->target->format != texture->format) {
@@ -1658,7 +1707,7 @@ GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
         }
     }
 
-    if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) {
+    if (GLES2_SelectProgram(renderer, sourceType) < 0) {
         return -1;
     }
 
@@ -1705,7 +1754,7 @@ GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
     }
 
     /* Configure texture blending */
-    GLES2_SetBlendMode(data, blendMode);
+    GLES2_SetBlendMode(data, renderer->blendMode);
 
     GLES2_SetTexCoords(data, SDL_TRUE);
     return 0;
@@ -1938,7 +1987,7 @@ GLES2_ResetState(SDL_Renderer *renderer)
         GLES2_ActivateRenderer(renderer);
     }
 
-    data->current.blendMode = -1;
+    data->current.blendMode = SDL_BLENDMODE_INVALID;
     data->current.tex_coords = SDL_FALSE;
 
     data->glActiveTexture(GL_TEXTURE0);
@@ -2091,28 +2140,29 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
     data->window_framebuffer = (GLuint)window_framebuffer;
 
     /* Populate the function pointers for the module */
-    renderer->WindowEvent         = &GLES2_WindowEvent;
-    renderer->GetOutputSize       = &GLES2_GetOutputSize;
-    renderer->CreateTexture       = &GLES2_CreateTexture;
-    renderer->UpdateTexture       = &GLES2_UpdateTexture;
-    renderer->UpdateTextureYUV    = &GLES2_UpdateTextureYUV;
-    renderer->LockTexture         = &GLES2_LockTexture;
-    renderer->UnlockTexture       = &GLES2_UnlockTexture;
-    renderer->SetRenderTarget     = &GLES2_SetRenderTarget;
-    renderer->UpdateViewport      = &GLES2_UpdateViewport;
-    renderer->UpdateClipRect      = &GLES2_UpdateClipRect;
-    renderer->RenderClear         = &GLES2_RenderClear;
-    renderer->RenderDrawPoints    = &GLES2_RenderDrawPoints;
-    renderer->RenderDrawLines     = &GLES2_RenderDrawLines;
-    renderer->RenderFillRects     = &GLES2_RenderFillRects;
-    renderer->RenderCopy          = &GLES2_RenderCopy;
-    renderer->RenderCopyEx        = &GLES2_RenderCopyEx;
-    renderer->RenderReadPixels    = &GLES2_RenderReadPixels;
-    renderer->RenderPresent       = &GLES2_RenderPresent;
-    renderer->DestroyTexture      = &GLES2_DestroyTexture;
-    renderer->DestroyRenderer     = &GLES2_DestroyRenderer;
-    renderer->GL_BindTexture      = &GLES2_BindTexture;
-    renderer->GL_UnbindTexture    = &GLES2_UnbindTexture;
+    renderer->WindowEvent         = GLES2_WindowEvent;
+    renderer->GetOutputSize       = GLES2_GetOutputSize;
+    renderer->SupportsBlendMode   = GLES2_SupportsBlendMode;
+    renderer->CreateTexture       = GLES2_CreateTexture;
+    renderer->UpdateTexture       = GLES2_UpdateTexture;
+    renderer->UpdateTextureYUV    = GLES2_UpdateTextureYUV;
+    renderer->LockTexture         = GLES2_LockTexture;
+    renderer->UnlockTexture       = GLES2_UnlockTexture;
+    renderer->SetRenderTarget     = GLES2_SetRenderTarget;
+    renderer->UpdateViewport      = GLES2_UpdateViewport;
+    renderer->UpdateClipRect      = GLES2_UpdateClipRect;
+    renderer->RenderClear         = GLES2_RenderClear;
+    renderer->RenderDrawPoints    = GLES2_RenderDrawPoints;
+    renderer->RenderDrawLines     = GLES2_RenderDrawLines;
+    renderer->RenderFillRects     = GLES2_RenderFillRects;
+    renderer->RenderCopy          = GLES2_RenderCopy;
+    renderer->RenderCopyEx        = GLES2_RenderCopyEx;
+    renderer->RenderReadPixels    = GLES2_RenderReadPixels;
+    renderer->RenderPresent       = GLES2_RenderPresent;
+    renderer->DestroyTexture      = GLES2_DestroyTexture;
+    renderer->DestroyRenderer     = GLES2_DestroyRenderer;
+    renderer->GL_BindTexture      = GLES2_BindTexture;
+    renderer->GL_UnbindTexture    = GLES2_UnbindTexture;
 
     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;

+ 11 - 556
src/render/opengles2/SDL_shaders_gles2.c

@@ -258,524 +258,46 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV21Src = {
 };
 
 
-/*************************************************************************************************
- * Vertex/fragment shader binaries (NVIDIA Tegra 1/2)                                            *
- *************************************************************************************************/
-
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-
-#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
-
-static const Uint8 GLES2_VertexTegra_Default_[] = {
-    243, 193, 1, 142, 31, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 46, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 85, 0, 0, 0, 2, 0, 0, 0, 24, 0, 0, 0, 3, 0, 0, 0,
-    91, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 95, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
-    13, 0, 0, 0, 102, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 16, 0, 0, 0, 104, 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 17, 0, 0, 0, 112, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 112, 0, 0, 0, 80, 0, 0, 0, 80, 0, 0, 0, 19, 0, 0, 0, 132, 0,
-    0, 0, 104, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97,
-    95, 112, 111, 115, 105, 116, 105, 111, 110, 0, 97, 95, 116, 101, 120, 67, 111, 111, 114, 100,
-    0, 118, 95, 116, 101, 120, 67, 111, 111, 114, 100, 0, 117, 95, 112, 114, 111, 106, 101, 99,
-    116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 82, 139, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 80, 139, 0,
-    0, 1, 0, 0, 0, 22, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 33, 0, 0, 0, 92, 139, 0, 0,
-    1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 240, 0, 0, 0, 0, 0, 0, 1, 0,
-    0, 0, 64, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 193, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 66, 24, 0, 6, 34, 108, 28,
-    0, 0, 42, 16, 128, 0, 195, 192, 6, 129, 252, 255, 65, 96, 108, 28, 0, 0, 0, 0, 0, 1, 195, 192,
-    6, 1, 252, 255, 33, 96, 108, 156, 31, 64, 8, 1, 64, 0, 131, 192, 6, 1, 156, 159, 65, 96, 108,
-    28, 0, 0, 85, 32, 0, 1, 195, 192, 6, 1, 252, 255, 33, 96, 108, 156, 31, 64, 0, 64, 64, 0, 131,
-    192, 134, 1, 152, 31, 65, 96, 108, 156, 31, 64, 127, 48, 0, 1, 195, 192, 6, 129, 129, 255, 33,
-    96
-};
-
-static const Uint8 GLES2_FragmentTegra_None_SolidSrc_[] = {
-    155, 191, 159, 1, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 75,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
-    75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 13, 0,
-    0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    22, 0, 0, 0, 84, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 15, 0, 0, 0, 93, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 113, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 113, 0, 0,
-    0, 108, 0, 0, 0, 108, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0,
-    0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 117, 95, 99, 111, 108, 111, 114, 0, 0, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0,
-    0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0, 0,
-    0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 21, 32, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 82, 50, 48, 45, 66, 73, 78, 1,
-    0, 0, 0, 1, 0, 0, 0, 1, 0, 65, 37, 0, 0, 0, 0, 1, 0, 0, 21, 0, 0, 0, 0, 1, 0, 1, 38, 0, 0, 0,
-    0, 1, 0, 1, 39, 0, 0, 0, 0, 1, 0, 1, 40, 1, 0, 0, 0, 8, 0, 4, 40, 0, 40, 0, 0, 0, 242, 65, 63,
-    192, 200, 0, 0, 0, 242, 65, 63, 128, 168, 0, 0, 0, 242, 65, 63, 64, 72, 0, 0, 0, 242, 65, 63,
-    1, 0, 6, 40, 0, 0, 0, 0, 1, 0, 1, 41, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Alpha_SolidSrc_[] = {
-    169, 153, 195, 28, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 75,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
-    75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 13, 0,
-    0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    22, 0, 0, 0, 84, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 15, 0, 0, 0, 93, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 113, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 113, 0, 0,
-    0, 220, 0, 0, 0, 220, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0,
-    0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 117, 95, 99, 111, 108, 111, 114, 0, 0, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 118, 118, 17, 241, 0, 0, 0, 240, 0,
-    0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0,
-    0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 21, 32, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 82, 50, 48, 45, 66, 73, 78,
-    1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 65, 37, 8, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 21, 0,
-    0, 0, 0, 3, 0, 1, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 39, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 3, 0, 1, 40, 1, 0, 0, 0, 5, 0, 0, 0, 9, 0, 0, 0, 24, 0, 4, 40, 232, 231, 15,
-    0, 0, 242, 65, 62, 194, 72, 1, 0, 0, 250, 65, 63, 194, 40, 1, 0, 0, 250, 65, 63, 192, 168, 1,
-    0, 0, 242, 1, 64, 192, 168, 1, 0, 0, 242, 1, 68, 168, 32, 0, 0, 0, 50, 64, 0, 192, 168, 15,
-    0, 0, 242, 1, 66, 168, 64, 0, 16, 0, 242, 65, 1, 232, 231, 15, 0, 0, 242, 65, 62, 168, 160,
-    0, 0, 0, 50, 64, 2, 104, 192, 0, 0, 36, 48, 66, 4, 232, 231, 15, 0, 0, 242, 65, 62, 3, 0, 6,
-    40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 41, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Additive_SolidSrc_[] = {
-    59, 71, 42, 17, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0, 0,
-    0, 8, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 75,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
-    75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 13, 0,
-    0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    22, 0, 0, 0, 84, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 15, 0, 0, 0, 93, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 113, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 113, 0, 0,
-    0, 108, 0, 0, 0, 108, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0,
-    0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 117, 95, 99, 111, 108, 111, 114, 0, 0, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 22, 22, 17, 241, 0, 0, 0, 240, 0,
-    0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0,
-    0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 21, 32, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 82, 50, 48, 45, 66, 73, 78,
-    1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 65, 37, 8, 0, 129, 0, 1, 0, 0, 21, 0, 0, 0, 0, 1, 0, 1, 38, 0,
-    0, 0, 0, 1, 0, 1, 39, 0, 0, 0, 0, 1, 0, 1, 40, 1, 0, 0, 0, 8, 0, 4, 40, 192, 200, 0, 0, 0, 26,
-    0, 70, 192, 40, 0, 0, 0, 2, 0, 64, 192, 72, 0, 0, 0, 10, 0, 66, 192, 168, 0, 0, 0, 18, 0, 68,
-    1, 0, 6, 40, 0, 0, 0, 0, 1, 0, 1, 41, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Modulated_SolidSrc_[] = {
-    37, 191, 49, 17, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0, 0,
-    0, 8, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 75,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
-    75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 13, 0,
-    0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 14, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    22, 0, 0, 0, 84, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 15, 0, 0, 0, 93, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 113, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 113, 0, 0,
-    0, 108, 0, 0, 0, 108, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0,
-    0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 117, 95, 99, 111, 108, 111, 114, 0, 0, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 32, 32, 17, 241, 0, 0, 0, 240, 0,
-    0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0,
-    0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 21, 32, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 82, 50, 48, 45, 66, 73, 78,
-    1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 65, 37, 8, 0, 129, 0, 1, 0, 0, 21, 0, 0, 0, 0, 1, 0, 1, 38, 0,
-    0, 0, 0, 1, 0, 1, 39, 0, 0, 0, 0, 1, 0, 1, 40, 1, 0, 0, 0, 8, 0, 4, 40, 104, 192, 0, 0, 0, 242,
-    1, 70, 8, 32, 0, 0, 0, 242, 1, 64, 40, 64, 0, 0, 0, 242, 1, 66, 72, 160, 0, 0, 0, 242, 1, 68,
-    1, 0, 6, 40, 0, 0, 0, 0, 1, 0, 1, 41, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_None_TextureSrc_[] = {
-    220, 217, 41, 211, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-    82, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 6, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
-    0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 2, 0, 0, 0, 56, 0, 0, 0,
-    13, 0, 0, 0, 101, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 22, 0, 0, 0, 106, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 114, 0, 0, 0, 1, 0,
-    0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 115, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 135,
-    0, 0, 0, 120, 0, 0, 0, 120, 0, 0, 0, 20, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
-    0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 118, 95, 116, 101, 120, 67, 111, 111, 114, 100, 0, 117, 95, 109, 111, 100, 117, 108,
-    97, 116, 105, 111, 110, 0, 117, 95, 116, 101, 120, 116, 117, 114, 101, 0, 0, 0, 0, 0, 0, 0,
-    2, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 94, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0,
-    0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 1, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240,
-    0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0,
-    0, 0, 1, 0, 0, 0, 21, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0,
-    0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 65, 82, 50, 48, 45, 66, 73, 78, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 65, 37, 0, 0, 0, 0, 1, 0,
-    0, 21, 0, 0, 0, 0, 1, 0, 1, 38, 1, 0, 0, 0, 2, 0, 4, 38, 186, 81, 78, 16, 2, 1, 0, 0, 1, 0,
-    1, 39, 0, 4, 0, 0, 1, 0, 1, 40, 1, 0, 0, 0, 8, 0, 4, 40, 104, 192, 0, 0, 0, 242, 1, 70, 8, 32,
-    0, 0, 0, 242, 1, 64, 40, 64, 0, 0, 0, 242, 1, 66, 72, 160, 0, 0, 0, 242, 1, 68, 1, 0, 6, 40,
-    0, 0, 0, 0, 1, 0, 1, 41, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Alpha_TextureSrc_[] = {
-    71, 202, 114, 229, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-    82, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 6, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
-    0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 2, 0, 0, 0, 56, 0, 0, 0,
-    13, 0, 0, 0, 101, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 22, 0, 0, 0, 106, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 114, 0, 0, 0, 1, 0,
-    0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 115, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 135,
-    0, 0, 0, 176, 0, 0, 0, 176, 0, 0, 0, 20, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
-    0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 118, 95, 116, 101, 120, 67, 111, 111, 114, 100, 0, 117, 95, 109, 111, 100, 117, 108,
-    97, 116, 105, 111, 110, 0, 117, 95, 116, 101, 120, 116, 117, 114, 101, 0, 0, 0, 0, 0, 0, 0,
-    2, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 94, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0,
-    0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 1, 118, 118, 17, 241, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0,
-    240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0,
-    1, 0, 0, 0, 2, 0, 0, 0, 21, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 16,
-    0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 65, 82, 50, 48, 45, 66, 73, 78, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 65, 37, 0, 0, 0, 0,
-    8, 0, 129, 0, 1, 0, 0, 21, 0, 0, 0, 0, 2, 0, 1, 38, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 38, 186,
-    81, 78, 16, 2, 1, 0, 0, 2, 0, 1, 39, 0, 4, 0, 0, 0, 0, 0, 0, 2, 0, 1, 40, 1, 0, 0, 0, 5, 0,
-    0, 0, 16, 0, 4, 40, 40, 160, 1, 0, 0, 242, 1, 66, 8, 192, 1, 0, 0, 242, 1, 64, 104, 32, 1, 0,
-    0, 242, 1, 70, 72, 64, 1, 0, 0, 242, 1, 68, 154, 192, 0, 0, 37, 34, 64, 3, 8, 32, 0, 0, 5, 58,
-    208, 4, 40, 64, 0, 0, 5, 50, 208, 4, 72, 160, 0, 0, 37, 42, 208, 4, 2, 0, 6, 40, 0, 0, 0, 0,
-    0, 0, 0, 0, 2, 0, 1, 41, 0, 0, 0, 0, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Additive_TextureSrc_[] = {
-    161, 234, 193, 234, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-    82, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 6, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
-    0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 2, 0, 0, 0, 56, 0, 0, 0,
-    13, 0, 0, 0, 101, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 22, 0, 0, 0, 106, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 114, 0, 0, 0, 1, 0,
-    0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 115, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 135,
-    0, 0, 0, 176, 0, 0, 0, 176, 0, 0, 0, 20, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
-    0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 118, 95, 116, 101, 120, 67, 111, 111, 114, 100, 0, 117, 95, 109, 111, 100, 117, 108,
-    97, 116, 105, 111, 110, 0, 117, 95, 116, 101, 120, 116, 117, 114, 101, 0, 0, 0, 0, 0, 0, 0,
-    2, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 94, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0,
-    0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 1, 22, 22, 17, 241, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240,
-    0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 1, 0,
-    0, 0, 2, 0, 0, 0, 21, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0,
-    0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 65, 82, 50, 48, 45, 66, 73, 78, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 65, 37, 0, 0, 0, 0, 8, 0,
-    129, 0, 1, 0, 0, 21, 0, 0, 0, 0, 2, 0, 1, 38, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 38, 186, 81,
-    78, 16, 2, 1, 0, 0, 2, 0, 1, 39, 0, 4, 0, 0, 0, 0, 0, 0, 2, 0, 1, 40, 1, 0, 0, 0, 5, 0, 0, 0,
-    16, 0, 4, 40, 40, 160, 1, 0, 0, 242, 1, 66, 104, 32, 1, 0, 0, 242, 1, 70, 8, 192, 1, 0, 0, 242,
-    1, 64, 72, 64, 1, 0, 0, 242, 1, 68, 136, 192, 0, 0, 0, 26, 64, 4, 136, 32, 0, 0, 0, 2, 64, 7,
-    136, 64, 0, 0, 0, 10, 64, 6, 136, 160, 0, 0, 0, 18, 64, 5, 2, 0, 6, 40, 0, 0, 0, 0, 0, 0, 0,
-    0, 2, 0, 1, 41, 0, 0, 0, 0, 5, 0, 2, 0
-};
-
-static const Uint8 GLES2_FragmentTegra_Modulated_TextureSrc_[] = {
-    75, 132, 201, 227, 47, 109, 131, 38, 6, 0, 1, 0, 5, 0, 0, 0, 17, 0, 0, 0, 1, 0, 0, 0, 73, 0,
-    0, 0, 34, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
-    82, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 6, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
-    0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 2, 0, 0, 0, 56, 0, 0, 0,
-    13, 0, 0, 0, 101, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 4,
-    0, 0, 0, 22, 0, 0, 0, 106, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 23, 0, 0, 0, 114, 0, 0, 0, 1, 0,
-    0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 115, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 135,
-    0, 0, 0, 176, 0, 0, 0, 176, 0, 0, 0, 20, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
-    0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 97, 110, 70, 73, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 118, 95, 116, 101, 120, 67, 111, 111, 114, 100, 0, 117, 95, 109, 111, 100, 117, 108,
-    97, 116, 105, 111, 110, 0, 117, 95, 116, 101, 120, 116, 117, 114, 101, 0, 0, 0, 0, 0, 0, 0,
-    2, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 82, 139, 0, 0, 1, 0, 0, 0, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 94, 139, 0, 0, 1, 0, 0, 0, 1, 0, 0,
-    0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 5, 48, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 1, 32, 32, 17, 241, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 240,
-    0, 0, 0, 240, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 1, 0,
-    0, 0, 2, 0, 0, 0, 21, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0,
-    0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 65, 82, 50, 48, 45, 66, 73, 78, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 65, 37, 0, 0, 0, 0, 8, 0,
-    129, 0, 1, 0, 0, 21, 0, 0, 0, 0, 2, 0, 1, 38, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 38, 186, 81,
-    78, 16, 2, 1, 0, 0, 2, 0, 1, 39, 0, 4, 0, 0, 0, 0, 0, 0, 2, 0, 1, 40, 1, 0, 0, 0, 5, 0, 0, 0,
-    16, 0, 4, 40, 40, 160, 1, 0, 0, 242, 1, 66, 8, 192, 1, 0, 0, 242, 1, 64, 104, 32, 1, 0, 0, 242,
-    1, 70, 72, 64, 1, 0, 0, 242, 1, 68, 104, 192, 0, 0, 0, 242, 65, 4, 232, 32, 0, 0, 0, 242, 65,
-    0, 40, 64, 0, 0, 0, 242, 65, 6, 72, 160, 0, 0, 0, 242, 65, 5, 2, 0, 6, 40, 0, 0, 0, 0, 0, 0,
-    0, 0, 2, 0, 1, 41, 0, 0, 0, 0, 5, 0, 2, 0
-};
-
-static const GLES2_ShaderInstance GLES2_VertexTegra_Default = {
-    GL_VERTEX_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_VertexTegra_Default_),
-    GLES2_VertexTegra_Default_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_None_SolidSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_None_SolidSrc_),
-    GLES2_FragmentTegra_None_SolidSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Alpha_SolidSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Alpha_SolidSrc_),
-    GLES2_FragmentTegra_Alpha_SolidSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Additive_SolidSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Additive_SolidSrc_),
-    GLES2_FragmentTegra_Additive_SolidSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Modulated_SolidSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Modulated_SolidSrc_),
-    GLES2_FragmentTegra_Modulated_SolidSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_None_TextureSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_None_TextureSrc_),
-    GLES2_FragmentTegra_None_TextureSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Alpha_TextureSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Alpha_TextureSrc_),
-    GLES2_FragmentTegra_Alpha_TextureSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Additive_TextureSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Additive_TextureSrc_),
-    GLES2_FragmentTegra_Additive_TextureSrc_
-};
-
-static const GLES2_ShaderInstance GLES2_FragmentTegra_Modulated_TextureSrc = {
-    GL_FRAGMENT_SHADER,
-    GL_NVIDIA_PLATFORM_BINARY_NV,
-    sizeof(GLES2_FragmentTegra_Modulated_TextureSrc_),
-    GLES2_FragmentTegra_Modulated_TextureSrc_
-};
-
-#endif /* GLES2_INCLUDE_NVIDIA_SHADERS */
-
 /*************************************************************************************************
  * Vertex/fragment shader definitions                                                            *
  *************************************************************************************************/
 
 static GLES2_Shader GLES2_VertexShader_Default = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
     1,
-#endif
     {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_VertexTegra_Default,
-#endif
         &GLES2_VertexSrc_Default
     }
 };
 
-static GLES2_Shader GLES2_FragmentShader_None_SolidSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_None_SolidSrc,
-#endif
-        &GLES2_FragmentSrc_SolidSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Alpha_SolidSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
+static GLES2_Shader GLES2_FragmentShader_SolidSrc = {
     1,
-#endif
     {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Alpha_SolidSrc,
-#endif
         &GLES2_FragmentSrc_SolidSrc
     }
 };
 
-static GLES2_Shader GLES2_FragmentShader_Additive_SolidSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Additive_SolidSrc,
-#endif
-        &GLES2_FragmentSrc_SolidSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Modulated_SolidSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Modulated_SolidSrc,
-#endif
-        &GLES2_FragmentSrc_SolidSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_None_TextureABGRSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_None_TextureSrc,
-#endif
-        &GLES2_FragmentSrc_TextureABGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Alpha_TextureABGRSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Alpha_TextureSrc,
-#endif
-        &GLES2_FragmentSrc_TextureABGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Additive_TextureABGRSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
+static GLES2_Shader GLES2_FragmentShader_TextureABGRSrc = {
     1,
-#endif
     {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Additive_TextureSrc,
-#endif
         &GLES2_FragmentSrc_TextureABGRSrc
     }
 };
 
-static GLES2_Shader GLES2_FragmentShader_Modulated_TextureABGRSrc = {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-    2,
-#else
-    1,
-#endif
-    {
-#if GLES2_INCLUDE_NVIDIA_SHADERS
-        &GLES2_FragmentTegra_Modulated_TextureSrc,
-#endif
-        &GLES2_FragmentSrc_TextureABGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_None_TextureARGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureARGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Alpha_TextureARGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureARGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Additive_TextureARGBSrc = {
+static GLES2_Shader GLES2_FragmentShader_TextureARGBSrc = {
     1,
     {
         &GLES2_FragmentSrc_TextureARGBSrc
     }
 };
 
-static GLES2_Shader GLES2_FragmentShader_Modulated_TextureARGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureARGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_None_TextureRGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureRGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Alpha_TextureRGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureRGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Additive_TextureRGBSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureRGBSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Modulated_TextureRGBSrc = {
+static GLES2_Shader GLES2_FragmentShader_TextureRGBSrc = {
     1,
     {
         &GLES2_FragmentSrc_TextureRGBSrc
     }
 };
 
-static GLES2_Shader GLES2_FragmentShader_None_TextureBGRSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureBGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Alpha_TextureBGRSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureBGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Additive_TextureBGRSrc = {
-    1,
-    {
-        &GLES2_FragmentSrc_TextureBGRSrc
-    }
-};
-
-static GLES2_Shader GLES2_FragmentShader_Modulated_TextureBGRSrc = {
+static GLES2_Shader GLES2_FragmentShader_TextureBGRSrc = {
     1,
     {
         &GLES2_FragmentSrc_TextureBGRSrc
@@ -808,94 +330,27 @@ static GLES2_Shader GLES2_FragmentShader_TextureNV21Src = {
  * Shader selector                                                                               *
  *************************************************************************************************/
 
-const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMode)
+const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type)
 {
     switch (type) {
     case GLES2_SHADER_VERTEX_DEFAULT:
         return &GLES2_VertexShader_Default;
     case GLES2_SHADER_FRAGMENT_SOLID_SRC:
-    switch (blendMode) {
-    case SDL_BLENDMODE_NONE:
-        return &GLES2_FragmentShader_None_SolidSrc;
-    case SDL_BLENDMODE_BLEND:
-        return &GLES2_FragmentShader_Alpha_SolidSrc;
-    case SDL_BLENDMODE_ADD:
-        return &GLES2_FragmentShader_Additive_SolidSrc;
-    case SDL_BLENDMODE_MOD:
-        return &GLES2_FragmentShader_Modulated_SolidSrc;
-    default:
-        return NULL;
-    }
+        return &GLES2_FragmentShader_SolidSrc;
     case GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC:
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
-            return &GLES2_FragmentShader_None_TextureABGRSrc;
-        case SDL_BLENDMODE_BLEND:
-            return &GLES2_FragmentShader_Alpha_TextureABGRSrc;
-        case SDL_BLENDMODE_ADD:
-            return &GLES2_FragmentShader_Additive_TextureABGRSrc;
-        case SDL_BLENDMODE_MOD:
-            return &GLES2_FragmentShader_Modulated_TextureABGRSrc;
-        default:
-            return NULL;
-    }
+        return &GLES2_FragmentShader_TextureABGRSrc;
     case GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC:
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
-            return &GLES2_FragmentShader_None_TextureARGBSrc;
-        case SDL_BLENDMODE_BLEND:
-            return &GLES2_FragmentShader_Alpha_TextureARGBSrc;
-        case SDL_BLENDMODE_ADD:
-            return &GLES2_FragmentShader_Additive_TextureARGBSrc;
-        case SDL_BLENDMODE_MOD:
-            return &GLES2_FragmentShader_Modulated_TextureARGBSrc;
-        default:
-            return NULL;
-    }
-
+        return &GLES2_FragmentShader_TextureARGBSrc;
     case GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC:
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
-            return &GLES2_FragmentShader_None_TextureRGBSrc;
-        case SDL_BLENDMODE_BLEND:
-            return &GLES2_FragmentShader_Alpha_TextureRGBSrc;
-        case SDL_BLENDMODE_ADD:
-            return &GLES2_FragmentShader_Additive_TextureRGBSrc;
-        case SDL_BLENDMODE_MOD:
-            return &GLES2_FragmentShader_Modulated_TextureRGBSrc;
-        default:
-            return NULL;
-    }
-
+        return &GLES2_FragmentShader_TextureRGBSrc;
     case GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC:
-        switch (blendMode) {
-        case SDL_BLENDMODE_NONE:
-            return &GLES2_FragmentShader_None_TextureBGRSrc;
-        case SDL_BLENDMODE_BLEND:
-            return &GLES2_FragmentShader_Alpha_TextureBGRSrc;
-        case SDL_BLENDMODE_ADD:
-            return &GLES2_FragmentShader_Additive_TextureBGRSrc;
-        case SDL_BLENDMODE_MOD:
-            return &GLES2_FragmentShader_Modulated_TextureBGRSrc;
-        default:
-            return NULL;
-    }
-    
+        return &GLES2_FragmentShader_TextureBGRSrc;
     case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC:
-    {
         return &GLES2_FragmentShader_TextureYUVSrc;
-    }
-
     case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC:
-    {
         return &GLES2_FragmentShader_TextureNV12Src;
-    }
-
     case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC:
-    {
         return &GLES2_FragmentShader_TextureNV21Src;
-    }
-
     default:
         return NULL;
     }

+ 1 - 1
src/render/opengles2/SDL_shaders_gles2.h

@@ -54,7 +54,7 @@ typedef enum
 
 #define GLES2_SOURCE_SHADER (GLenum)-1
 
-const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMode);
+const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type);
 
 #endif /* SDL_shaders_gles2_h_ */
 

+ 9 - 1
test/testsprite2.c

@@ -99,7 +99,12 @@ LoadSprite(const char *file)
             SDL_FreeSurface(temp);
             return (-1);
         }
-        SDL_SetTextureBlendMode(sprites[i], blendMode);
+        if (SDL_SetTextureBlendMode(sprites[i], blendMode) < 0) {
+            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set blend mode: %s\n", SDL_GetError());
+            SDL_FreeSurface(temp);
+            SDL_DestroyTexture(sprites[i]);
+            return (-1);
+        }
     }
     SDL_FreeSurface(temp);
 
@@ -295,6 +300,9 @@ main(int argc, char *argv[])
                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
                         blendMode = SDL_BLENDMODE_MOD;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "sub") == 0) {
+                        blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
+                        consumed = 2;
                     }
                 }
             } else if (SDL_strcasecmp(argv[i], "--iterations") == 0) {