Kaynağa Gözat

Handle partial OpenGL shader availability

The pixelart shaders are not supported on OpenGL 2.1 (GLSL 130 isn't available)

Fixes the OpenGL renderer on macOS
Sam Lantinga 11 ay önce
ebeveyn
işleme
7a49ce71a1

+ 41 - 8
src/render/opengl/SDL_render_gl.c

@@ -91,6 +91,7 @@ typedef struct
 
     bool debug_enabled;
     bool GL_ARB_debug_output_supported;
+    bool pixelart_supported;
     int errors;
     char **error_messages;
     GLDEBUGPROCARB next_error_callback;
@@ -455,7 +456,13 @@ static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_PixelFo
         data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         break;
-    case SDL_SCALEMODE_PIXELART:    // Uses linear sampling
+    case SDL_SCALEMODE_PIXELART:    // Uses linear sampling if supported
+        if (!data->pixelart_supported) {
+            data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            break;
+        }
+        SDL_FALLTHROUGH;
     case SDL_SCALEMODE_LINEAR:
         if (format == SDL_PIXELFORMAT_INDEX8) {
             // We'll do linear sampling in the shader
@@ -1210,19 +1217,22 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
         if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_LINEAR) {
             shader = SHADER_PALETTE_LINEAR;
             shader_params = texturedata->texel_size;
-        } else if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
+        } else if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART &&
+                   data->pixelart_supported) {
             shader = SHADER_PALETTE_PIXELART;
             shader_params = texturedata->texel_size;
         }
         break;
     case SHADER_RGB:
-        if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
+        if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART &&
+            data->pixelart_supported) {
             shader = SHADER_RGB_PIXELART;
             shader_params = texturedata->texel_size;
         }
         break;
     case SHADER_RGBA:
-        if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
+        if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART &&
+            data->pixelart_supported) {
             shader = SHADER_RGBA_PIXELART;
             shader_params = texturedata->texel_size;
         }
@@ -1928,27 +1938,50 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
     data->shaders = GL_CreateShaderContext();
     SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
                 data->shaders ? "ENABLED" : "DISABLED");
-    if (data->shaders) {
+    if (GL_SupportsShader(data->shaders, SHADER_RGB)) {
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
         if (bgra_supported) {
             SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
         }
+    } else {
+        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL RGB shaders not supported");
+    }
+    // We support PIXELART mode using a shader
+    if (GL_SupportsShader(data->shaders, SHADER_RGB_PIXELART) &&
+        GL_SupportsShader(data->shaders, SHADER_RGBA_PIXELART)) {
+        data->pixelart_supported = true;
+    } else {
+        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL PIXELART shaders not supported");
     }
     // We support INDEX8 textures using 2 textures and a shader
-    if (data->shaders && data->num_texture_units >= 2) {
+    if (GL_SupportsShader(data->shaders, SHADER_PALETTE_NEAREST) &&
+        GL_SupportsShader(data->shaders, SHADER_PALETTE_LINEAR) &&
+        (!data->pixelart_supported || GL_SupportsShader(data->shaders, SHADER_PALETTE_PIXELART)) &&
+        data->num_texture_units >= 2) {
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
+    } else {
+        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL palette shaders not supported");
     }
 #ifdef SDL_HAVE_YUV
     // We support YV12 textures using 3 textures and a shader
-    if (data->shaders && data->num_texture_units >= 3) {
+    if (GL_SupportsShader(data->shaders, SHADER_YUV) &&
+        data->num_texture_units >= 3) {
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
+    } else {
+        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL YUV not supported");
     }
 
     // We support NV12 textures using 2 textures and a shader
-    if (data->shaders && data->num_texture_units >= 2) {
+    if (GL_SupportsShader(data->shaders, SHADER_NV12_RA) &&
+        GL_SupportsShader(data->shaders, SHADER_NV12_RG) &&
+        GL_SupportsShader(data->shaders, SHADER_NV21_RA) &&
+        GL_SupportsShader(data->shaders, SHADER_NV21_RG) &&
+        data->num_texture_units >= 2) {
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
         SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
+    } else {
+        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL NV12/NV21 not supported");
     }
 #endif
 #ifdef SDL_PLATFORM_MACOS

+ 27 - 9
src/render/opengl/SDL_shaders_gl.c

@@ -520,10 +520,15 @@ static bool CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char
         info = SDL_small_alloc(char, length + 1, &isstack);
         if (info) {
             ctx->glGetInfoLogARB(shader, length, NULL, info);
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to compile shader:");
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", defines);
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", source);
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", info);
+            SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Failed to compile shader:");
+            if (version) {
+                SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", version);
+            }
+            if (defines) {
+                SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", defines);
+            }
+            SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", source);
+            SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", info);
             SDL_small_free(info, isstack);
         }
         return false;
@@ -598,9 +603,18 @@ static bool CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData
 
 static void DestroyShaderProgram(GL_ShaderContext *ctx, GL_ShaderData *data)
 {
-    ctx->glDeleteObjectARB(data->vert_shader);
-    ctx->glDeleteObjectARB(data->frag_shader);
-    ctx->glDeleteObjectARB(data->program);
+    if (data->vert_shader) {
+        ctx->glDeleteObjectARB(data->vert_shader);
+        data->vert_shader = 0;
+    }
+    if (data->frag_shader) {
+        ctx->glDeleteObjectARB(data->frag_shader);
+        data->frag_shader = 0;
+    }
+    if (data->program) {
+        ctx->glDeleteObjectARB(data->program);
+        data->program = 0;
+    }
 }
 
 GL_ShaderContext *GL_CreateShaderContext(void)
@@ -669,8 +683,7 @@ GL_ShaderContext *GL_CreateShaderContext(void)
     // Compile all the shaders
     for (i = 0; i < NUM_SHADERS; ++i) {
         if (!CompileShaderProgram(ctx, i, &ctx->shaders[i])) {
-            GL_DestroyShaderContext(ctx);
-            return NULL;
+            DestroyShaderProgram(ctx, &ctx->shaders[i]);
         }
     }
 
@@ -678,6 +691,11 @@ GL_ShaderContext *GL_CreateShaderContext(void)
     return ctx;
 }
 
+bool GL_SupportsShader(GL_ShaderContext *ctx, GL_Shader shader)
+{
+    return ctx && ctx->shaders[shader].program;
+}
+
 void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params)
 {
     GLint location;

+ 1 - 0
src/render/opengl/SDL_shaders_gl.h

@@ -51,6 +51,7 @@ typedef enum
 typedef struct GL_ShaderContext GL_ShaderContext;
 
 extern GL_ShaderContext *GL_CreateShaderContext(void);
+extern bool GL_SupportsShader(GL_ShaderContext *ctx, GL_Shader shader);
 extern void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params);
 extern void GL_DestroyShaderContext(GL_ShaderContext *ctx);