From 637035000610477d043c952706c9c4b581b17a02 Mon Sep 17 00:00:00 2001 From: Quantum Date: Thu, 30 Sep 2021 06:36:24 -0400 Subject: [PATCH] [client] opengl: indirectly access non-OpenGL 1.3 functions This commit adds check for the extensions that we need and then calls the functions indirectly through gl_dynprocs. This should improve compatibility with older versions of OpenGL, as we now fallback to the ARB extensions if possible, and in the case of glGenerateMipmap, we can handle the function not existing at all. --- client/renderers/OpenGL/opengl.c | 62 ++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index d47855b3..12393572 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -35,6 +35,7 @@ #include "common/option.h" #include "common/framebuffer.h" #include "common/locking.h" +#include "gl_dynprocs.h" #include "ll.h" #include "util.h" @@ -413,6 +414,31 @@ bool opengl_renderStartup(LG_Renderer * renderer, bool useDMA) DEBUG_INFO("GL_AMD_pinned_memory is available but not in use"); } + GLint maj, min; + glGetIntegerv(GL_MAJOR_VERSION, &maj); + glGetIntegerv(GL_MINOR_VERSION, &min); + + if ((maj < 3 || (maj == 3 && min < 2)) && !util_hasGLExt(exts, "GL_ARB_sync")) + { + DEBUG_ERROR("Need OpenGL 3.2+ or GL_ARB_sync for sync objects"); + return false; + } + + if (maj < 2 && !util_hasGLExt(exts, "GL_ARB_pixel_buffer_object")) + { + DEBUG_ERROR("Need OpenGL 2.0+ or GL_ARB_pixel_buffer_object"); + return false; + } + + if (this->opt.mipmap && maj < 3 && + !util_hasGLExt(exts, "GL_ARB_framebuffer_object") && + !util_hasGLExt(exts, "GL_EXT_framebuffer_object")) + { + DEBUG_WARN("Need OpenGL 3.0+ or GL_ARB_framebuffer_object or " + "GL_EXT_framebuffer_object for glGenerateMipmap, disabling mipmaps"); + this->opt.mipmap = false; + } + glEnable(GL_TEXTURE_2D); glEnable(GL_COLOR_MATERIAL); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -705,7 +731,7 @@ static enum ConfigStatus configure(struct Inst * this) this->texSize = this->format.height * this->format.pitch; this->texPos = 0; - glGenBuffers(BUFFER_COUNT, this->vboID); + g_gl_dynProcs.glGenBuffers(BUFFER_COUNT, this->vboID); if (check_gl_error("glGenBuffers")) { LG_UNLOCK(this->formatLock); @@ -728,14 +754,14 @@ static enum ConfigStatus configure(struct Inst * this) memset(this->texPixels[i], 0, this->texSize); - glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, this->vboID[i]); + g_gl_dynProcs.glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, this->vboID[i]); if (check_gl_error("glBindBuffer")) { LG_UNLOCK(this->formatLock); return CONFIG_STATUS_ERROR; } - glBufferData( + g_gl_dynProcs.glBufferData( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, this->texSize, this->texPixels[i], @@ -748,20 +774,20 @@ static enum ConfigStatus configure(struct Inst * this) return CONFIG_STATUS_ERROR; } } - glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0); + g_gl_dynProcs.glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0); } else { for(int i = 0; i < BUFFER_COUNT; ++i) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[i]); + g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[i]); if (check_gl_error("glBindBuffer")) { LG_UNLOCK(this->formatLock); return CONFIG_STATUS_ERROR; } - glBufferData( + g_gl_dynProcs.glBufferData( GL_PIXEL_UNPACK_BUFFER, this->texSize, NULL, @@ -773,7 +799,7 @@ static enum ConfigStatus configure(struct Inst * this) return CONFIG_STATUS_ERROR; } } - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } // create the frame textures @@ -833,7 +859,7 @@ static enum ConfigStatus configure(struct Inst * this) } glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); this->drawStart = nanotime(); this->configured = true; @@ -853,7 +879,7 @@ static void deconfigure(struct Inst * this) if (this->hasBuffers) { - glDeleteBuffers(BUFFER_COUNT, this->vboID); + g_gl_dynProcs.glDeleteBuffers(BUFFER_COUNT, this->vboID); this->hasBuffers = false; } @@ -863,7 +889,7 @@ static void deconfigure(struct Inst * this) { if (this->fences[i]) { - glDeleteSync(this->fences[i]); + g_gl_dynProcs.glDeleteSync(this->fences[i]); this->fences[i] = NULL; } @@ -1028,7 +1054,7 @@ static bool opengl_bufferFn(void * opaque, const void * data, size_t size) struct Inst * this = (struct Inst *)opaque; // update the buffer, this performs a DMA transfer if possible - glBufferSubData( + g_gl_dynProcs.glBufferSubData( GL_PIXEL_UNPACK_BUFFER, this->texPos, size, @@ -1042,9 +1068,9 @@ static bool opengl_bufferFn(void * opaque, const void * data, size_t size) static bool drawFrame(struct Inst * this) { - if (glIsSync(this->fences[this->texWIndex])) + if (g_gl_dynProcs.glIsSync(this->fences[this->texWIndex])) { - switch(glClientWaitSync(this->fences[this->texWIndex], 0, GL_TIMEOUT_IGNORED)) + switch(g_gl_dynProcs.glClientWaitSync(this->fences[this->texWIndex], 0, GL_TIMEOUT_IGNORED)) { case GL_ALREADY_SIGNALED: break; @@ -1062,7 +1088,7 @@ static bool drawFrame(struct Inst * this) break; } - glDeleteSync(this->fences[this->texWIndex]); + g_gl_dynProcs.glDeleteSync(this->fences[this->texWIndex]); this->fences[this->texWIndex] = NULL; this->texRIndex = this->texWIndex; @@ -1079,7 +1105,7 @@ static bool drawFrame(struct Inst * this) LG_LOCK(this->formatLock); glBindTexture(GL_TEXTURE_2D, this->frames[this->texWIndex]); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[this->texWIndex]); + g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, this->vboID[this->texWIndex]); const int bpp = this->format.bpp / 8; glPixelStorei(GL_UNPACK_ALIGNMENT , bpp); @@ -1119,7 +1145,7 @@ static bool drawFrame(struct Inst * this) } // unbind the buffer - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); const bool mipmap = this->opt.mipmap && ( (this->format.width > this->destRect.w) || @@ -1127,7 +1153,7 @@ static bool drawFrame(struct Inst * this) if (mipmap) { - glGenerateMipmap(GL_TEXTURE_2D); + g_gl_dynProcs.glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } @@ -1140,7 +1166,7 @@ static bool drawFrame(struct Inst * this) // set a fence so we don't overwrite a buffer in use this->fences[this->texWIndex] = - glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + g_gl_dynProcs.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); LG_UNLOCK(this->formatLock);