diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 38d46b8c89..55aaca6a39 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/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 diff --git a/src/render/opengl/SDL_shaders_gl.c b/src/render/opengl/SDL_shaders_gl.c index 069123b24e..1648751271 100644 --- a/src/render/opengl/SDL_shaders_gl.c +++ b/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; diff --git a/src/render/opengl/SDL_shaders_gl.h b/src/render/opengl/SDL_shaders_gl.h index 350018b9a9..438418472c 100644 --- a/src/render/opengl/SDL_shaders_gl.h +++ b/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);