mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 23:07:18 +00:00
[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.
This commit is contained in:
parent
ad4b40fad6
commit
6370350006
@ -35,6 +35,7 @@
|
|||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
#include "common/framebuffer.h"
|
#include "common/framebuffer.h"
|
||||||
#include "common/locking.h"
|
#include "common/locking.h"
|
||||||
|
#include "gl_dynprocs.h"
|
||||||
#include "ll.h"
|
#include "ll.h"
|
||||||
#include "util.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");
|
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_TEXTURE_2D);
|
||||||
glEnable(GL_COLOR_MATERIAL);
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
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->texSize = this->format.height * this->format.pitch;
|
||||||
this->texPos = 0;
|
this->texPos = 0;
|
||||||
|
|
||||||
glGenBuffers(BUFFER_COUNT, this->vboID);
|
g_gl_dynProcs.glGenBuffers(BUFFER_COUNT, this->vboID);
|
||||||
if (check_gl_error("glGenBuffers"))
|
if (check_gl_error("glGenBuffers"))
|
||||||
{
|
{
|
||||||
LG_UNLOCK(this->formatLock);
|
LG_UNLOCK(this->formatLock);
|
||||||
@ -728,14 +754,14 @@ static enum ConfigStatus configure(struct Inst * this)
|
|||||||
|
|
||||||
memset(this->texPixels[i], 0, this->texSize);
|
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"))
|
if (check_gl_error("glBindBuffer"))
|
||||||
{
|
{
|
||||||
LG_UNLOCK(this->formatLock);
|
LG_UNLOCK(this->formatLock);
|
||||||
return CONFIG_STATUS_ERROR;
|
return CONFIG_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBufferData(
|
g_gl_dynProcs.glBufferData(
|
||||||
GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD,
|
GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD,
|
||||||
this->texSize,
|
this->texSize,
|
||||||
this->texPixels[i],
|
this->texPixels[i],
|
||||||
@ -748,20 +774,20 @@ static enum ConfigStatus configure(struct Inst * this)
|
|||||||
return CONFIG_STATUS_ERROR;
|
return CONFIG_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
|
g_gl_dynProcs.glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(int i = 0; i < BUFFER_COUNT; ++i)
|
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"))
|
if (check_gl_error("glBindBuffer"))
|
||||||
{
|
{
|
||||||
LG_UNLOCK(this->formatLock);
|
LG_UNLOCK(this->formatLock);
|
||||||
return CONFIG_STATUS_ERROR;
|
return CONFIG_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBufferData(
|
g_gl_dynProcs.glBufferData(
|
||||||
GL_PIXEL_UNPACK_BUFFER,
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
this->texSize,
|
this->texSize,
|
||||||
NULL,
|
NULL,
|
||||||
@ -773,7 +799,7 @@ static enum ConfigStatus configure(struct Inst * this)
|
|||||||
return CONFIG_STATUS_ERROR;
|
return CONFIG_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the frame textures
|
// create the frame textures
|
||||||
@ -833,7 +859,7 @@ static enum ConfigStatus configure(struct Inst * this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
this->drawStart = nanotime();
|
this->drawStart = nanotime();
|
||||||
this->configured = true;
|
this->configured = true;
|
||||||
@ -853,7 +879,7 @@ static void deconfigure(struct Inst * this)
|
|||||||
|
|
||||||
if (this->hasBuffers)
|
if (this->hasBuffers)
|
||||||
{
|
{
|
||||||
glDeleteBuffers(BUFFER_COUNT, this->vboID);
|
g_gl_dynProcs.glDeleteBuffers(BUFFER_COUNT, this->vboID);
|
||||||
this->hasBuffers = false;
|
this->hasBuffers = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,7 +889,7 @@ static void deconfigure(struct Inst * this)
|
|||||||
{
|
{
|
||||||
if (this->fences[i])
|
if (this->fences[i])
|
||||||
{
|
{
|
||||||
glDeleteSync(this->fences[i]);
|
g_gl_dynProcs.glDeleteSync(this->fences[i]);
|
||||||
this->fences[i] = NULL;
|
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;
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
// update the buffer, this performs a DMA transfer if possible
|
// update the buffer, this performs a DMA transfer if possible
|
||||||
glBufferSubData(
|
g_gl_dynProcs.glBufferSubData(
|
||||||
GL_PIXEL_UNPACK_BUFFER,
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
this->texPos,
|
this->texPos,
|
||||||
size,
|
size,
|
||||||
@ -1042,9 +1068,9 @@ static bool opengl_bufferFn(void * opaque, const void * data, size_t size)
|
|||||||
|
|
||||||
static bool drawFrame(struct Inst * this)
|
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:
|
case GL_ALREADY_SIGNALED:
|
||||||
break;
|
break;
|
||||||
@ -1062,7 +1088,7 @@ static bool drawFrame(struct Inst * this)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteSync(this->fences[this->texWIndex]);
|
g_gl_dynProcs.glDeleteSync(this->fences[this->texWIndex]);
|
||||||
this->fences[this->texWIndex] = NULL;
|
this->fences[this->texWIndex] = NULL;
|
||||||
|
|
||||||
this->texRIndex = this->texWIndex;
|
this->texRIndex = this->texWIndex;
|
||||||
@ -1079,7 +1105,7 @@ static bool drawFrame(struct Inst * this)
|
|||||||
|
|
||||||
LG_LOCK(this->formatLock);
|
LG_LOCK(this->formatLock);
|
||||||
glBindTexture(GL_TEXTURE_2D, this->frames[this->texWIndex]);
|
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;
|
const int bpp = this->format.bpp / 8;
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT , bpp);
|
glPixelStorei(GL_UNPACK_ALIGNMENT , bpp);
|
||||||
@ -1119,7 +1145,7 @@ static bool drawFrame(struct Inst * this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unbind the buffer
|
// unbind the buffer
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
const bool mipmap = this->opt.mipmap && (
|
const bool mipmap = this->opt.mipmap && (
|
||||||
(this->format.width > this->destRect.w) ||
|
(this->format.width > this->destRect.w) ||
|
||||||
@ -1127,7 +1153,7 @@ static bool drawFrame(struct Inst * this)
|
|||||||
|
|
||||||
if (mipmap)
|
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_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_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
|
// set a fence so we don't overwrite a buffer in use
|
||||||
this->fences[this->texWIndex] =
|
this->fences[this->texWIndex] =
|
||||||
glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
g_gl_dynProcs.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
LG_UNLOCK(this->formatLock);
|
LG_UNLOCK(this->formatLock);
|
||||||
|
Loading…
Reference in New Issue
Block a user