port: detect gl core and GLES3 at runtime; add hacks to make it work properly

This commit is contained in:
fgsfds committed 2024-11-20 12:07:18 +01:00
1 parent 140f6f24e8
commit 3c020cad84
4 files changed
+1725 -2255

No files matched your search

+107 -48
View File
@@ -57,8 +57,10 @@ static float current_noise_scale;
static FilteringMode current_filter_mode = FILTER_LINEAR;
static bool current_textures_linear_filter[2] = {false, false};
static int gl_glsl_version = 130;
static char gl_glsl_version_str[16] = "130";
static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE;
static bool gl_es = false;
static bool gl_core_profile = false;
static int gfx_opengl_get_max_texture_size() {
@@ -243,15 +245,19 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
// Vertex shader
#ifdef __APPLE__
append_line(vs_buf, &vs_len, "#version 410 core");
append_line(vs_buf, &vs_len, "#define INPUT in");
append_line(vs_buf, &vs_len, "#define OUTPUT out");
#else
append_line(vs_buf, &vs_len, "#version 110");
append_line(vs_buf, &vs_len, "#define INPUT attribute");
append_line(vs_buf, &vs_len, "#define OUTPUT varying");
#endif
vs_len += sprintf(vs_buf + vs_len, "#version %s\n", gl_glsl_version_str);
if (gl_es) {
append_line(vs_buf, &vs_len, "precision mediump float;");
}
if (gl_glsl_version >= 130) {
append_line(vs_buf, &vs_len, "#define INPUT in");
append_line(vs_buf, &vs_len, "#define OUTPUT out");
} else {
append_line(vs_buf, &vs_len, "#define INPUT attribute");
append_line(vs_buf, &vs_len, "#define OUTPUT varying");
}
append_line(vs_buf, &vs_len, "INPUT vec4 aVtxPos;");
@@ -308,22 +314,31 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
for (int i = 0; i < cc_features.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, " vInput%d = aInput%d;\n", i + 1, i + 1);
}
append_line(vs_buf, &vs_len, " gl_Position = aVtxPos;");
if (!GLAD_GL_ARB_depth_clamp) {
// HACK: workaround for no GL_DEPTH_CLAMP
append_line(vs_buf, &vs_len, " gl_Position.z *= 0.3f;");
}
append_line(vs_buf, &vs_len, "}");
// Fragment shader
#ifdef __APPLE__
append_line(fs_buf, &fs_len, "#version 410 core");
append_line(fs_buf, &fs_len, "#define INPUT in");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR outColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture(tex, uv)");
#else
append_line(fs_buf, &fs_len, "#version 130");
append_line(fs_buf, &fs_len, "#define INPUT varying");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR gl_FragColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture2D(tex, uv)");
#endif
fs_len += sprintf(fs_buf + fs_len, "#version %s\n", gl_glsl_version_str);
if (gl_es) {
append_line(fs_buf, &fs_len, "precision mediump float;");
}
if (gl_glsl_version >= 130) {
append_line(fs_buf, &fs_len, "#define INPUT in");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR outColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture(tex, uv)");
} else {
append_line(fs_buf, &fs_len, "#define INPUT varying");
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR gl_FragColor");
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture2D(tex, uv)");
}
// Reference approach to color wrapping as per GLideN64
// Return wrapped value of x in interval [low, high)
@@ -351,6 +366,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
for (int i = 0; i < cc_features.num_inputs; i++) {
fs_len += sprintf(fs_buf + fs_len, "INPUT vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
}
if (cc_features.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
if (current_filter_mode == FILTER_THREE_POINT)
@@ -418,9 +434,9 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
}
}
#if __APPLE__
append_line(fs_buf, &fs_len, "out vec4 outColor;");
#endif
if (gl_glsl_version >= 130) {
append_line(fs_buf, &fs_len, "out vec4 outColor;");
}
append_line(fs_buf, &fs_len, "void main() {");
@@ -428,7 +444,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
if (cc_features.used_textures[i]) {
bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1];
fs_len += sprintf(fs_buf + fs_len, " vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i);
fs_len += sprintf(fs_buf + fs_len, " vec2 texSize%d = vec2(textureSize(uTex%d, 0));\n", i, i);
if (!s && !t) {
fs_len += sprintf(fs_buf + fs_len, " vec2 vTexCoordAdj%d = vTexCoord%d;\n", i, i);
@@ -520,6 +536,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
} else {
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = vec4(texel, 1.0);");
}
append_line(fs_buf, &fs_len, "}");
vs_buf[vs_len] = '\0';
@@ -744,7 +761,11 @@ static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool d
}
static void gfx_opengl_set_depth_range(float znear, float zfar) {
glDepthRange(znear, zfar);
if (glDepthRangef) {
glDepthRangef(znear, zfar);
} else {
glDepthRange(znear, zfar);
}
}
static void gfx_opengl_set_viewport(int x, int y, int width, int height) {
@@ -814,18 +835,6 @@ static bool gfx_opengl_supports_framebuffers(void) {
return (glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
}
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
// because of the way glad works we'll have to copy the pointers over
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
// sanity check
return (glad_glFramebufferRenderbuffer && glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
}
@@ -890,11 +899,39 @@ static void *gl_load_proc(const char *name) {
return NULL;
}
static void gfx_opengl_init_extensions(void) {
// patch up some extension values and pointers
if (!GLAD_GL_ARB_depth_clamp) {
if (GLAD_GL_EXT_depth_clamp || GLAD_GL_NV_depth_clamp) {
GLAD_GL_ARB_depth_clamp = 1;
}
}
if (GLVersion.major < 3 && !GLAD_GL_ARB_framebuffer_object) {
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
// because of the way glad works we'll have to copy the pointers over
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
}
}
}
static void gfx_opengl_init(void) {
if (!gladLoadGLLoader(gl_load_proc) || glGetString == NULL || glEnable == NULL) {
sysFatalError("Could not load OpenGL.\nReported SDL error: %s", SDL_GetError());
}
gfx_opengl_init_extensions();
if (sysArgCheck("--debug-gl")) {
gfx_opengl_enable_debug();
// dump version info as early as possible
@@ -908,7 +945,7 @@ static void gfx_opengl_init(void) {
}
if (!gfx_opengl_supports_shaders()) {
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 unsupported");
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 may be unsupported");
// maybe replace this with sysFatalError, though the GLSL compiler will cause that later anyway
}
@@ -924,20 +961,41 @@ static void gfx_opengl_init(void) {
gl_mirror_clamp = GL_MIRRORED_REPEAT;
}
if ((GLVersion.major == 3 && GLVersion.minor >= 2) || GLVersion.major > 3) {
// check if we're using core profile, which is more strict
int val = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
// check if we're using ES or core, which have more limited feature sets
int val = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
gl_es = (val == SDL_GL_CONTEXT_PROFILE_ES);
// determine GLSL version
if (gl_es) {
// ES has its own numbering scheme, but it should support 300 even on 3.1 and 3.2
gl_glsl_version = 300;
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d es", gl_glsl_version);
} else if (!gl_core_profile) {
// in compat profile we can just request the lowest possible
gl_glsl_version = 130;
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d", gl_glsl_version);
} else {
// otherwise we have to pick a specific version
if (GLVersion.major == 3 && GLVersion.minor == 2) {
// 3.2core is the earliest core version and it follows the old numbering scheme
gl_glsl_version = 150;
} else {
// 3.3+ follow the new numbering scheme
gl_glsl_version = GLVersion.major * 100 + GLVersion.minor * 10;
}
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d core", gl_glsl_version);
}
sysLogPrintf(LOG_NOTE, "GL: using GLSL version %s", gl_glsl_version_str);
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
if (gl_core_profile) {
if (gl_core_profile || gl_es) {
// warn user that funny things can happen
sysLogPrintf(LOG_WARNING, "GL: using core profile, watch out for errors");
// core will explode if we don't use a VAO for our VBO
sysLogPrintf(LOG_WARNING, "GL: using core profile or ES, watch out for errors");
// core/es will explode if we don't use a VAO for our VBO
glGenVertexArrays(1, &opengl_vao);
glBindVertexArray(opengl_vao);
}
@@ -1156,7 +1214,8 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool
}
if (fb_src == 0) {
glReadBuffer(use_back ? GL_BACK : GL_FRONT);
// GLES does not support GL_FRONT here
glReadBuffer((use_back || gl_es) ? GL_BACK : GL_FRONT);
} else {
glReadBuffer(GL_COLOR_ATTACHMENT0);
}
+14 -10
View File
@@ -128,20 +128,21 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
// if that doesn't work, try 3.2 core in case we're on mac, 2.1 compat as a last resort
static u32 glver[][3] = {
{ 0, 0, 0 }, // for command line override
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY },
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE },
{ 4, 1, SDL_GL_CONTEXT_PROFILE_CORE },
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // will still require GLSL130
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 3.0: default, has all the features required
{ 4, 1, SDL_GL_CONTEXT_PROFILE_CORE }, // 4.1core: macs only have core profile and this is the latest
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE }, // 3.2core: older macs will only have this at best
{ 3, 0, SDL_GL_CONTEXT_PROFILE_ES }, // es3: don't really support ES properly, but we can try
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 2.1: absolute last resort, will still require GLSL130 as an extension
};
u32 glcore = false;
u32 verstart = 1;
const u32 verend = sizeof(glver) / sizeof(*glver);
const char *verstr = sysArgGetString("--gl-version");
if (verstr && *verstr) {
// user override
glver[0][2] = strstr(verstr, "core") ? SDL_GL_CONTEXT_PROFILE_CORE :
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
(strstr(verstr, "es") ? SDL_GL_CONTEXT_PROFILE_ES :
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
sscanf(verstr, "%d.%d", &glver[0][0], &glver[0][1]);
if (glver[0][0] >= 1 && glver[0][0] <= 4 && glver[0][1] < 9) {
verstart = 0;
@@ -149,18 +150,21 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
}
ctx = NULL;
u32 vmin = 0, vmaj = 0;
u32 vmin = 0, vmaj = 0, vprof = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
const char *vprofstr = "";
for (u32 i = verstart; i < verend; ++i) {
vmaj = glver[i][0];
vmin = glver[i][1];
vprof = glver[i][2];
vprofstr = (glver[i][2] == SDL_GL_CONTEXT_PROFILE_CORE ? "core" :
(glver[i][2] == SDL_GL_CONTEXT_PROFILE_ES ? "es" : ""));
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, vmaj);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, vmin);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, glver[i][2]);
ctx = SDL_GL_CreateContext(wnd);
if (!ctx) {
sysLogPrintf(LOG_WARNING, "GL: could not create GL%d.%d context: %s", vmaj, vmin, SDL_GetError());
sysLogPrintf(LOG_WARNING, "GL: could not create GL%d.%d%s context: %s", vmaj, vmin, vprofstr, SDL_GetError());
} else {
glcore = (glver[i][2] == SDL_GL_CONTEXT_PROFILE_CORE);
break;
}
}
@@ -168,7 +172,7 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
if (!ctx) {
sysFatalError("Could not create an OpenGL context of any supported version.\nSDL error: %s", SDL_GetError());
} else {
sysLogPrintf(LOG_NOTE, "GL: created GL%d.%d%s context", vmaj, vmin, glcore ? "core" : "");
sysLogPrintf(LOG_NOTE, "GL: created GL%d.%d%s context", vmaj, vmin, vprofstr);
}
SDL_GL_MakeCurrent(wnd, ctx);
+763 -709
View File
File diff suppressed because it is too large. Load diff
+841 -1488
View File
File diff suppressed because it is too large. Load diff