diff --git a/projects/msvc/GLideN64.vcxproj b/projects/msvc/GLideN64.vcxproj index 4daf237df..9e6a9e2a6 100644 --- a/projects/msvc/GLideN64.vcxproj +++ b/projects/msvc/GLideN64.vcxproj @@ -260,9 +260,16 @@ copy /Y "$(OutDir)$(TargetName).*" "$(Mupen64PluginsDir_x64)") + + + + true + + true + true @@ -399,6 +406,15 @@ copy /Y "$(OutDir)$(TargetName).*" "$(Mupen64PluginsDir_x64)") + + + + + + + + true + diff --git a/projects/msvc/GLideN64.vcxproj.filters b/projects/msvc/GLideN64.vcxproj.filters index facba9173..123b08092 100644 --- a/projects/msvc/GLideN64.vcxproj.filters +++ b/projects/msvc/GLideN64.vcxproj.filters @@ -69,6 +69,12 @@ {77259791-9942-4601-a63f-5a0468e69e49} + + {09919f83-2933-4b48-a4c7-f7bf6e790304} + + + {32e9be50-cb55-445a-9562-bbe05085bbe1} + @@ -260,6 +266,12 @@ Source Files\Graphics\OpenGL\windows + + Source Files\Graphics\OpenGL\windows + + + Source Files\Graphics\OpenGL\windows + Source Files\Graphics\OpenGL\mupen64plus @@ -392,6 +404,18 @@ Source Files\Graphics\OpenGL\GLSL + + Source Files\Graphics\OpenGL\ThreadedOpenGL + + + Source Files\Graphics\OpenGL\ThreadedOpenGL + + + Source Files\Graphics\OpenGL\ThreadedOpenGL + + + Source Files\Graphics\OpenGL\ThreadedOpenGL + @@ -631,6 +655,9 @@ Header Files\Graphics\OpenGL + + Header Files\Graphics\OpenGL\windows + Header Files @@ -724,5 +751,23 @@ Header Files\Graphics\OpenGL\GLSL + + Header Files\Graphics\OpenGL\ThreadedOpenGL + + + Header Files\Graphics\OpenGL\ThreadedOpenGL + + + Header Files\Graphics\OpenGL\ThreadedOpenGL + + + Header Files\Graphics\OpenGL\ThreadedOpenGL + + + Header Files\Graphics\OpenGL\ThreadedOpenGL + + + Header Files\Graphics\OpenGL\ThreadedOpenGL + \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f634b64fb..b01db67b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,10 @@ set(GLideN64_SOURCES Graphics/CombinerProgram.cpp Graphics/ObjectHandle.cpp Graphics/OpenGLContext/GLFunctions.cpp + Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.cpp + Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.cpp + Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp + Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.cpp Graphics/OpenGLContext/opengl_Attributes.cpp Graphics/OpenGLContext/opengl_BufferedDrawer.cpp Graphics/OpenGLContext/opengl_BufferManipulationObjectFactory.cpp diff --git a/src/Config.cpp b/src/Config.cpp index 880d6e6b2..d4a3eb04e 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -25,6 +25,7 @@ void Config::resetToDefaults() video.fxaa = 0; video.multisampling = 0; video.verticalSync = 0; + video.threadedVideo = 0; texture.maxAnisotropy = 0; texture.bilinearMode = BILINEAR_STANDARD; diff --git a/src/Config.h b/src/Config.h index 6d0db2aac..7e04d912f 100644 --- a/src/Config.h +++ b/src/Config.h @@ -28,6 +28,7 @@ struct Config u32 fxaa; u32 multisampling; u32 verticalSync; + u32 threadedVideo; } video; struct diff --git a/src/GLideNUI/ConfigDialog.cpp b/src/GLideNUI/ConfigDialog.cpp index 66ff91cd0..5a25193a3 100644 --- a/src/GLideNUI/ConfigDialog.cpp +++ b/src/GLideNUI/ConfigDialog.cpp @@ -117,6 +117,7 @@ void ConfigDialog::_init() ui->aliasingLabelVal->setText(QString::number(config.video.multisampling)); ui->anisotropicSlider->setValue(config.texture.maxAnisotropy); ui->vSyncCheckBox->setChecked(config.video.verticalSync != 0); + ui->vThreadedVideoCheckBox->setChecked(config.video.threadedVideo != 0); switch (config.texture.bilinearMode) { case BILINEAR_3POINT: @@ -426,6 +427,8 @@ void ConfigDialog::accept() config.video.verticalSync = ui->vSyncCheckBox->isChecked() ? 1 : 0; + config.video.threadedVideo = ui->vThreadedVideoCheckBox->isChecked() ? 1 : 0; + // Emulation settings config.generalEmulation.enableLOD = ui->emulateLodCheckBox->isChecked() ? 1 : 0; config.generalEmulation.enableNoise = ui->emulateNoiseCheckBox->isChecked() ? 1 : 0; diff --git a/src/GLideNUI/Settings.cpp b/src/GLideNUI/Settings.cpp index 717876276..dd814d2fe 100644 --- a/src/GLideNUI/Settings.cpp +++ b/src/GLideNUI/Settings.cpp @@ -29,6 +29,7 @@ void _loadSettings(QSettings & settings) config.video.multisampling = settings.value("multisampling", config.video.multisampling).toInt(); config.video.fxaa= settings.value("fxaa", config.video.fxaa).toInt(); config.video.verticalSync = settings.value("verticalSync", config.video.verticalSync).toInt(); + config.video.threadedVideo = settings.value("threadedVideo", config.video.threadedVideo).toInt(); settings.endGroup(); settings.beginGroup("texture"); @@ -197,6 +198,7 @@ void writeSettings(const QString & _strIniFolder) settings.setValue("multisampling", config.video.multisampling); settings.setValue("fxaa", config.video.fxaa); settings.setValue("verticalSync", config.video.verticalSync); + settings.setValue("threadedVideo", config.video.threadedVideo); settings.endGroup(); settings.beginGroup("texture"); diff --git a/src/GLideNUI/configDialog.ui b/src/GLideNUI/configDialog.ui index 4f5b73bca..2faa73105 100644 --- a/src/GLideNUI/configDialog.ui +++ b/src/GLideNUI/configDialog.ui @@ -160,6 +160,16 @@ + + + + <html><head/><body><p>Threaded video can improve performance with poor OpenGL drivers at the cost of very marginal input lag, usually less than half a frame</p><p>[Recommended: <span style=" font-style:italic;">Usually off, unless there are performance issues.</span>]</p></body></html> + + + Enable threaded video + + + diff --git a/src/Graphics/OpenGLContext/GLFunctions.cpp b/src/Graphics/OpenGLContext/GLFunctions.cpp index 9b8dab4b3..e470884e8 100644 --- a/src/Graphics/OpenGLContext/GLFunctions.cpp +++ b/src/Graphics/OpenGLContext/GLFunctions.cpp @@ -3,16 +3,18 @@ #ifdef OS_WINDOWS #define glGetProcAddress wglGetProcAddress -#define GL_GET_PROC_ADR(proc_type, proc_name) g_##proc_name = (proc_type) glGetProcAddress(#proc_name) +#define GL_GET_PROC_ADR(proc_type, proc_name) ptr##proc_name = (proc_type) glGetProcAddress("gl"#proc_name) +#define ASSIGN_PROC_ADR(proc_type, proc_name) ptr##proc_name = gl##proc_name #elif defined(VERO4K) || defined(ODROID) || defined(VC) -#define GL_GET_PROC_ADR(proc_type, proc_name) g_##proc_name = (proc_type) dlsym(gles2so, #proc_name); +#define GL_GET_PROC_ADR(proc_type, proc_name) ptr##proc_name = (proc_type) dlsym(gles2so, "gl"#proc_name); #elif defined(EGL) #define glGetProcAddress eglGetProcAddress -#define GL_GET_PROC_ADR(proc_type, proc_name) g_##proc_name = (proc_type) glGetProcAddress(#proc_name) +#define GL_GET_PROC_ADR(proc_type, proc_name) ptr##proc_name = (proc_type) glGetProcAddress("gl"#proc_name) +#define GL_GET_PROC_ADR_EGL(proc_type, proc_name) ptr##proc_name = (proc_type) glGetProcAddress("egl"#proc_name) #elif defined(OS_LINUX) @@ -58,145 +60,140 @@ static void* IOSGLGetProcAddress (const char *name) #endif //GL Fucntions - -#ifdef OS_WINDOWS -PFNGLACTIVETEXTUREPROC g_glActiveTexture; -PFNGLBLENDCOLORPROC g_glBlendColor; -#elif defined(EGL) || defined(OS_IOS) -PFNGLBLENDFUNCPROC g_glBlendFunc; -PFNGLPIXELSTOREIPROC g_glPixelStorei; -PFNGLCLEARCOLORPROC g_glClearColor; -PFNGLCULLFACEPROC g_glCullFace; -PFNGLDEPTHFUNCPROC g_glDepthFunc; -PFNGLDEPTHMASKPROC g_glDepthMask; -PFNGLDISABLEPROC g_glDisable; -PFNGLENABLEPROC g_glEnable; -PFNGLPOLYGONOFFSETPROC g_glPolygonOffset; -PFNGLSCISSORPROC g_glScissor; -PFNGLVIEWPORTPROC g_glViewport; -PFNGLBINDTEXTUREPROC g_glBindTexture; -PFNGLTEXIMAGE2DPROC g_glTexImage2D; -PFNGLTEXPARAMETERIPROC g_glTexParameteri; -PFNGLGETINTEGERVPROC g_glGetIntegerv; -PFNGLGETSTRINGPROC g_glGetString; -PFNGLREADPIXELSPROC g_glReadPixels; -PFNGLTEXSUBIMAGE2DPROC g_glTexSubImage2D; -PFNGLDRAWARRAYSPROC g_glDrawArrays; -PFNGLGETERRORPROC g_glGetError; -PFNGLDRAWELEMENTSPROC g_glDrawElements; -PFNGLLINEWIDTHPROC g_glLineWidth; -PFNGLCLEARPROC g_glClear; -PFNGLGETFLOATVPROC g_glGetFloatv; -PFNGLDELETETEXTURESPROC g_glDeleteTextures; -PFNGLGENTEXTURESPROC g_glGenTextures; -PFNGLTEXPARAMETERFPROC g_glTexParameterf; -PFNGLACTIVETEXTUREPROC g_glActiveTexture; -PFNGLBLENDCOLORPROC g_glBlendColor; -PFNGLREADBUFFERPROC g_glReadBuffer; -PFNGLFINISHPROC g_glFinish; +PFNGLBLENDFUNCPROC ptrBlendFunc; +PFNGLPIXELSTOREIPROC ptrPixelStorei; +PFNGLCLEARCOLORPROC ptrClearColor; +PFNGLCULLFACEPROC ptrCullFace; +PFNGLDEPTHFUNCPROC ptrDepthFunc; +PFNGLDEPTHMASKPROC ptrDepthMask; +PFNGLDISABLEPROC ptrDisable; +PFNGLENABLEPROC ptrEnable; +PFNGLPOLYGONOFFSETPROC ptrPolygonOffset; +PFNGLSCISSORPROC ptrScissor; +PFNGLVIEWPORTPROC ptrViewport; +PFNGLBINDTEXTUREPROC ptrBindTexture; +PFNGLTEXIMAGE2DPROC ptrTexImage2D; +PFNGLTEXPARAMETERIPROC ptrTexParameteri; +PFNGLGETINTEGERVPROC ptrGetIntegerv; +PFNGLGETSTRINGPROC ptrGetString; +PFNGLREADPIXELSPROC ptrReadPixels; +PFNGLTEXSUBIMAGE2DPROC ptrTexSubImage2D; +PFNGLDRAWARRAYSPROC ptrDrawArrays; +PFNGLGETERRORPROC ptrGetError; +PFNGLDRAWELEMENTSPROC ptrDrawElements; +PFNGLLINEWIDTHPROC ptrLineWidth; +PFNGLCLEARPROC ptrClear; +PFNGLGETFLOATVPROC ptrGetFloatv; +PFNGLDELETETEXTURESPROC ptrDeleteTextures; +PFNGLGENTEXTURESPROC ptrGenTextures; +PFNGLTEXPARAMETERFPROC ptrTexParameterf; +PFNGLACTIVETEXTUREPROC ptrActiveTexture; +PFNGLBLENDCOLORPROC ptrBlendColor; +PFNGLREADBUFFERPROC ptrReadBuffer; +PFNGLFINISHPROC ptrFinish; #if defined(OS_ANDROID) -PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC g_eglGetNativeClientBufferANDROID; -#endif +PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC ptrGetNativeClientBufferANDROID; #endif -PFNGLCREATESHADERPROC g_glCreateShader; -PFNGLCOMPILESHADERPROC g_glCompileShader; -PFNGLSHADERSOURCEPROC g_glShaderSource; -PFNGLCREATEPROGRAMPROC g_glCreateProgram; -PFNGLATTACHSHADERPROC g_glAttachShader; -PFNGLLINKPROGRAMPROC g_glLinkProgram; -PFNGLUSEPROGRAMPROC g_glUseProgram; -PFNGLGETUNIFORMLOCATIONPROC g_glGetUniformLocation; -PFNGLUNIFORM1IPROC g_glUniform1i; -PFNGLUNIFORM1FPROC g_glUniform1f; -PFNGLUNIFORM2FPROC g_glUniform2f; -PFNGLUNIFORM2IPROC g_glUniform2i; -PFNGLUNIFORM4IPROC g_glUniform4i; -PFNGLUNIFORM4FPROC g_glUniform4f; -PFNGLUNIFORM3FVPROC g_glUniform3fv; -PFNGLUNIFORM4FVPROC g_glUniform4fv; -PFNGLDETACHSHADERPROC g_glDetachShader; -PFNGLDELETESHADERPROC g_glDeleteShader; -PFNGLDELETEPROGRAMPROC g_glDeleteProgram; -PFNGLGETPROGRAMINFOLOGPROC g_glGetProgramInfoLog; -PFNGLGETSHADERINFOLOGPROC g_glGetShaderInfoLog; -PFNGLGETSHADERIVPROC g_glGetShaderiv; -PFNGLGETPROGRAMIVPROC g_glGetProgramiv; - -PFNGLENABLEVERTEXATTRIBARRAYPROC g_glEnableVertexAttribArray; -PFNGLDISABLEVERTEXATTRIBARRAYPROC g_glDisableVertexAttribArray; -PFNGLVERTEXATTRIBPOINTERPROC g_glVertexAttribPointer; -PFNGLBINDATTRIBLOCATIONPROC g_glBindAttribLocation; -PFNGLVERTEXATTRIB1FPROC g_glVertexAttrib1f; -PFNGLVERTEXATTRIB4FPROC g_glVertexAttrib4f; -PFNGLVERTEXATTRIB4FVPROC g_glVertexAttrib4fv; + +PFNGLCREATESHADERPROC ptrCreateShader; +PFNGLCOMPILESHADERPROC ptrCompileShader; +PFNGLSHADERSOURCEPROC ptrShaderSource; +PFNGLCREATEPROGRAMPROC ptrCreateProgram; +PFNGLATTACHSHADERPROC ptrAttachShader; +PFNGLLINKPROGRAMPROC ptrLinkProgram; +PFNGLUSEPROGRAMPROC ptrUseProgram; +PFNGLGETUNIFORMLOCATIONPROC ptrGetUniformLocation; +PFNGLUNIFORM1IPROC ptrUniform1i; +PFNGLUNIFORM1FPROC ptrUniform1f; +PFNGLUNIFORM2FPROC ptrUniform2f; +PFNGLUNIFORM2IPROC ptrUniform2i; +PFNGLUNIFORM4IPROC ptrUniform4i; +PFNGLUNIFORM4FPROC ptrUniform4f; +PFNGLUNIFORM3FVPROC ptrUniform3fv; +PFNGLUNIFORM4FVPROC ptrUniform4fv; +PFNGLDETACHSHADERPROC ptrDetachShader; +PFNGLDELETESHADERPROC ptrDeleteShader; +PFNGLDELETEPROGRAMPROC ptrDeleteProgram; +PFNGLGETPROGRAMINFOLOGPROC ptrGetProgramInfoLog; +PFNGLGETSHADERINFOLOGPROC ptrGetShaderInfoLog; +PFNGLGETSHADERIVPROC ptrGetShaderiv; +PFNGLGETPROGRAMIVPROC ptrGetProgramiv; + +PFNGLENABLEVERTEXATTRIBARRAYPROC ptrEnableVertexAttribArray; +PFNGLDISABLEVERTEXATTRIBARRAYPROC ptrDisableVertexAttribArray; +PFNGLVERTEXATTRIBPOINTERPROC ptrVertexAttribPointer; +PFNGLBINDATTRIBLOCATIONPROC ptrBindAttribLocation; +PFNGLVERTEXATTRIB1FPROC ptrVertexAttrib1f; +PFNGLVERTEXATTRIB4FPROC ptrVertexAttrib4f; +PFNGLVERTEXATTRIB4FVPROC ptrVertexAttrib4fv; // multitexture functions -PFNGLDEPTHRANGEFPROC g_glDepthRangef; -PFNGLCLEARDEPTHFPROC g_glClearDepthf; - -PFNGLDRAWBUFFERSPROC g_glDrawBuffers; -PFNGLBINDFRAMEBUFFERPROC g_glBindFramebuffer; -PFNGLDELETEFRAMEBUFFERSPROC g_glDeleteFramebuffers; -PFNGLGENFRAMEBUFFERSPROC g_glGenFramebuffers; -PFNGLFRAMEBUFFERTEXTURE2DPROC g_glFramebufferTexture2D; -PFNGLTEXIMAGE2DMULTISAMPLEPROC g_glTexImage2DMultisample; -PFNGLTEXSTORAGE2DMULTISAMPLEPROC g_glTexStorage2DMultisample; -PFNGLGENRENDERBUFFERSPROC g_glGenRenderbuffers; -PFNGLBINDRENDERBUFFERPROC g_glBindRenderbuffer; -PFNGLRENDERBUFFERSTORAGEPROC g_glRenderbufferStorage; -PFNGLFRAMEBUFFERRENDERBUFFERPROC g_glFramebufferRenderbuffer; -PFNGLDELETERENDERBUFFERSPROC g_glDeleteRenderbuffers; -PFNGLCHECKFRAMEBUFFERSTATUSPROC g_glCheckFramebufferStatus; -PFNGLBLITFRAMEBUFFERPROC g_glBlitFramebuffer; -PFNGLGENVERTEXARRAYSPROC g_glGenVertexArrays; -PFNGLBINDVERTEXARRAYPROC g_glBindVertexArray; -PFNGLDELETEVERTEXARRAYSPROC g_glDeleteVertexArrays; -PFNGLGENBUFFERSPROC g_glGenBuffers; -PFNGLBINDBUFFERPROC g_glBindBuffer; -PFNGLBUFFERDATAPROC g_glBufferData; -PFNGLMAPBUFFERPROC g_glMapBuffer; -PFNGLMAPBUFFERRANGEPROC g_glMapBufferRange; -PFNGLUNMAPBUFFERPROC g_glUnmapBuffer; -PFNGLDELETEBUFFERSPROC g_glDeleteBuffers; -PFNGLBINDIMAGETEXTUREPROC g_glBindImageTexture; -PFNGLMEMORYBARRIERPROC g_glMemoryBarrier; -PFNGLGETSTRINGIPROC g_glGetStringi; -PFNGLINVALIDATEFRAMEBUFFERPROC g_glInvalidateFramebuffer; -PFNGLBUFFERSTORAGEPROC g_glBufferStorage; -PFNGLFENCESYNCPROC g_glFenceSync; -PFNGLCLIENTWAITSYNCPROC g_glClientWaitSync; -PFNGLDELETESYNCPROC g_glDeleteSync; - -PFNGLGETUNIFORMBLOCKINDEXPROC g_glGetUniformBlockIndex; -PFNGLUNIFORMBLOCKBINDINGPROC g_glUniformBlockBinding; -PFNGLGETACTIVEUNIFORMBLOCKIVPROC g_glGetActiveUniformBlockiv; -PFNGLGETUNIFORMINDICESPROC g_glGetUniformIndices; -PFNGLGETACTIVEUNIFORMSIVPROC g_glGetActiveUniformsiv; -PFNGLBINDBUFFERBASEPROC g_glBindBufferBase; -PFNGLBUFFERSUBDATAPROC g_glBufferSubData; - -PFNGLGETPROGRAMBINARYPROC g_glGetProgramBinary; -PFNGLPROGRAMBINARYPROC g_glProgramBinary; -PFNGLPROGRAMPARAMETERIPROC g_glProgramParameteri; - -PFNGLTEXSTORAGE2DPROC g_glTexStorage2D; -PFNGLTEXTURESTORAGE2DPROC g_glTextureStorage2D; -PFNGLTEXTURESUBIMAGE2DPROC g_glTextureSubImage2D; -PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC g_glTextureStorage2DMultisample; -PFNGLTEXTUREPARAMETERIPROC g_glTextureParameteri; -PFNGLTEXTUREPARAMETERFPROC g_glTextureParameterf; -PFNGLCREATETEXTURESPROC g_glCreateTextures; -PFNGLCREATEBUFFERSPROC g_glCreateBuffers; -PFNGLCREATEFRAMEBUFFERSPROC g_glCreateFramebuffers; -PFNGLNAMEDFRAMEBUFFERTEXTUREPROC g_glNamedFramebufferTexture; -PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC g_glDrawRangeElementsBaseVertex; -PFNGLFLUSHMAPPEDBUFFERRANGEPROC g_glFlushMappedBufferRange; -PFNGLTEXTUREBARRIERPROC g_glTextureBarrier; -PFNGLTEXTUREBARRIERNVPROC g_glTextureBarrierNV; -PFNGLCLEARBUFFERFVPROC g_glClearBufferfv; -PFNGLENABLEIPROC g_glEnablei; -PFNGLDISABLEIPROC g_glDisablei; -PFNGLEGLIMAGETARGETTEXTURE2DOESPROC g_glEGLImageTargetTexture2DOES; +PFNGLDEPTHRANGEFPROC ptrDepthRangef; +PFNGLCLEARDEPTHFPROC ptrClearDepthf; + +PFNGLDRAWBUFFERSPROC ptrDrawBuffers; +PFNGLBINDFRAMEBUFFERPROC ptrBindFramebuffer; +PFNGLDELETEFRAMEBUFFERSPROC ptrDeleteFramebuffers; +PFNGLGENFRAMEBUFFERSPROC ptrGenFramebuffers; +PFNGLFRAMEBUFFERTEXTURE2DPROC ptrFramebufferTexture2D; +PFNGLTEXIMAGE2DMULTISAMPLEPROC ptrTexImage2DMultisample; +PFNGLTEXSTORAGE2DMULTISAMPLEPROC ptrTexStorage2DMultisample; +PFNGLGENRENDERBUFFERSPROC ptrGenRenderbuffers; +PFNGLBINDRENDERBUFFERPROC ptrBindRenderbuffer; +PFNGLRENDERBUFFERSTORAGEPROC ptrRenderbufferStorage; +PFNGLFRAMEBUFFERRENDERBUFFERPROC ptrFramebufferRenderbuffer; +PFNGLDELETERENDERBUFFERSPROC ptrDeleteRenderbuffers; +PFNGLCHECKFRAMEBUFFERSTATUSPROC ptrCheckFramebufferStatus; +PFNGLBLITFRAMEBUFFERPROC ptrBlitFramebuffer; +PFNGLGENVERTEXARRAYSPROC ptrGenVertexArrays; +PFNGLBINDVERTEXARRAYPROC ptrBindVertexArray; +PFNGLDELETEVERTEXARRAYSPROC ptrDeleteVertexArrays; +PFNGLGENBUFFERSPROC ptrGenBuffers; +PFNGLBINDBUFFERPROC ptrBindBuffer; +PFNGLBUFFERDATAPROC ptrBufferData; +PFNGLMAPBUFFERPROC ptrMapBuffer; +PFNGLMAPBUFFERRANGEPROC ptrMapBufferRange; +PFNGLUNMAPBUFFERPROC ptrUnmapBuffer; +PFNGLDELETEBUFFERSPROC ptrDeleteBuffers; +PFNGLBINDIMAGETEXTUREPROC ptrBindImageTexture; +PFNGLMEMORYBARRIERPROC ptrMemoryBarrier; +PFNGLGETSTRINGIPROC ptrGetStringi; +PFNGLINVALIDATEFRAMEBUFFERPROC ptrInvalidateFramebuffer; +PFNGLBUFFERSTORAGEPROC ptrBufferStorage; +PFNGLFENCESYNCPROC ptrFenceSync; +PFNGLCLIENTWAITSYNCPROC ptrClientWaitSync; +PFNGLDELETESYNCPROC ptrDeleteSync; + +PFNGLGETUNIFORMBLOCKINDEXPROC ptrGetUniformBlockIndex; +PFNGLUNIFORMBLOCKBINDINGPROC ptrUniformBlockBinding; +PFNGLGETACTIVEUNIFORMBLOCKIVPROC ptrGetActiveUniformBlockiv; +PFNGLGETUNIFORMINDICESPROC ptrGetUniformIndices; +PFNGLGETACTIVEUNIFORMSIVPROC ptrGetActiveUniformsiv; +PFNGLBINDBUFFERBASEPROC ptrBindBufferBase; +PFNGLBUFFERSUBDATAPROC ptrBufferSubData; + +PFNGLGETPROGRAMBINARYPROC ptrGetProgramBinary; +PFNGLPROGRAMBINARYPROC ptrProgramBinary; +PFNGLPROGRAMPARAMETERIPROC ptrProgramParameteri; + +PFNGLTEXSTORAGE2DPROC ptrTexStorage2D; +PFNGLTEXTURESTORAGE2DPROC ptrTextureStorage2D; +PFNGLTEXTURESUBIMAGE2DPROC ptrTextureSubImage2D; +PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC ptrTextureStorage2DMultisample; +PFNGLTEXTUREPARAMETERIPROC ptrTextureParameteri; +PFNGLTEXTUREPARAMETERFPROC ptrTextureParameterf; +PFNGLCREATETEXTURESPROC ptrCreateTextures; +PFNGLCREATEBUFFERSPROC ptrCreateBuffers; +PFNGLCREATEFRAMEBUFFERSPROC ptrCreateFramebuffers; +PFNGLNAMEDFRAMEBUFFERTEXTUREPROC ptrNamedFramebufferTexture; +PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC ptrDrawRangeElementsBaseVertex; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC ptrFlushMappedBufferRange; +PFNGLTEXTUREBARRIERPROC ptrTextureBarrier; +PFNGLTEXTUREBARRIERNVPROC ptrTextureBarrierNV; +PFNGLCLEARBUFFERFVPROC ptrClearBufferfv; +PFNGLENABLEIPROC ptrEnablei; +PFNGLDISABLEIPROC ptrDisablei; +PFNGLEGLIMAGETARGETTEXTURE2DOESPROC ptrEGLImageTargetTexture2DOES; void initGLFunctions() { @@ -207,143 +204,178 @@ void initGLFunctions() #elif defined(VERO4K) void *gles2so = dlopen("/opt/vero3/lib/libGLESv2.so", RTLD_NOW); #endif + +#if defined(EGL) || defined(OS_IOS) + GL_GET_PROC_ADR(PFNGLBLENDFUNCPROC, BlendFunc); + GL_GET_PROC_ADR(PFNGLPIXELSTOREIPROC, PixelStorei); + GL_GET_PROC_ADR(PFNGLCLEARCOLORPROC, ClearColor); + GL_GET_PROC_ADR(PFNGLCULLFACEPROC, CullFace); + GL_GET_PROC_ADR(PFNGLDEPTHFUNCPROC, DepthFunc); + GL_GET_PROC_ADR(PFNGLDEPTHMASKPROC, DepthMask); + GL_GET_PROC_ADR(PFNGLDISABLEPROC, Disable); + GL_GET_PROC_ADR(PFNGLENABLEPROC, Enable); + GL_GET_PROC_ADR(PFNGLPOLYGONOFFSETPROC, PolygonOffset); + GL_GET_PROC_ADR(PFNGLSCISSORPROC, Scissor); + GL_GET_PROC_ADR(PFNGLVIEWPORTPROC, Viewport); + GL_GET_PROC_ADR(PFNGLBINDTEXTUREPROC, BindTexture); + GL_GET_PROC_ADR(PFNGLTEXIMAGE2DPROC, TexImage2D); + GL_GET_PROC_ADR(PFNGLTEXPARAMETERIPROC, TexParameteri); + GL_GET_PROC_ADR(PFNGLGETINTEGERVPROC, GetIntegerv); + GL_GET_PROC_ADR(PFNGLGETSTRINGPROC, GetString); + GL_GET_PROC_ADR(PFNGLREADPIXELSPROC, ReadPixels); + GL_GET_PROC_ADR(PFNGLTEXSUBIMAGE2DPROC, TexSubImage2D); + GL_GET_PROC_ADR(PFNGLDRAWARRAYSPROC, DrawArrays); + GL_GET_PROC_ADR(PFNGLGETERRORPROC, GetError); + GL_GET_PROC_ADR(PFNGLDRAWELEMENTSPROC, DrawElements); + GL_GET_PROC_ADR(PFNGLLINEWIDTHPROC, LineWidth); + GL_GET_PROC_ADR(PFNGLCLEARPROC, Clear); + GL_GET_PROC_ADR(PFNGLGETFLOATVPROC, GetFloatv); + GL_GET_PROC_ADR(PFNGLDELETETEXTURESPROC, DeleteTextures); + GL_GET_PROC_ADR(PFNGLGENTEXTURESPROC, GenTextures); + GL_GET_PROC_ADR(PFNGLTEXPARAMETERFPROC, TexParameterf); + GL_GET_PROC_ADR(PFNGLACTIVETEXTUREPROC, ActiveTexture); + GL_GET_PROC_ADR(PFNGLBLENDCOLORPROC, BlendColor); + GL_GET_PROC_ADR(PFNGLREADBUFFERPROC, ReadBuffer); + GL_GET_PROC_ADR(PFNGLFINISHPROC, Finish); +#if defined(OS_ANDROID) + GL_GET_PROC_ADR_EGL(PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC, GetNativeClientBufferANDROID); +#endif +#else #ifdef OS_WINDOWS - GL_GET_PROC_ADR(PFNGLACTIVETEXTUREPROC, glActiveTexture); - GL_GET_PROC_ADR(PFNGLBLENDCOLORPROC, glBlendColor); -#elif defined(EGL) || defined(OS_IOS) - GL_GET_PROC_ADR(PFNGLBLENDFUNCPROC, glBlendFunc); - GL_GET_PROC_ADR(PFNGLPIXELSTOREIPROC, glPixelStorei); - GL_GET_PROC_ADR(PFNGLCLEARCOLORPROC, glClearColor); - GL_GET_PROC_ADR(PFNGLCULLFACEPROC, glCullFace); - GL_GET_PROC_ADR(PFNGLDEPTHFUNCPROC, glDepthFunc); - GL_GET_PROC_ADR(PFNGLDEPTHMASKPROC, glDepthMask); - GL_GET_PROC_ADR(PFNGLDISABLEPROC, glDisable); - GL_GET_PROC_ADR(PFNGLENABLEPROC, glEnable); - GL_GET_PROC_ADR(PFNGLPOLYGONOFFSETPROC, glPolygonOffset); - GL_GET_PROC_ADR(PFNGLSCISSORPROC, glScissor); - GL_GET_PROC_ADR(PFNGLVIEWPORTPROC, glViewport); - GL_GET_PROC_ADR(PFNGLBINDTEXTUREPROC, glBindTexture); - GL_GET_PROC_ADR(PFNGLTEXIMAGE2DPROC, glTexImage2D); - GL_GET_PROC_ADR(PFNGLTEXPARAMETERIPROC, glTexParameteri); - GL_GET_PROC_ADR(PFNGLGETINTEGERVPROC, glGetIntegerv); - GL_GET_PROC_ADR(PFNGLGETSTRINGPROC, glGetString); - GL_GET_PROC_ADR(PFNGLREADPIXELSPROC, glReadPixels); - GL_GET_PROC_ADR(PFNGLTEXSUBIMAGE2DPROC, glTexSubImage2D); - GL_GET_PROC_ADR(PFNGLDRAWARRAYSPROC, glDrawArrays); - GL_GET_PROC_ADR(PFNGLGETERRORPROC, glGetError); - GL_GET_PROC_ADR(PFNGLDRAWELEMENTSPROC, glDrawElements); - GL_GET_PROC_ADR(PFNGLLINEWIDTHPROC, glLineWidth); - GL_GET_PROC_ADR(PFNGLCLEARPROC, glClear); - GL_GET_PROC_ADR(PFNGLGETFLOATVPROC, glGetFloatv); - GL_GET_PROC_ADR(PFNGLDELETETEXTURESPROC, glDeleteTextures); - GL_GET_PROC_ADR(PFNGLGENTEXTURESPROC, glGenTextures); - GL_GET_PROC_ADR(PFNGLTEXPARAMETERFPROC, glTexParameterf); - GL_GET_PROC_ADR(PFNGLACTIVETEXTUREPROC, glActiveTexture); - GL_GET_PROC_ADR(PFNGLBLENDCOLORPROC, glBlendColor); - GL_GET_PROC_ADR(PFNGLREADBUFFERPROC, glReadBuffer); - GL_GET_PROC_ADR(PFNGLFINISHPROC, glFinish); -#ifdef OS_ANDROID - GL_GET_PROC_ADR(PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC, eglGetNativeClientBufferANDROID); + GL_GET_PROC_ADR(PFNGLACTIVETEXTUREPROC, ActiveTexture); + GL_GET_PROC_ADR(PFNGLBLENDCOLORPROC, BlendColor); +#else + ASSIGN_PROC_ADR(PFNGLACTIVETEXTUREPROC, ActiveTexture) + ASSIGN_PROC_ADR(PFNGLBLENDCOLORPROC, BlendColor); #endif + ASSIGN_PROC_ADR(PFNGLBLENDFUNCPROC, BlendFunc); + ASSIGN_PROC_ADR(PFNGLPIXELSTOREIPROC, PixelStorei); + ASSIGN_PROC_ADR(PFNGLCLEARCOLORPROC, ClearColor); + ASSIGN_PROC_ADR(PFNGLCULLFACEPROC, CullFace); + ASSIGN_PROC_ADR(PFNGLDEPTHFUNCPROC, DepthFunc); + ASSIGN_PROC_ADR(PFNGLDEPTHMASKPROC, DepthMask); + ASSIGN_PROC_ADR(PFNGLDISABLEPROC, Disable); + ASSIGN_PROC_ADR(PFNGLENABLEPROC, Enable); + ASSIGN_PROC_ADR(PFNGLPOLYGONOFFSETPROC, PolygonOffset); + ASSIGN_PROC_ADR(PFNGLSCISSORPROC, Scissor); + ASSIGN_PROC_ADR(PFNGLVIEWPORTPROC, Viewport); + ASSIGN_PROC_ADR(PFNGLBINDTEXTUREPROC, BindTexture); + ASSIGN_PROC_ADR(PFNGLTEXIMAGE2DPROC, TexImage2D); + ASSIGN_PROC_ADR(PFNGLTEXPARAMETERIPROC, TexParameteri); + ASSIGN_PROC_ADR(PFNGLGETINTEGERVPROC, GetIntegerv); + ASSIGN_PROC_ADR(PFNGLGETSTRINGPROC, GetString); + ASSIGN_PROC_ADR(PFNGLREADPIXELSPROC, ReadPixels); + ASSIGN_PROC_ADR(PFNGLTEXSUBIMAGE2DPROC, TexSubImage2D); + ASSIGN_PROC_ADR(PFNGLDRAWARRAYSPROC, DrawArrays); + ASSIGN_PROC_ADR(PFNGLGETERRORPROC, GetError); + ASSIGN_PROC_ADR(PFNGLDRAWELEMENTSPROC, DrawElements); + ASSIGN_PROC_ADR(PFNGLLINEWIDTHPROC, LineWidth); + ASSIGN_PROC_ADR(PFNGLCLEARPROC, Clear); + ASSIGN_PROC_ADR(PFNGLGETFLOATVPROC, GetFloatv); + ASSIGN_PROC_ADR(PFNGLDELETETEXTURESPROC, DeleteTextures); + ASSIGN_PROC_ADR(PFNGLGENTEXTURESPROC, GenTextures); + ASSIGN_PROC_ADR(PFNGLTEXPARAMETERFPROC, TexParameterf); + ASSIGN_PROC_ADR(PFNGLREADBUFFERPROC, ReadBuffer); + ASSIGN_PROC_ADR(PFNGLFINISHPROC, Finish); #endif - GL_GET_PROC_ADR(PFNGLCREATESHADERPROC, glCreateShader); - GL_GET_PROC_ADR(PFNGLCOMPILESHADERPROC, glCompileShader); - GL_GET_PROC_ADR(PFNGLSHADERSOURCEPROC, glShaderSource); - GL_GET_PROC_ADR(PFNGLCREATEPROGRAMPROC, glCreateProgram); - GL_GET_PROC_ADR(PFNGLATTACHSHADERPROC, glAttachShader); - GL_GET_PROC_ADR(PFNGLLINKPROGRAMPROC, glLinkProgram); - GL_GET_PROC_ADR(PFNGLUSEPROGRAMPROC, glUseProgram); - GL_GET_PROC_ADR(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); - GL_GET_PROC_ADR(PFNGLUNIFORM1IPROC, glUniform1i); - GL_GET_PROC_ADR(PFNGLUNIFORM1FPROC, glUniform1f); - GL_GET_PROC_ADR(PFNGLUNIFORM2FPROC, glUniform2f); - GL_GET_PROC_ADR(PFNGLUNIFORM2IPROC, glUniform2i); - GL_GET_PROC_ADR(PFNGLUNIFORM4IPROC, glUniform4i); - GL_GET_PROC_ADR(PFNGLUNIFORM4FPROC, glUniform4f); - GL_GET_PROC_ADR(PFNGLUNIFORM3FVPROC, glUniform3fv); - GL_GET_PROC_ADR(PFNGLUNIFORM4FVPROC, glUniform4fv); - GL_GET_PROC_ADR(PFNGLDETACHSHADERPROC, glDetachShader); - GL_GET_PROC_ADR(PFNGLDELETESHADERPROC, glDeleteShader); - GL_GET_PROC_ADR(PFNGLDELETEPROGRAMPROC, glDeleteProgram); - GL_GET_PROC_ADR(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); - GL_GET_PROC_ADR(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); - GL_GET_PROC_ADR(PFNGLGETSHADERIVPROC, glGetShaderiv); - GL_GET_PROC_ADR(PFNGLGETPROGRAMIVPROC, glGetProgramiv); - - GL_GET_PROC_ADR(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); - GL_GET_PROC_ADR(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray); - GL_GET_PROC_ADR(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); - GL_GET_PROC_ADR(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); - GL_GET_PROC_ADR(PFNGLVERTEXATTRIB1FPROC, glVertexAttrib1f); - GL_GET_PROC_ADR(PFNGLVERTEXATTRIB4FPROC, glVertexAttrib4f); - GL_GET_PROC_ADR(PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv); - - GL_GET_PROC_ADR(PFNGLDEPTHRANGEFPROC, glDepthRangef); - GL_GET_PROC_ADR(PFNGLCLEARDEPTHFPROC, glClearDepthf); - - GL_GET_PROC_ADR(PFNGLDRAWBUFFERSPROC, glDrawBuffers); - GL_GET_PROC_ADR(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer); - GL_GET_PROC_ADR(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers); - GL_GET_PROC_ADR(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers); - GL_GET_PROC_ADR(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D); - GL_GET_PROC_ADR(PFNGLTEXIMAGE2DMULTISAMPLEPROC, glTexImage2DMultisample); - GL_GET_PROC_ADR(PFNGLTEXSTORAGE2DMULTISAMPLEPROC, glTexStorage2DMultisample); - GL_GET_PROC_ADR(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers); - GL_GET_PROC_ADR(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer); - GL_GET_PROC_ADR(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage); - GL_GET_PROC_ADR(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer); - GL_GET_PROC_ADR(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers); - GL_GET_PROC_ADR(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus); - GL_GET_PROC_ADR(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); - GL_GET_PROC_ADR(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); - GL_GET_PROC_ADR(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); - GL_GET_PROC_ADR(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays); - GL_GET_PROC_ADR(PFNGLGENBUFFERSPROC, glGenBuffers); - GL_GET_PROC_ADR(PFNGLBINDBUFFERPROC, glBindBuffer); - GL_GET_PROC_ADR(PFNGLBUFFERDATAPROC, glBufferData); - GL_GET_PROC_ADR(PFNGLMAPBUFFERPROC, glMapBuffer); - GL_GET_PROC_ADR(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange); - GL_GET_PROC_ADR(PFNGLUNMAPBUFFERPROC, glUnmapBuffer); - GL_GET_PROC_ADR(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); - GL_GET_PROC_ADR(PFNGLBINDIMAGETEXTUREPROC, glBindImageTexture); - GL_GET_PROC_ADR(PFNGLMEMORYBARRIERPROC, glMemoryBarrier); - GL_GET_PROC_ADR(PFNGLGETSTRINGIPROC, glGetStringi); - GL_GET_PROC_ADR(PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer); - GL_GET_PROC_ADR(PFNGLBUFFERSTORAGEPROC, glBufferStorage); - GL_GET_PROC_ADR(PFNGLFENCESYNCPROC, glFenceSync); - GL_GET_PROC_ADR(PFNGLCLIENTWAITSYNCPROC, glClientWaitSync); - GL_GET_PROC_ADR(PFNGLDELETESYNCPROC, glDeleteSync); - - GL_GET_PROC_ADR(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex); - GL_GET_PROC_ADR(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding); - GL_GET_PROC_ADR(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, glGetActiveUniformBlockiv); - GL_GET_PROC_ADR(PFNGLGETUNIFORMINDICESPROC, glGetUniformIndices); - GL_GET_PROC_ADR(PFNGLGETACTIVEUNIFORMSIVPROC, glGetActiveUniformsiv); - GL_GET_PROC_ADR(PFNGLBINDBUFFERBASEPROC, glBindBufferBase); - GL_GET_PROC_ADR(PFNGLBUFFERSUBDATAPROC, glBufferSubData); - - GL_GET_PROC_ADR(PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary); - GL_GET_PROC_ADR(PFNGLPROGRAMBINARYPROC, glProgramBinary); - GL_GET_PROC_ADR(PFNGLPROGRAMPARAMETERIPROC, glProgramParameteri); - - GL_GET_PROC_ADR(PFNGLTEXSTORAGE2DPROC, glTexStorage2D); - GL_GET_PROC_ADR(PFNGLTEXTURESTORAGE2DPROC, glTextureStorage2D); - GL_GET_PROC_ADR(PFNGLTEXTURESUBIMAGE2DPROC, glTextureSubImage2D); - GL_GET_PROC_ADR(PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC, glTextureStorage2DMultisample); - - GL_GET_PROC_ADR(PFNGLTEXTUREPARAMETERIPROC, glTextureParameteri); - GL_GET_PROC_ADR(PFNGLTEXTUREPARAMETERFPROC, glTextureParameterf); - GL_GET_PROC_ADR(PFNGLCREATETEXTURESPROC, glCreateTextures); - GL_GET_PROC_ADR(PFNGLCREATEBUFFERSPROC, glCreateBuffers); - GL_GET_PROC_ADR(PFNGLCREATEFRAMEBUFFERSPROC, glCreateFramebuffers); - GL_GET_PROC_ADR(PFNGLNAMEDFRAMEBUFFERTEXTUREPROC, glNamedFramebufferTexture); - GL_GET_PROC_ADR(PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC, glDrawRangeElementsBaseVertex); - GL_GET_PROC_ADR(PFNGLFLUSHMAPPEDBUFFERRANGEPROC, glFlushMappedBufferRange); - GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERPROC, glTextureBarrier); - GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERNVPROC, glTextureBarrierNV); - GL_GET_PROC_ADR(PFNGLCLEARBUFFERFVPROC, glClearBufferfv); - GL_GET_PROC_ADR(PFNGLENABLEIPROC, glEnablei); - GL_GET_PROC_ADR(PFNGLDISABLEIPROC, glDisablei); - GL_GET_PROC_ADR(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC, glEGLImageTargetTexture2DOES); + GL_GET_PROC_ADR(PFNGLCREATESHADERPROC, CreateShader); + GL_GET_PROC_ADR(PFNGLCOMPILESHADERPROC, CompileShader); + GL_GET_PROC_ADR(PFNGLSHADERSOURCEPROC, ShaderSource); + GL_GET_PROC_ADR(PFNGLCREATEPROGRAMPROC, CreateProgram); + GL_GET_PROC_ADR(PFNGLATTACHSHADERPROC, AttachShader); + GL_GET_PROC_ADR(PFNGLLINKPROGRAMPROC, LinkProgram); + GL_GET_PROC_ADR(PFNGLUSEPROGRAMPROC, UseProgram); + GL_GET_PROC_ADR(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation); + GL_GET_PROC_ADR(PFNGLUNIFORM1IPROC, Uniform1i); + GL_GET_PROC_ADR(PFNGLUNIFORM1FPROC, Uniform1f); + GL_GET_PROC_ADR(PFNGLUNIFORM2FPROC, Uniform2f); + GL_GET_PROC_ADR(PFNGLUNIFORM2IPROC, Uniform2i); + GL_GET_PROC_ADR(PFNGLUNIFORM4IPROC, Uniform4i); + GL_GET_PROC_ADR(PFNGLUNIFORM4FPROC, Uniform4f); + GL_GET_PROC_ADR(PFNGLUNIFORM3FVPROC, Uniform3fv); + GL_GET_PROC_ADR(PFNGLUNIFORM4FVPROC, Uniform4fv); + GL_GET_PROC_ADR(PFNGLDETACHSHADERPROC, DetachShader); + GL_GET_PROC_ADR(PFNGLDELETESHADERPROC, DeleteShader); + GL_GET_PROC_ADR(PFNGLDELETEPROGRAMPROC, DeleteProgram); + GL_GET_PROC_ADR(PFNGLGETPROGRAMINFOLOGPROC, GetProgramInfoLog); + GL_GET_PROC_ADR(PFNGLGETSHADERINFOLOGPROC, GetShaderInfoLog); + GL_GET_PROC_ADR(PFNGLGETSHADERIVPROC, GetShaderiv); + GL_GET_PROC_ADR(PFNGLGETPROGRAMIVPROC, GetProgramiv); + + GL_GET_PROC_ADR(PFNGLENABLEVERTEXATTRIBARRAYPROC, EnableVertexAttribArray); + GL_GET_PROC_ADR(PFNGLDISABLEVERTEXATTRIBARRAYPROC, DisableVertexAttribArray); + GL_GET_PROC_ADR(PFNGLVERTEXATTRIBPOINTERPROC, VertexAttribPointer); + GL_GET_PROC_ADR(PFNGLBINDATTRIBLOCATIONPROC, BindAttribLocation); + GL_GET_PROC_ADR(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f); + GL_GET_PROC_ADR(PFNGLVERTEXATTRIB4FPROC, VertexAttrib4f); + GL_GET_PROC_ADR(PFNGLVERTEXATTRIB4FVPROC, VertexAttrib4fv); + + GL_GET_PROC_ADR(PFNGLDEPTHRANGEFPROC, DepthRangef); + GL_GET_PROC_ADR(PFNGLCLEARDEPTHFPROC, ClearDepthf); + + GL_GET_PROC_ADR(PFNGLDRAWBUFFERSPROC, DrawBuffers); + GL_GET_PROC_ADR(PFNGLBINDFRAMEBUFFERPROC, BindFramebuffer); + GL_GET_PROC_ADR(PFNGLDELETEFRAMEBUFFERSPROC, DeleteFramebuffers); + GL_GET_PROC_ADR(PFNGLGENFRAMEBUFFERSPROC, GenFramebuffers); + GL_GET_PROC_ADR(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D); + GL_GET_PROC_ADR(PFNGLTEXIMAGE2DMULTISAMPLEPROC, TexImage2DMultisample); + GL_GET_PROC_ADR(PFNGLTEXSTORAGE2DMULTISAMPLEPROC, TexStorage2DMultisample); + GL_GET_PROC_ADR(PFNGLGENRENDERBUFFERSPROC, GenRenderbuffers); + GL_GET_PROC_ADR(PFNGLBINDRENDERBUFFERPROC, BindRenderbuffer); + GL_GET_PROC_ADR(PFNGLRENDERBUFFERSTORAGEPROC, RenderbufferStorage); + GL_GET_PROC_ADR(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer); + GL_GET_PROC_ADR(PFNGLDELETERENDERBUFFERSPROC, DeleteRenderbuffers); + GL_GET_PROC_ADR(PFNGLCHECKFRAMEBUFFERSTATUSPROC, CheckFramebufferStatus); + GL_GET_PROC_ADR(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer); + GL_GET_PROC_ADR(PFNGLGENVERTEXARRAYSPROC, GenVertexArrays); + GL_GET_PROC_ADR(PFNGLBINDVERTEXARRAYPROC, BindVertexArray); + GL_GET_PROC_ADR(PFNGLDELETEVERTEXARRAYSPROC, DeleteVertexArrays); + GL_GET_PROC_ADR(PFNGLGENBUFFERSPROC, GenBuffers); + GL_GET_PROC_ADR(PFNGLBINDBUFFERPROC, BindBuffer); + GL_GET_PROC_ADR(PFNGLBUFFERDATAPROC, BufferData); + GL_GET_PROC_ADR(PFNGLMAPBUFFERPROC, MapBuffer); + GL_GET_PROC_ADR(PFNGLMAPBUFFERRANGEPROC, MapBufferRange); + GL_GET_PROC_ADR(PFNGLUNMAPBUFFERPROC, UnmapBuffer); + GL_GET_PROC_ADR(PFNGLDELETEBUFFERSPROC, DeleteBuffers); + GL_GET_PROC_ADR(PFNGLBINDIMAGETEXTUREPROC, BindImageTexture); + GL_GET_PROC_ADR(PFNGLMEMORYBARRIERPROC, MemoryBarrier); + GL_GET_PROC_ADR(PFNGLGETSTRINGIPROC, GetStringi); + GL_GET_PROC_ADR(PFNGLINVALIDATEFRAMEBUFFERPROC, InvalidateFramebuffer); + GL_GET_PROC_ADR(PFNGLBUFFERSTORAGEPROC, BufferStorage); + GL_GET_PROC_ADR(PFNGLFENCESYNCPROC, FenceSync); + GL_GET_PROC_ADR(PFNGLCLIENTWAITSYNCPROC, ClientWaitSync); + GL_GET_PROC_ADR(PFNGLDELETESYNCPROC, DeleteSync); + + GL_GET_PROC_ADR(PFNGLGETUNIFORMBLOCKINDEXPROC, GetUniformBlockIndex); + GL_GET_PROC_ADR(PFNGLUNIFORMBLOCKBINDINGPROC, UniformBlockBinding); + GL_GET_PROC_ADR(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, GetActiveUniformBlockiv); + GL_GET_PROC_ADR(PFNGLGETUNIFORMINDICESPROC, GetUniformIndices); + GL_GET_PROC_ADR(PFNGLGETACTIVEUNIFORMSIVPROC, GetActiveUniformsiv); + GL_GET_PROC_ADR(PFNGLBINDBUFFERBASEPROC, BindBufferBase); + GL_GET_PROC_ADR(PFNGLBUFFERSUBDATAPROC, BufferSubData); + + GL_GET_PROC_ADR(PFNGLGETPROGRAMBINARYPROC, GetProgramBinary); + GL_GET_PROC_ADR(PFNGLPROGRAMBINARYPROC, ProgramBinary); + GL_GET_PROC_ADR(PFNGLPROGRAMPARAMETERIPROC, ProgramParameteri); + + GL_GET_PROC_ADR(PFNGLTEXSTORAGE2DPROC, TexStorage2D); + GL_GET_PROC_ADR(PFNGLTEXTURESTORAGE2DPROC, TextureStorage2D); + GL_GET_PROC_ADR(PFNGLTEXTURESUBIMAGE2DPROC, TextureSubImage2D); + GL_GET_PROC_ADR(PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC, TextureStorage2DMultisample); + + GL_GET_PROC_ADR(PFNGLTEXTUREPARAMETERIPROC, TextureParameteri); + GL_GET_PROC_ADR(PFNGLTEXTUREPARAMETERFPROC, TextureParameterf); + GL_GET_PROC_ADR(PFNGLCREATETEXTURESPROC, CreateTextures); + GL_GET_PROC_ADR(PFNGLCREATEBUFFERSPROC, CreateBuffers); + GL_GET_PROC_ADR(PFNGLCREATEFRAMEBUFFERSPROC, CreateFramebuffers); + GL_GET_PROC_ADR(PFNGLNAMEDFRAMEBUFFERTEXTUREPROC, NamedFramebufferTexture); + GL_GET_PROC_ADR(PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC, DrawRangeElementsBaseVertex); + GL_GET_PROC_ADR(PFNGLFLUSHMAPPEDBUFFERRANGEPROC, FlushMappedBufferRange); + GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERPROC, TextureBarrier); + GL_GET_PROC_ADR(PFNGLTEXTUREBARRIERNVPROC, TextureBarrierNV); + GL_GET_PROC_ADR(PFNGLCLEARBUFFERFVPROC, ClearBufferfv); + GL_GET_PROC_ADR(PFNGLENABLEIPROC, Enablei); + GL_GET_PROC_ADR(PFNGLDISABLEIPROC, Disablei); + GL_GET_PROC_ADR(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC, EGLImageTargetTexture2DOES); } diff --git a/src/Graphics/OpenGLContext/GLFunctions.h b/src/Graphics/OpenGLContext/GLFunctions.h index f2673f8f9..944e23acb 100644 --- a/src/Graphics/OpenGLContext/GLFunctions.h +++ b/src/Graphics/OpenGLContext/GLFunctions.h @@ -4,7 +4,6 @@ #ifdef OS_WINDOWS #include #elif defined(OS_LINUX) -//#define GL_GLEXT_PROTOTYPES #include #endif @@ -16,7 +15,7 @@ #include #include #include -//#include + #elif defined(OS_IOS) #include #include @@ -30,6 +29,7 @@ typedef double GLdouble; #include #else #include +#include #endif #include @@ -37,326 +37,296 @@ typedef double GLdouble; #include #include "Log.h" -#ifdef GL_ERROR_DEBUG -#define CHECKED_GL_FUNCTION(proc_name, ...) checked([&]() { proc_name(__VA_ARGS__);}, #proc_name) -#define CHECKED_GL_FUNCTION_WITH_RETURN(proc_name, ReturnType, ...) checkedWithReturn([&]() { return proc_name(__VA_ARGS__);}, #proc_name) -#else -#define CHECKED_GL_FUNCTION(proc_name, ...) proc_name(__VA_ARGS__) -#define CHECKED_GL_FUNCTION_WITH_RETURN(proc_name, ReturnType, ...) proc_name(__VA_ARGS__) -#endif +#define IS_GL_FUNCTION_VALID(proc_name) ptr##proc_name != nullptr -#define IS_GL_FUNCTION_VALID(proc_name) g_##proc_name != nullptr -#define GET_GL_FUNCTION(proc_name) g_##proc_name - -#if defined(EGL) || defined(OS_IOS) - -#define glGetError g_glGetError -#define glBlendFunc(...) CHECKED_GL_FUNCTION(g_glBlendFunc, __VA_ARGS__) -#define glPixelStorei(...) CHECKED_GL_FUNCTION(g_glPixelStorei, __VA_ARGS__) -#define glClearColor(...) CHECKED_GL_FUNCTION(g_glClearColor, __VA_ARGS__) -#define glCullFace(...) CHECKED_GL_FUNCTION(g_glCullFace, __VA_ARGS__) -#define glDepthFunc(...) CHECKED_GL_FUNCTION(g_glDepthFunc, __VA_ARGS__) -#define glDepthMask(...) CHECKED_GL_FUNCTION(g_glDepthMask, __VA_ARGS__) -#define glDisable(...) CHECKED_GL_FUNCTION(g_glDisable, __VA_ARGS__) -#define glEnable(...) CHECKED_GL_FUNCTION(g_glEnable, __VA_ARGS__) -#define glPolygonOffset(...) CHECKED_GL_FUNCTION(g_glPolygonOffset, __VA_ARGS__) -#define glScissor(...) CHECKED_GL_FUNCTION(g_glScissor, __VA_ARGS__) -#define glViewport(...) CHECKED_GL_FUNCTION(g_glViewport, __VA_ARGS__) -#define glBindTexture(...) CHECKED_GL_FUNCTION(g_glBindTexture, __VA_ARGS__) -#define glTexImage2D(...) CHECKED_GL_FUNCTION(g_glTexImage2D, __VA_ARGS__) -#define glTexParameteri(...) CHECKED_GL_FUNCTION(g_glTexParameteri, __VA_ARGS__) -#define glGetIntegerv(...) CHECKED_GL_FUNCTION(g_glGetIntegerv, __VA_ARGS__) -#define glGetString(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glGetString, const GLubyte*, __VA_ARGS__) -#define glReadPixels(...) CHECKED_GL_FUNCTION(g_glReadPixels, __VA_ARGS__) -#define glTexSubImage2D(...) CHECKED_GL_FUNCTION(g_glTexSubImage2D, __VA_ARGS__) -#define glDrawArrays(...) CHECKED_GL_FUNCTION(g_glDrawArrays, __VA_ARGS__) -#define glDrawElements(...) CHECKED_GL_FUNCTION(g_glDrawElements, __VA_ARGS__) -#define glLineWidth(...) CHECKED_GL_FUNCTION(g_glLineWidth, __VA_ARGS__) -#define glClear(...) CHECKED_GL_FUNCTION(g_glClear, __VA_ARGS__) -#define glGetFloatv(...) CHECKED_GL_FUNCTION(g_glGetFloatv, __VA_ARGS__) -#define glDeleteTextures(...) CHECKED_GL_FUNCTION(g_glDeleteTextures, __VA_ARGS__) -#define glGenTextures(...) CHECKED_GL_FUNCTION(g_glGenTextures, __VA_ARGS__) -#define glTexParameterf(...) CHECKED_GL_FUNCTION(g_glTexParameterf, __VA_ARGS__) -#define glActiveTexture(...) CHECKED_GL_FUNCTION(g_glActiveTexture, __VA_ARGS__) -#define glBlendColor(...) CHECKED_GL_FUNCTION(g_glBlendColor, __VA_ARGS__) -#define glReadBuffer(...) CHECKED_GL_FUNCTION(g_glReadBuffer, __VA_ARGS__) -#define glFinish(...) CHECKED_GL_FUNCTION(g_glFinish, __VA_ARGS__) -#if defined(OS_ANDROID) -#define eglGetNativeClientBufferANDROID(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_eglGetNativeClientBufferANDROID, EGLClientBuffer, __VA_ARGS__) +#if !defined(EGL) && !defined(OS_IOS) +typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units); +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); #endif -extern PFNGLBLENDFUNCPROC g_glBlendFunc; -extern PFNGLPIXELSTOREIPROC g_glPixelStorei; -extern PFNGLCLEARCOLORPROC g_glClearColor; -extern PFNGLCULLFACEPROC g_glCullFace; -extern PFNGLDEPTHFUNCPROC g_glDepthFunc; -extern PFNGLDEPTHMASKPROC g_glDepthMask; -extern PFNGLDISABLEPROC g_glDisable; -extern PFNGLENABLEPROC g_glEnable; -extern PFNGLPOLYGONOFFSETPROC g_glPolygonOffset; -extern PFNGLSCISSORPROC g_glScissor; -extern PFNGLVIEWPORTPROC g_glViewport; -extern PFNGLBINDTEXTUREPROC g_glBindTexture; -extern PFNGLTEXIMAGE2DPROC g_glTexImage2D; -extern PFNGLTEXPARAMETERIPROC g_glTexParameteri; -extern PFNGLGETINTEGERVPROC g_glGetIntegerv; -extern PFNGLGETSTRINGPROC g_glGetString; -extern PFNGLREADPIXELSPROC g_glReadPixels; -extern PFNGLTEXSUBIMAGE2DPROC g_glTexSubImage2D; -extern PFNGLDRAWARRAYSPROC g_glDrawArrays; -extern PFNGLGETERRORPROC g_glGetError; -extern PFNGLDRAWELEMENTSPROC g_glDrawElements; -extern PFNGLLINEWIDTHPROC g_glLineWidth; -extern PFNGLCLEARPROC g_glClear; -extern PFNGLGETFLOATVPROC g_glGetFloatv; -extern PFNGLDELETETEXTURESPROC g_glDeleteTextures; -extern PFNGLGENTEXTURESPROC g_glGenTextures; -extern PFNGLTEXPARAMETERFPROC g_glTexParameterf; -extern PFNGLACTIVETEXTUREPROC g_glActiveTexture; -extern PFNGLBLENDCOLORPROC g_glBlendColor; -extern PFNGLREADBUFFERPROC g_glReadBuffer; -extern PFNGLFINISHPROC g_glFinish; +extern PFNGLBLENDFUNCPROC ptrBlendFunc; +extern PFNGLPIXELSTOREIPROC ptrPixelStorei; +extern PFNGLCLEARCOLORPROC ptrClearColor; +extern PFNGLCULLFACEPROC ptrCullFace; +extern PFNGLDEPTHFUNCPROC ptrDepthFunc; +extern PFNGLDEPTHMASKPROC ptrDepthMask; +extern PFNGLDISABLEPROC ptrDisable; +extern PFNGLENABLEPROC ptrEnable; +extern PFNGLPOLYGONOFFSETPROC ptrPolygonOffset; +extern PFNGLSCISSORPROC ptrScissor; +extern PFNGLVIEWPORTPROC ptrViewport; +extern PFNGLBINDTEXTUREPROC ptrBindTexture; +extern PFNGLTEXIMAGE2DPROC ptrTexImage2D; +extern PFNGLTEXPARAMETERIPROC ptrTexParameteri; +extern PFNGLGETINTEGERVPROC ptrGetIntegerv; +extern PFNGLGETSTRINGPROC ptrGetString; +extern PFNGLREADPIXELSPROC ptrReadPixels; +extern PFNGLTEXSUBIMAGE2DPROC ptrTexSubImage2D; +extern PFNGLDRAWARRAYSPROC ptrDrawArrays; +extern PFNGLGETERRORPROC ptrGetError; +extern PFNGLDRAWELEMENTSPROC ptrDrawElements; +extern PFNGLLINEWIDTHPROC ptrLineWidth; +extern PFNGLCLEARPROC ptrClear; +extern PFNGLGETFLOATVPROC ptrGetFloatv; +extern PFNGLDELETETEXTURESPROC ptrDeleteTextures; +extern PFNGLGENTEXTURESPROC ptrGenTextures; +extern PFNGLTEXPARAMETERFPROC ptrTexParameterf; +extern PFNGLACTIVETEXTUREPROC ptrActiveTexture; +extern PFNGLBLENDCOLORPROC ptrBlendColor; +extern PFNGLREADBUFFERPROC ptrReadBuffer; +extern PFNGLFINISHPROC ptrFinish; #if defined(OS_ANDROID) -extern PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC g_eglGetNativeClientBufferANDROID; -#endif +extern PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC ptrGetNativeClientBufferANDROID; #endif #ifdef OS_WINDOWS -#define glActiveTexture g_glActiveTexture -#define glBlendColor g_glBlendColor - -extern PFNGLACTIVETEXTUREPROC g_glActiveTexture; -extern PFNGLBLENDCOLORPROC g_glBlendColor; +extern PFNGLACTIVETEXTUREPROC ptrActiveTexture; +extern PFNGLBLENDCOLORPROC ptrBlendColor; #endif -#define glCreateShader(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glCreateShader, GLuint, __VA_ARGS__) -#define glCompileShader(...) CHECKED_GL_FUNCTION(g_glCompileShader, __VA_ARGS__) -#define glShaderSource(...) CHECKED_GL_FUNCTION(g_glShaderSource, __VA_ARGS__) -#define glCreateProgram(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glCreateProgram, GLuint, __VA_ARGS__) -#define glAttachShader(...) CHECKED_GL_FUNCTION(g_glAttachShader, __VA_ARGS__) -#define glLinkProgram(...) CHECKED_GL_FUNCTION(g_glLinkProgram, __VA_ARGS__) -#define glUseProgram(...) CHECKED_GL_FUNCTION(g_glUseProgram, __VA_ARGS__) -#define glGetUniformLocation(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glGetUniformLocation, GLint, __VA_ARGS__) -#define glUniform1i(...) CHECKED_GL_FUNCTION(g_glUniform1i, __VA_ARGS__) -#define glUniform1f(...) CHECKED_GL_FUNCTION(g_glUniform1f, __VA_ARGS__) -#define glUniform2f(...) CHECKED_GL_FUNCTION(g_glUniform2f, __VA_ARGS__) -#define glUniform2i(...) CHECKED_GL_FUNCTION(g_glUniform2i, __VA_ARGS__) -#define glUniform4i(...) CHECKED_GL_FUNCTION(g_glUniform4i, __VA_ARGS__) - -#define glUniform4f(...) CHECKED_GL_FUNCTION(g_glUniform4f, __VA_ARGS__) -#define glUniform3fv(...) CHECKED_GL_FUNCTION(g_glUniform3fv, __VA_ARGS__) -#define glUniform4fv(...) CHECKED_GL_FUNCTION(g_glUniform4fv, __VA_ARGS__) -#define glDetachShader(...) CHECKED_GL_FUNCTION(g_glDetachShader, __VA_ARGS__) -#define glDeleteShader(...) CHECKED_GL_FUNCTION(g_glDeleteShader, __VA_ARGS__) -#define glDeleteProgram(...) CHECKED_GL_FUNCTION(g_glDeleteProgram, __VA_ARGS__) -#define glGetProgramInfoLog(...) CHECKED_GL_FUNCTION(g_glGetProgramInfoLog, __VA_ARGS__) -#define glGetShaderInfoLog(...) CHECKED_GL_FUNCTION(g_glGetShaderInfoLog, __VA_ARGS__) -#define glGetShaderiv(...) CHECKED_GL_FUNCTION(g_glGetShaderiv, __VA_ARGS__) -#define glGetProgramiv(...) CHECKED_GL_FUNCTION(g_glGetProgramiv, __VA_ARGS__) - -#define glEnableVertexAttribArray(...) CHECKED_GL_FUNCTION(g_glEnableVertexAttribArray, __VA_ARGS__) -#define glDisableVertexAttribArray(...) CHECKED_GL_FUNCTION(g_glDisableVertexAttribArray, __VA_ARGS__) -#define glVertexAttribPointer(...) CHECKED_GL_FUNCTION(g_glVertexAttribPointer, __VA_ARGS__) -#define glBindAttribLocation(...) CHECKED_GL_FUNCTION(g_glBindAttribLocation, __VA_ARGS__) -#define glVertexAttrib1f(...) CHECKED_GL_FUNCTION(g_glVertexAttrib1f, __VA_ARGS__) -#define glVertexAttrib4f(...) CHECKED_GL_FUNCTION(g_glVertexAttrib4f, __VA_ARGS__) -#define glVertexAttrib4fv(...) CHECKED_GL_FUNCTION(g_glVertexAttrib4fv, __VA_ARGS__) - -#define glDepthRangef(...) CHECKED_GL_FUNCTION(g_glDepthRangef, __VA_ARGS__) -#define glClearDepthf(...) CHECKED_GL_FUNCTION(g_glClearDepthf, __VA_ARGS__) - -#define glBindBuffer(...) CHECKED_GL_FUNCTION(g_glBindBuffer, __VA_ARGS__) -#define glBindFramebuffer(...) CHECKED_GL_FUNCTION(g_glBindFramebuffer, __VA_ARGS__) -#define glBindRenderbuffer(...) CHECKED_GL_FUNCTION(g_glBindRenderbuffer, __VA_ARGS__) -#define glDrawBuffers(...) CHECKED_GL_FUNCTION(g_glDrawBuffers, __VA_ARGS__) -#define glGenFramebuffers(...) CHECKED_GL_FUNCTION(g_glGenFramebuffers, __VA_ARGS__) -#define glDeleteFramebuffers(...) CHECKED_GL_FUNCTION(g_glDeleteFramebuffers, __VA_ARGS__) -#define glFramebufferTexture2D(...) CHECKED_GL_FUNCTION(g_glFramebufferTexture2D, __VA_ARGS__) -#define glTexImage2DMultisample(...) CHECKED_GL_FUNCTION(g_glTexImage2DMultisample, __VA_ARGS__) -#define glTexStorage2DMultisample(...) CHECKED_GL_FUNCTION(g_glTexStorage2DMultisample, __VA_ARGS__) -#define glGenRenderbuffers(...) CHECKED_GL_FUNCTION(g_glGenRenderbuffers, __VA_ARGS__) -#define glRenderbufferStorage(...) CHECKED_GL_FUNCTION(g_glRenderbufferStorage, __VA_ARGS__) -#define glDeleteRenderbuffers(...) CHECKED_GL_FUNCTION(g_glDeleteRenderbuffers, __VA_ARGS__) -#define glFramebufferRenderbuffer(...) CHECKED_GL_FUNCTION(g_glFramebufferRenderbuffer, __VA_ARGS__) -#define glCheckFramebufferStatus(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glCheckFramebufferStatus, GLenum, __VA_ARGS__) -#define glBlitFramebuffer(...) CHECKED_GL_FUNCTION(g_glBlitFramebuffer, __VA_ARGS__) -#define glGenVertexArrays(...) CHECKED_GL_FUNCTION(g_glGenVertexArrays, __VA_ARGS__) -#define glBindVertexArray(...) CHECKED_GL_FUNCTION(g_glBindVertexArray, __VA_ARGS__) -#define glDeleteVertexArrays(...) CHECKED_GL_FUNCTION(g_glDeleteVertexArrays, __VA_ARGS__); -#define glGenBuffers(...) CHECKED_GL_FUNCTION(g_glGenBuffers, __VA_ARGS__) -#define glBufferData(...) CHECKED_GL_FUNCTION(g_glBufferData, __VA_ARGS__) -#define glMapBuffer(...) CHECKED_GL_FUNCTION(g_glMapBuffer, __VA_ARGS__) -#define glMapBufferRange(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glMapBufferRange, void*, __VA_ARGS__) -#define glUnmapBuffer(...) CHECKED_GL_FUNCTION(g_glUnmapBuffer, __VA_ARGS__) -#define glDeleteBuffers(...) CHECKED_GL_FUNCTION(g_glDeleteBuffers, __VA_ARGS__) -#define glBindImageTexture(...) CHECKED_GL_FUNCTION(g_glBindImageTexture, __VA_ARGS__) -#define glMemoryBarrier(...) CHECKED_GL_FUNCTION(g_glMemoryBarrier, __VA_ARGS__) -#define glGetStringi(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glGetStringi, const GLubyte*, __VA_ARGS__) -#define glInvalidateFramebuffer(...) CHECKED_GL_FUNCTION(g_glInvalidateFramebuffer, __VA_ARGS__) -#define glBufferStorage(...) CHECKED_GL_FUNCTION(g_glBufferStorage, __VA_ARGS__) -#define glFenceSync(...) CHECKED_GL_FUNCTION_WITH_RETURN(g_glFenceSync, GLsync, __VA_ARGS__) -#define glClientWaitSync(...) CHECKED_GL_FUNCTION(g_glClientWaitSync, __VA_ARGS__) -#define glDeleteSync(...) CHECKED_GL_FUNCTION(g_glDeleteSync, __VA_ARGS__) - -#define glGetUniformBlockIndex(...) CHECKED_GL_FUNCTION(g_glGetUniformBlockIndex, __VA_ARGS__) -#define glUniformBlockBinding(...) CHECKED_GL_FUNCTION(g_glUniformBlockBinding, __VA_ARGS__) -#define glGetActiveUniformBlockiv(...) CHECKED_GL_FUNCTION(g_glGetActiveUniformBlockiv, __VA_ARGS__) -#define glGetUniformIndices(...) CHECKED_GL_FUNCTION(g_glGetUniformIndices, __VA_ARGS__) -#define glGetActiveUniformsiv(...) CHECKED_GL_FUNCTION(g_glGetActiveUniformsiv, __VA_ARGS__) -#define glBindBufferBase(...) CHECKED_GL_FUNCTION(g_glBindBufferBase, __VA_ARGS__) -#define glBufferSubData(...) CHECKED_GL_FUNCTION(g_glBufferSubData, __VA_ARGS__) - -#define glGetProgramBinary(...) CHECKED_GL_FUNCTION(g_glGetProgramBinary, __VA_ARGS__) -#define glProgramBinary(...) CHECKED_GL_FUNCTION(g_glProgramBinary, __VA_ARGS__) -#define glProgramParameteri(...) CHECKED_GL_FUNCTION(g_glProgramParameteri, __VA_ARGS__) - -#define glTexStorage2D(...) CHECKED_GL_FUNCTION(g_glTexStorage2D, __VA_ARGS__) -#define glTextureStorage2D(...) CHECKED_GL_FUNCTION(g_glTextureStorage2D, __VA_ARGS__) -#define glTextureSubImage2D(...) CHECKED_GL_FUNCTION(g_glTextureSubImage2D, __VA_ARGS__) -#define glTextureStorage2DMultisample(...) CHECKED_GL_FUNCTION(g_glTextureStorage2DMultisample, __VA_ARGS__) -#define glTextureParameteri(...) CHECKED_GL_FUNCTION(g_glTextureParameteri, __VA_ARGS__) -#define glTextureParameterf(...) CHECKED_GL_FUNCTION(g_glTextureParameterf, __VA_ARGS__) -#define glCreateTextures(...) CHECKED_GL_FUNCTION(g_glCreateTextures, __VA_ARGS__) -#define glCreateBuffers(...) CHECKED_GL_FUNCTION(g_glCreateBuffers, __VA_ARGS__) -#define glCreateFramebuffers(...) CHECKED_GL_FUNCTION(g_glCreateFramebuffers, __VA_ARGS__) -#define glNamedFramebufferTexture(...) CHECKED_GL_FUNCTION(g_glNamedFramebufferTexture, __VA_ARGS__) -#define glDrawRangeElementsBaseVertex(...) CHECKED_GL_FUNCTION(g_glDrawRangeElementsBaseVertex, __VA_ARGS__) -#define glFlushMappedBufferRange(...) CHECKED_GL_FUNCTION(g_glFlushMappedBufferRange, __VA_ARGS__) -#define glTextureBarrier(...) CHECKED_GL_FUNCTION(g_glTextureBarrier, __VA_ARGS__) -#define glTextureBarrierNV(...) CHECKED_GL_FUNCTION(g_glTextureBarrierNV, __VA_ARGS__) -#define glClearBufferfv(...) CHECKED_GL_FUNCTION(g_glClearBufferfv, __VA_ARGS__) -#define glEnablei(...) CHECKED_GL_FUNCTION(g_glEnablei, __VA_ARGS__) -#define glDisablei(...) CHECKED_GL_FUNCTION(g_glDisablei, __VA_ARGS__) -#define glEGLImageTargetTexture2DOES(...) CHECKED_GL_FUNCTION(g_glEGLImageTargetTexture2DOES, __VA_ARGS__) - -extern PFNGLCREATESHADERPROC g_glCreateShader; -extern PFNGLCOMPILESHADERPROC g_glCompileShader; -extern PFNGLSHADERSOURCEPROC g_glShaderSource; -extern PFNGLCREATEPROGRAMPROC g_glCreateProgram; -extern PFNGLATTACHSHADERPROC g_glAttachShader; -extern PFNGLLINKPROGRAMPROC g_glLinkProgram; -extern PFNGLUSEPROGRAMPROC g_glUseProgram; -extern PFNGLGETUNIFORMLOCATIONPROC g_glGetUniformLocation; -extern PFNGLUNIFORM1IPROC g_glUniform1i; -extern PFNGLUNIFORM1FPROC g_glUniform1f; -extern PFNGLUNIFORM2FPROC g_glUniform2f; -extern PFNGLUNIFORM2IPROC g_glUniform2i; -extern PFNGLUNIFORM4IPROC g_glUniform4i; - -extern PFNGLUNIFORM4FPROC g_glUniform4f; -extern PFNGLUNIFORM3FVPROC g_glUniform3fv; -extern PFNGLUNIFORM4FVPROC g_glUniform4fv; -extern PFNGLDETACHSHADERPROC g_glDetachShader; -extern PFNGLDELETESHADERPROC g_glDeleteShader; -extern PFNGLDELETEPROGRAMPROC g_glDeleteProgram; -extern PFNGLGETPROGRAMINFOLOGPROC g_glGetProgramInfoLog; -extern PFNGLGETSHADERINFOLOGPROC g_glGetShaderInfoLog; -extern PFNGLGETSHADERIVPROC g_glGetShaderiv; -extern PFNGLGETPROGRAMIVPROC g_glGetProgramiv; - -extern PFNGLENABLEVERTEXATTRIBARRAYPROC g_glEnableVertexAttribArray; -extern PFNGLDISABLEVERTEXATTRIBARRAYPROC g_glDisableVertexAttribArray; -extern PFNGLVERTEXATTRIBPOINTERPROC g_glVertexAttribPointer; -extern PFNGLBINDATTRIBLOCATIONPROC g_glBindAttribLocation; -extern PFNGLVERTEXATTRIB1FPROC g_glVertexAttrib1f; -extern PFNGLVERTEXATTRIB4FPROC g_glVertexAttrib4f; -extern PFNGLVERTEXATTRIB4FVPROC g_glVertexAttrib4fv; - -extern PFNGLDEPTHRANGEFPROC g_glDepthRangef; -extern PFNGLCLEARDEPTHFPROC g_glClearDepthf; - -extern PFNGLDRAWBUFFERSPROC g_glDrawBuffers; -extern PFNGLGENFRAMEBUFFERSPROC g_glGenFramebuffers; -extern PFNGLBINDFRAMEBUFFERPROC g_glBindFramebuffer; -extern PFNGLDELETEFRAMEBUFFERSPROC g_glDeleteFramebuffers; -extern PFNGLFRAMEBUFFERTEXTURE2DPROC g_glFramebufferTexture2D; -extern PFNGLTEXIMAGE2DMULTISAMPLEPROC g_glTexImage2DMultisample; -extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC g_glTexStorage2DMultisample; -extern PFNGLGENRENDERBUFFERSPROC g_glGenRenderbuffers; -extern PFNGLBINDRENDERBUFFERPROC g_glBindRenderbuffer; -extern PFNGLRENDERBUFFERSTORAGEPROC g_glRenderbufferStorage; -extern PFNGLDELETERENDERBUFFERSPROC g_glDeleteRenderbuffers; -extern PFNGLFRAMEBUFFERRENDERBUFFERPROC g_glFramebufferRenderbuffer; -extern PFNGLCHECKFRAMEBUFFERSTATUSPROC g_glCheckFramebufferStatus; -extern PFNGLBLITFRAMEBUFFERPROC g_glBlitFramebuffer; -extern PFNGLGENVERTEXARRAYSPROC g_glGenVertexArrays; -extern PFNGLBINDVERTEXARRAYPROC g_glBindVertexArray; -extern PFNGLDELETEVERTEXARRAYSPROC g_glDeleteVertexArrays; -extern PFNGLGENBUFFERSPROC g_glGenBuffers; -extern PFNGLBINDBUFFERPROC g_glBindBuffer; -extern PFNGLBUFFERDATAPROC g_glBufferData; -extern PFNGLMAPBUFFERPROC g_glMapBuffer; -extern PFNGLMAPBUFFERRANGEPROC g_glMapBufferRange; -extern PFNGLUNMAPBUFFERPROC g_glUnmapBuffer; -extern PFNGLDELETEBUFFERSPROC g_glDeleteBuffers; -extern PFNGLBINDIMAGETEXTUREPROC g_glBindImageTexture; -extern PFNGLMEMORYBARRIERPROC g_glMemoryBarrier; -extern PFNGLGETSTRINGIPROC g_glGetStringi; -extern PFNGLINVALIDATEFRAMEBUFFERPROC g_glInvalidateFramebuffer; -extern PFNGLBUFFERSTORAGEPROC g_glBufferStorage; -extern PFNGLFENCESYNCPROC g_glFenceSync; -extern PFNGLCLIENTWAITSYNCPROC g_glClientWaitSync; -extern PFNGLDELETESYNCPROC g_glDeleteSync; - -extern PFNGLGETUNIFORMBLOCKINDEXPROC g_glGetUniformBlockIndex; -extern PFNGLUNIFORMBLOCKBINDINGPROC g_glUniformBlockBinding; -extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC g_glGetActiveUniformBlockiv; -extern PFNGLGETUNIFORMINDICESPROC g_glGetUniformIndices; -extern PFNGLGETACTIVEUNIFORMSIVPROC g_glGetActiveUniformsiv; -extern PFNGLBINDBUFFERBASEPROC g_glBindBufferBase; -extern PFNGLBUFFERSUBDATAPROC g_glBufferSubData; - -extern PFNGLGETPROGRAMBINARYPROC g_glGetProgramBinary; -extern PFNGLPROGRAMBINARYPROC g_glProgramBinary; -extern PFNGLPROGRAMPARAMETERIPROC g_glProgramParameteri; - -extern PFNGLTEXSTORAGE2DPROC g_glTexStorage2D; -extern PFNGLTEXTURESTORAGE2DPROC g_glTextureStorage2D; -extern PFNGLTEXTURESUBIMAGE2DPROC g_glTextureSubImage2D; -extern PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC g_glTextureStorage2DMultisample; -extern PFNGLTEXTUREPARAMETERIPROC g_glTextureParameteri; -extern PFNGLTEXTUREPARAMETERFPROC g_glTextureParameterf; -extern PFNGLCREATETEXTURESPROC g_glCreateTextures; -extern PFNGLCREATEBUFFERSPROC g_glCreateBuffers; -extern PFNGLCREATEFRAMEBUFFERSPROC g_glCreateFramebuffers; -extern PFNGLNAMEDFRAMEBUFFERTEXTUREPROC g_glNamedFramebufferTexture; -extern PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC g_glDrawRangeElementsBaseVertex; -extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC g_glFlushMappedBufferRange; -extern PFNGLTEXTUREBARRIERPROC g_glTextureBarrier; -extern PFNGLTEXTUREBARRIERNVPROC g_glTextureBarrierNV; -extern PFNGLCLEARBUFFERFVPROC g_glClearBufferfv; -extern PFNGLENABLEIPROC g_glEnablei; -extern PFNGLDISABLEIPROC g_glDisablei; +extern PFNGLCREATESHADERPROC ptrCreateShader; +extern PFNGLCOMPILESHADERPROC ptrCompileShader; +extern PFNGLSHADERSOURCEPROC ptrShaderSource; +extern PFNGLCREATEPROGRAMPROC ptrCreateProgram; +extern PFNGLATTACHSHADERPROC ptrAttachShader; +extern PFNGLLINKPROGRAMPROC ptrLinkProgram; +extern PFNGLUSEPROGRAMPROC ptrUseProgram; +extern PFNGLGETUNIFORMLOCATIONPROC ptrGetUniformLocation; +extern PFNGLUNIFORM1IPROC ptrUniform1i; +extern PFNGLUNIFORM1FPROC ptrUniform1f; +extern PFNGLUNIFORM2FPROC ptrUniform2f; +extern PFNGLUNIFORM2IPROC ptrUniform2i; +extern PFNGLUNIFORM4IPROC ptrUniform4i; + +extern PFNGLUNIFORM4FPROC ptrUniform4f; +extern PFNGLUNIFORM3FVPROC ptrUniform3fv; +extern PFNGLUNIFORM4FVPROC ptrUniform4fv; +extern PFNGLDETACHSHADERPROC ptrDetachShader; +extern PFNGLDELETESHADERPROC ptrDeleteShader; +extern PFNGLDELETEPROGRAMPROC ptrDeleteProgram; +extern PFNGLGETPROGRAMINFOLOGPROC ptrGetProgramInfoLog; +extern PFNGLGETSHADERINFOLOGPROC ptrGetShaderInfoLog; +extern PFNGLGETSHADERIVPROC ptrGetShaderiv; +extern PFNGLGETPROGRAMIVPROC ptrGetProgramiv; + +extern PFNGLENABLEVERTEXATTRIBARRAYPROC ptrEnableVertexAttribArray; +extern PFNGLDISABLEVERTEXATTRIBARRAYPROC ptrDisableVertexAttribArray; +extern PFNGLVERTEXATTRIBPOINTERPROC ptrVertexAttribPointer; +extern PFNGLBINDATTRIBLOCATIONPROC ptrBindAttribLocation; +extern PFNGLVERTEXATTRIB1FPROC ptrVertexAttrib1f; +extern PFNGLVERTEXATTRIB4FPROC ptrVertexAttrib4f; +extern PFNGLVERTEXATTRIB4FVPROC ptrVertexAttrib4fv; + +extern PFNGLDEPTHRANGEFPROC ptrDepthRangef; +extern PFNGLCLEARDEPTHFPROC ptrClearDepthf; + +extern PFNGLDRAWBUFFERSPROC ptrDrawBuffers; +extern PFNGLGENFRAMEBUFFERSPROC ptrGenFramebuffers; +extern PFNGLBINDFRAMEBUFFERPROC ptrBindFramebuffer; +extern PFNGLDELETEFRAMEBUFFERSPROC ptrDeleteFramebuffers; +extern PFNGLFRAMEBUFFERTEXTURE2DPROC ptrFramebufferTexture2D; +extern PFNGLTEXIMAGE2DMULTISAMPLEPROC ptrTexImage2DMultisample; +extern PFNGLTEXSTORAGE2DMULTISAMPLEPROC ptrTexStorage2DMultisample; +extern PFNGLGENRENDERBUFFERSPROC ptrGenRenderbuffers; +extern PFNGLBINDRENDERBUFFERPROC ptrBindRenderbuffer; +extern PFNGLRENDERBUFFERSTORAGEPROC ptrRenderbufferStorage; +extern PFNGLDELETERENDERBUFFERSPROC ptrDeleteRenderbuffers; +extern PFNGLFRAMEBUFFERRENDERBUFFERPROC ptrFramebufferRenderbuffer; +extern PFNGLCHECKFRAMEBUFFERSTATUSPROC ptrCheckFramebufferStatus; +extern PFNGLBLITFRAMEBUFFERPROC ptrBlitFramebuffer; +extern PFNGLGENVERTEXARRAYSPROC ptrGenVertexArrays; +extern PFNGLBINDVERTEXARRAYPROC ptrBindVertexArray; +extern PFNGLDELETEVERTEXARRAYSPROC ptrDeleteVertexArrays; +extern PFNGLGENBUFFERSPROC ptrGenBuffers; +extern PFNGLBINDBUFFERPROC ptrBindBuffer; +extern PFNGLBUFFERDATAPROC ptrBufferData; +extern PFNGLMAPBUFFERPROC ptrMapBuffer; +extern PFNGLMAPBUFFERRANGEPROC ptrMapBufferRange; +extern PFNGLUNMAPBUFFERPROC ptrUnmapBuffer; +extern PFNGLDELETEBUFFERSPROC ptrDeleteBuffers; +extern PFNGLBINDIMAGETEXTUREPROC ptrBindImageTexture; +extern PFNGLMEMORYBARRIERPROC ptrMemoryBarrier; +extern PFNGLGETSTRINGIPROC ptrGetStringi; +extern PFNGLINVALIDATEFRAMEBUFFERPROC ptrInvalidateFramebuffer; +extern PFNGLBUFFERSTORAGEPROC ptrBufferStorage; +extern PFNGLFENCESYNCPROC ptrFenceSync; +extern PFNGLCLIENTWAITSYNCPROC ptrClientWaitSync; +extern PFNGLDELETESYNCPROC ptrDeleteSync; + +extern PFNGLGETUNIFORMBLOCKINDEXPROC ptrGetUniformBlockIndex; +extern PFNGLUNIFORMBLOCKBINDINGPROC ptrUniformBlockBinding; +extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC ptrGetActiveUniformBlockiv; +extern PFNGLGETUNIFORMINDICESPROC ptrGetUniformIndices; +extern PFNGLGETACTIVEUNIFORMSIVPROC ptrGetActiveUniformsiv; +extern PFNGLBINDBUFFERBASEPROC ptrBindBufferBase; +extern PFNGLBUFFERSUBDATAPROC ptrBufferSubData; + +extern PFNGLGETPROGRAMBINARYPROC ptrGetProgramBinary; +extern PFNGLPROGRAMBINARYPROC ptrProgramBinary; +extern PFNGLPROGRAMPARAMETERIPROC ptrProgramParameteri; + +extern PFNGLTEXSTORAGE2DPROC ptrTexStorage2D; +extern PFNGLTEXTURESTORAGE2DPROC ptrTextureStorage2D; +extern PFNGLTEXTURESUBIMAGE2DPROC ptrTextureSubImage2D; +extern PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC ptrTextureStorage2DMultisample; +extern PFNGLTEXTUREPARAMETERIPROC ptrTextureParameteri; +extern PFNGLTEXTUREPARAMETERFPROC ptrTextureParameterf; +extern PFNGLCREATETEXTURESPROC ptrCreateTextures; +extern PFNGLCREATEBUFFERSPROC ptrCreateBuffers; +extern PFNGLCREATEFRAMEBUFFERSPROC ptrCreateFramebuffers; +extern PFNGLNAMEDFRAMEBUFFERTEXTUREPROC ptrNamedFramebufferTexture; +extern PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC ptrDrawRangeElementsBaseVertex; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC ptrFlushMappedBufferRange; +extern PFNGLTEXTUREBARRIERPROC ptrTextureBarrier; +extern PFNGLTEXTUREBARRIERNVPROC ptrTextureBarrierNV; +extern PFNGLCLEARBUFFERFVPROC ptrClearBufferfv; +extern PFNGLENABLEIPROC ptrEnablei; +extern PFNGLDISABLEIPROC ptrDisablei; typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, void* image); -extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC g_glEGLImageTargetTexture2DOES; +extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC ptrEGLImageTargetTexture2DOES; void initGLFunctions(); -template void checked(F fn, const char* _functionName) -{ - fn(); - auto error = glGetError(); - if (error != GL_NO_ERROR) { - std::stringstream errorString; - errorString << _functionName << " OpenGL error: 0x" << std::hex << error; - LOG(LOG_ERROR, errorString.str().c_str()); - throw std::runtime_error(errorString.str().c_str()); - } -} - -template R checkedWithReturn(F fn, const char* _functionName) -{ - R returnValue = fn(); - auto error = glGetError(); - if (error != GL_NO_ERROR) { - std::stringstream errorString; - errorString << _functionName << " OpenGL error: 0x" << std::hex << error; - LOG(LOG_ERROR, errorString.str().c_str()); - throw std::runtime_error(errorString.str().c_str()); - } - - return returnValue; -} +#define glGetError(...) opengl::FunctionWrapper::wrGetError(__VA_ARGS__) +#define glBlendFunc(...) opengl::FunctionWrapper::wrBlendFunc(__VA_ARGS__) +#define glPixelStorei(...) opengl::FunctionWrapper::wrPixelStorei(__VA_ARGS__) +#define glClearColor(...) opengl::FunctionWrapper::wrClearColor(__VA_ARGS__) +#define glCullFace(...) opengl::FunctionWrapper::wrCullFace(__VA_ARGS__) +#define glDepthFunc(...) opengl::FunctionWrapper::wrDepthFunc(__VA_ARGS__) +#define glDepthMask(...) opengl::FunctionWrapper::wrDepthMask(__VA_ARGS__) +#define glDisable(...) opengl::FunctionWrapper::wrDisable(__VA_ARGS__) +#define glEnable(...) opengl::FunctionWrapper::wrEnable(__VA_ARGS__) +#define glPolygonOffset(...) opengl::FunctionWrapper::wrPolygonOffset(__VA_ARGS__) +#define glScissor(...) opengl::FunctionWrapper::wrScissor(__VA_ARGS__) +#define glViewport(...) opengl::FunctionWrapper::wrViewport(__VA_ARGS__) +#define glBindTexture(...) opengl::FunctionWrapper::wrBindTexture(__VA_ARGS__) +#define glTexImage2D(...) opengl::FunctionWrapper::wrTexImage2D(__VA_ARGS__) +#define glTexParameteri(...) opengl::FunctionWrapper::wrTexParameteri(__VA_ARGS__) +#define glGetIntegerv(...) opengl::FunctionWrapper::wrGetIntegerv(__VA_ARGS__) +#define glGetString(...) opengl::FunctionWrapper::wrGetString(__VA_ARGS__) +#define glReadPixels(...) opengl::FunctionWrapper::wrReadPixels(__VA_ARGS__) +#define glTexSubImage2D(...) opengl::FunctionWrapper::wrTexSubImage2D(__VA_ARGS__) +#define glDrawArrays(...) opengl::FunctionWrapper::wrDrawArrays(__VA_ARGS__) +#define glDrawElements(...) opengl::FunctionWrapper::wrDrawElements(__VA_ARGS__) +#define glLineWidth(...) opengl::FunctionWrapper::wrLineWidth(__VA_ARGS__) +#define glClear(...) opengl::FunctionWrapper::wrClear(__VA_ARGS__) +#define glGetFloatv(...) opengl::FunctionWrapper::wrGetFloatv(__VA_ARGS__) +#define glDeleteTextures(...) opengl::FunctionWrapper::wrDeleteTextures(__VA_ARGS__) +#define glGenTextures(...) opengl::FunctionWrapper::wrGenTextures(__VA_ARGS__) +#define glTexParameterf(...) opengl::FunctionWrapper::wrTexParameterf(__VA_ARGS__) +#define glActiveTexture(...) opengl::FunctionWrapper::wrActiveTexture(__VA_ARGS__) +#define glBlendColor(...) opengl::FunctionWrapper::wrBlendColor(__VA_ARGS__) +#define glReadBuffer(...) opengl::FunctionWrapper::wrReadBuffer(__VA_ARGS__) +#define glFinish(...) opengl::FunctionWrapper::wrFinish(__VA_ARGS__) +#if defined(OS_ANDROID) +#define eglGetNativeClientBufferANDROID(...) opengl::FunctionWrapper::ewrGetNativeClientBufferANDROID(__VA_ARGS__) +#endif +#define glCreateShader(...) opengl::FunctionWrapper::wrCreateShader(__VA_ARGS__) +#define glCompileShader(...) opengl::FunctionWrapper::wrCompileShader(__VA_ARGS__) +#define glShaderSource(...) opengl::FunctionWrapper::wrShaderSource(__VA_ARGS__) +#define glCreateProgram(...) opengl::FunctionWrapper::wrCreateProgram(__VA_ARGS__) +#define glAttachShader(...) opengl::FunctionWrapper::wrAttachShader(__VA_ARGS__) +#define glLinkProgram(...) opengl::FunctionWrapper::wrLinkProgram(__VA_ARGS__) +#define glUseProgram(...) opengl::FunctionWrapper::wrUseProgram(__VA_ARGS__) +#define glGetUniformLocation(...) opengl::FunctionWrapper::wrGetUniformLocation(__VA_ARGS__) +#define glUniform1i(...) opengl::FunctionWrapper::wrUniform1i(__VA_ARGS__) +#define glUniform1f(...) opengl::FunctionWrapper::wrUniform1f(__VA_ARGS__) +#define glUniform2f(...) opengl::FunctionWrapper::wrUniform2f(__VA_ARGS__) +#define glUniform2i(...) opengl::FunctionWrapper::wrUniform2i(__VA_ARGS__) +#define glUniform4i(...) opengl::FunctionWrapper::wrUniform4i(__VA_ARGS__) + +#define glUniform4f(...) opengl::FunctionWrapper::wrUniform4f(__VA_ARGS__) +#define glUniform3fv(...) opengl::FunctionWrapper::wrUniform3fv(__VA_ARGS__) +#define glUniform4fv(...) opengl::FunctionWrapper::wrUniform4fv(__VA_ARGS__) +#define glDetachShader(...) opengl::FunctionWrapper::wrDetachShader(__VA_ARGS__) +#define glDeleteShader(...) opengl::FunctionWrapper::wrDeleteShader(__VA_ARGS__) +#define glDeleteProgram(...) opengl::FunctionWrapper::wrDeleteProgram(__VA_ARGS__) +#define glGetProgramInfoLog(...) opengl::FunctionWrapper::wrGetProgramInfoLog(__VA_ARGS__) +#define glGetShaderInfoLog(...) opengl::FunctionWrapper::wrGetShaderInfoLog(__VA_ARGS__) +#define glGetShaderiv(...) opengl::FunctionWrapper::wrGetShaderiv(__VA_ARGS__) +#define glGetProgramiv(...) opengl::FunctionWrapper::wrGetProgramiv(__VA_ARGS__) + +#define glEnableVertexAttribArray(...) opengl::FunctionWrapper::wrEnableVertexAttribArray(__VA_ARGS__) +#define glDisableVertexAttribArray(...) opengl::FunctionWrapper::wrDisableVertexAttribArray(__VA_ARGS__) +#define glVertexAttribPointer(...) opengl::FunctionWrapper::wrVertexAttribPointer(__VA_ARGS__) +#define glBindAttribLocation(...) opengl::FunctionWrapper::wrBindAttribLocation(__VA_ARGS__) +#define glVertexAttrib1f(...) opengl::FunctionWrapper::wrVertexAttrib1f(__VA_ARGS__) +#define glVertexAttrib4f(...) opengl::FunctionWrapper::wrVertexAttrib4f(__VA_ARGS__) +#define glVertexAttrib4fv(...) opengl::FunctionWrapper::wrVertexAttrib4fv(__VA_ARGS__) + +#define glDepthRangef(...) opengl::FunctionWrapper::wrDepthRangef(__VA_ARGS__) +#define glClearDepthf(...) opengl::FunctionWrapper::wrClearDepthf(__VA_ARGS__) + +#define glBindBuffer(...) opengl::FunctionWrapper::wrBindBuffer(__VA_ARGS__) +#define glBindFramebuffer(...) opengl::FunctionWrapper::wrBindFramebuffer(__VA_ARGS__) +#define glBindRenderbuffer(...) opengl::FunctionWrapper::wrBindRenderbuffer(__VA_ARGS__) +#define glDrawBuffers(...) opengl::FunctionWrapper::wrDrawBuffers(__VA_ARGS__) +#define glGenFramebuffers(...) opengl::FunctionWrapper::wrGenFramebuffers(__VA_ARGS__) +#define glDeleteFramebuffers(...) opengl::FunctionWrapper::wrDeleteFramebuffers(__VA_ARGS__) +#define glFramebufferTexture2D(...) opengl::FunctionWrapper::wrFramebufferTexture2D(__VA_ARGS__) +#define glTexImage2DMultisample(...) opengl::FunctionWrapper::wrTexImage2DMultisample(__VA_ARGS__) +#define glTexStorage2DMultisample(...) opengl::FunctionWrapper::wrTexStorage2DMultisample(__VA_ARGS__) +#define glGenRenderbuffers(...) opengl::FunctionWrapper::wrGenRenderbuffers(__VA_ARGS__) +#define glRenderbufferStorage(...) opengl::FunctionWrapper::wrRenderbufferStorage(__VA_ARGS__) +#define glDeleteRenderbuffers(...) opengl::FunctionWrapper::wrDeleteRenderbuffers(__VA_ARGS__) +#define glFramebufferRenderbuffer(...) opengl::FunctionWrapper::wrFramebufferRenderbuffer(__VA_ARGS__) +#define glCheckFramebufferStatus(...) opengl::FunctionWrapper::wrCheckFramebufferStatus(__VA_ARGS__) +#define glBlitFramebuffer(...) opengl::FunctionWrapper::wrBlitFramebuffer(__VA_ARGS__) +#define glGenVertexArrays(...) opengl::FunctionWrapper::wrGenVertexArrays(__VA_ARGS__) +#define glBindVertexArray(...) opengl::FunctionWrapper::wrBindVertexArray(__VA_ARGS__) +#define glDeleteVertexArrays(...) opengl::FunctionWrapper::wrDeleteVertexArrays(__VA_ARGS__); +#define glGenBuffers(...) opengl::FunctionWrapper::wrGenBuffers(__VA_ARGS__) +#define glBufferData(...) opengl::FunctionWrapper::wrBufferData(__VA_ARGS__) +#define glMapBuffer(...) opengl::FunctionWrapper::wrMapBuffer(__VA_ARGS__) +#define glMapBufferRange(...) opengl::FunctionWrapper::wrMapBufferRange(__VA_ARGS__) +#define glUnmapBuffer(...) opengl::FunctionWrapper::wrUnmapBuffer(__VA_ARGS__) +#define glDeleteBuffers(...) opengl::FunctionWrapper::wrDeleteBuffers(__VA_ARGS__) +#define glBindImageTexture(...) opengl::FunctionWrapper::wrBindImageTexture(__VA_ARGS__) +#define glMemoryBarrier(...) opengl::FunctionWrapper::wrMemoryBarrier(__VA_ARGS__) +#define glGetStringi(...) opengl::FunctionWrapper::wrGetStringi(__VA_ARGS__) +#define glInvalidateFramebuffer(...) opengl::FunctionWrapper::wrInvalidateFramebuffer(__VA_ARGS__) +#define glBufferStorage(...) opengl::FunctionWrapper::wrBufferStorage(__VA_ARGS__) +#define glFenceSync(...) opengl::FunctionWrapper::wrFenceSync(__VA_ARGS__) +#define glClientWaitSync(...) opengl::FunctionWrapper::wrClientWaitSync(__VA_ARGS__) +#define glDeleteSync(...) opengl::FunctionWrapper::wrDeleteSync(__VA_ARGS__) + +#define glGetUniformBlockIndex(...) opengl::FunctionWrapper::wrGetUniformBlockIndex(__VA_ARGS__) +#define glUniformBlockBinding(...) opengl::FunctionWrapper::wrUniformBlockBinding(__VA_ARGS__) +#define glGetActiveUniformBlockiv(...) opengl::FunctionWrapper::wrGetActiveUniformBlockiv(__VA_ARGS__) +#define glGetUniformIndices(...) opengl::FunctionWrapper::wrGetUniformIndices(__VA_ARGS__) +#define glGetActiveUniformsiv(...) opengl::FunctionWrapper::wrGetActiveUniformsiv(__VA_ARGS__) +#define glBindBufferBase(...) opengl::FunctionWrapper::wrBindBufferBase(__VA_ARGS__) +#define glBufferSubData(...) opengl::FunctionWrapper::wrBufferSubData(__VA_ARGS__) + +#define glGetProgramBinary(...) opengl::FunctionWrapper::wrGetProgramBinary(__VA_ARGS__) +#define glProgramBinary(...) opengl::FunctionWrapper::wrProgramBinary(__VA_ARGS__) +#define glProgramParameteri(...) opengl::FunctionWrapper::wrProgramParameteri(__VA_ARGS__) + +#define glTexStorage2D(...) opengl::FunctionWrapper::wrTexStorage2D(__VA_ARGS__) +#define glTextureStorage2D(...) opengl::FunctionWrapper::wrTextureStorage2D(__VA_ARGS__) +#define glTextureSubImage2D(...) opengl::FunctionWrapper::wrTextureSubImage2D(__VA_ARGS__) +#define glTextureStorage2DMultisample(...) opengl::FunctionWrapper::wrTextureStorage2DMultisample(__VA_ARGS__) +#define glTextureParameteri(...) opengl::FunctionWrapper::wrTextureParameteri(__VA_ARGS__) +#define glTextureParameterf(...) opengl::FunctionWrapper::wrTextureParameterf(__VA_ARGS__) +#define glCreateTextures(...) opengl::FunctionWrapper::wrCreateTextures(__VA_ARGS__) +#define glCreateBuffers(...) opengl::FunctionWrapper::wrCreateBuffers(__VA_ARGS__) +#define glCreateFramebuffers(...) opengl::FunctionWrapper::wrCreateFramebuffers(__VA_ARGS__) +#define glNamedFramebufferTexture(...) opengl::FunctionWrapper::wrNamedFramebufferTexture(__VA_ARGS__) +#define glDrawRangeElementsBaseVertex(...) opengl::FunctionWrapper::wrDrawRangeElementsBaseVertex(__VA_ARGS__) +#define glFlushMappedBufferRange(...) opengl::FunctionWrapper::wrFlushMappedBufferRange(__VA_ARGS__) +#define glTextureBarrier(...) opengl::FunctionWrapper::wrTextureBarrier(__VA_ARGS__) +#define glTextureBarrierNV(...) opengl::FunctionWrapper::wrTextureBarrierNV(__VA_ARGS__) +#define glClearBufferfv(...) opengl::FunctionWrapper::wrClearBufferfv(__VA_ARGS__) +#define glEnablei(...) opengl::FunctionWrapper::wrEnablei(__VA_ARGS__) +#define glDisablei(...) opengl::FunctionWrapper::wrDisablei(__VA_ARGS__) +#define glEGLImageTargetTexture2DOES(...) opengl::FunctionWrapper::wrEGLImageTargetTexture2DOES(__VA_ARGS__) + +#include "Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h" #endif // GLFUNCTIONS_H diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index 55a6b0bd6..b87239e73 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -2444,7 +2444,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine glAttachShader(program, bUseTextures ? m_vertexShaderTexturedTriangle : m_vertexShaderTriangle); glAttachShader(program, fragmentShader); if (CombinerInfo::get().isShaderCacheSupported()) { - if (IS_GL_FUNCTION_VALID(glProgramParameteri)) + if (IS_GL_FUNCTION_VALID(ProgramParameteri)) glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); } glLinkProgram(program); diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/BlockingQueue.h b/src/Graphics/OpenGLContext/ThreadedOpenGl/BlockingQueue.h new file mode 100644 index 000000000..516f0dec0 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/BlockingQueue.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include + +template > +class BlockingQueue +{ +private: + std::mutex m_mutex; + std::condition_variable m_condition; + Container m_queue; +public: + void push(T const& value) { + { + std::unique_lock lock(this->m_mutex); + m_queue.push_front(value); + } + this->m_condition.notify_one(); + } + + void pushBack(T const& value) { + { + std::unique_lock lock(this->m_mutex); + m_queue.push_back(value); + } + this->m_condition.notify_one(); + } + + T pop() { + std::unique_lock lock(this->m_mutex); + this->m_condition.wait(lock, [this]{ return !this->m_queue.empty(); }); + T rc(std::move(this->m_queue.back())); + this->m_queue.pop_back(); + return rc; + } + bool tryPop (T & v, std::chrono::milliseconds dur) { + std::unique_lock lock(this->m_mutex); + if (!this->m_condition.wait_for(lock, dur, [this]{ return !this->m_queue.empty(); })) { + return false; + } + v = std::move(this->m_queue.back()); + this->m_queue.pop_back(); + return true; + } + int size() { + return m_queue.size(); + } +}; diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.cpp b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.cpp new file mode 100644 index 000000000..6dbf7f694 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.cpp @@ -0,0 +1,60 @@ +#include "opengl_Command.h" +#include "Graphics/OpenGLContext/GLFunctions.h" + +namespace opengl { + +void OpenGlCommand::performCommandSingleThreaded() { + commandToExecute(); + + setInUse(false); +#ifdef GL_DEBUG + if (m_isGlCommand) { + auto error = ptrGetError(); + if (error != GL_NO_ERROR) { + std::stringstream errorString; + errorString << " OpenGL error: 0x" << std::hex << error << ", on function: " << m_functionName; + LOG(LOG_ERROR, errorString.str().c_str()); + throw std::runtime_error(errorString.str().c_str()); + } + } +#endif +} + +void OpenGlCommand::performCommand() { + std::unique_lock lock(m_condvarMutex); + performCommandSingleThreaded(); + if (m_synced) { +#ifdef GL_DEBUG + if (m_logIfSynced) { + std::stringstream errorString; + errorString << " Executing synced: " << m_functionName; + LOG(LOG_VERBOSE, errorString.str().c_str()); + } +#endif + m_executed = true; + m_condition.notify_all(); + } +} + +void OpenGlCommand::waitOnCommand() { + std::unique_lock lock(m_condvarMutex); + + if (m_synced && !m_executed) { + m_condition.wait(lock, [this] { return m_executed; }); + } + + m_executed = false; +} + +OpenGlCommand::OpenGlCommand(bool _synced, bool _logIfSynced, const std::string &_functionName, + bool _isGlCommand) : + m_synced(_synced), m_executed(false) +#ifdef GL_DEBUG +, m_logIfSynced(_logIfSynced) + , m_functionName(std::move(_functionName)) + , m_isGlCommand(_isGlCommand) +#endif +{ +} + +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.h b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.h new file mode 100644 index 000000000..f0202870b --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include "opengl_ObjectPool.h" +#include + +namespace opengl { + +class OpenGlCommand : public PoolObject { +public: + void performCommandSingleThreaded(); + + void performCommand(); + + void waitOnCommand(); + +protected: + OpenGlCommand(bool _synced, bool _logIfSynced, const std::string &_functionName, + bool _isGlCommand = true); + + virtual void commandToExecute() = 0; + + template + static std::shared_ptr getFromPool(int _poolId) { + auto poolObject = OpenGlCommandPool::get().getAvailableObject(_poolId); + if (poolObject == nullptr) { + poolObject = std::shared_ptr(new CoomandType); + OpenGlCommandPool::get().addObjectToPool(_poolId, poolObject); + } + + poolObject->setInUse(true); + return std::static_pointer_cast(poolObject); + } + +protected: + +#ifdef GL_DEBUG + const bool m_logIfSynced; + const std::string m_functionName; + const bool m_isGlCommand; +#endif + +private: + std::atomic m_synced; + bool m_executed; + std::mutex m_condvarMutex; + std::condition_variable m_condition; +}; +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.cpp b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.cpp new file mode 100644 index 000000000..e732ff77e --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.cpp @@ -0,0 +1,85 @@ +#include "opengl_ObjectPool.h" + +namespace opengl { + + +PoolObject::PoolObject() : + m_inUse(false), m_poolId(0), m_objectId(0) { +} + +bool PoolObject::isInUse() { + return m_inUse; +} + +void PoolObject::setInUse(bool _inUse) { + m_inUse = _inUse; +} + +int PoolObject::getPoolId() { + return m_poolId; +} + +void PoolObject::setPoolId(int _poolId) { + m_poolId = _poolId; +} + +int PoolObject::getObjectId() { + return m_objectId; +} + +void PoolObject::setObjectId(int _objectId) { + m_objectId = _objectId; +} + + +OpenGlCommandPool &OpenGlCommandPool::get() { + static OpenGlCommandPool commandPool; + return commandPool; +} + +int OpenGlCommandPool::getNextAvailablePool() { + m_objectPool.push_back(std::vector>()); + m_objectPoolIndex.push_back(0); + return m_objectPool.size() - 1; +} + +std::shared_ptr OpenGlCommandPool::getAvailableObject(int _poolId) { + auto ¤tPool = m_objectPool[_poolId]; + auto ¤tIndex = m_objectPoolIndex[_poolId]; + + if (currentPool.empty()) { + return nullptr; + } else if (!currentPool[currentIndex]->isInUse()) { + int objectId = currentIndex; + ++currentIndex; + + if (currentIndex == currentPool.size()) { + currentIndex = 0; + } + + return currentPool[objectId]; + + } else { + bool found = false; + unsigned int index; + //Not found in most common case, so go ahead and search + for (index = currentIndex; index < currentPool.size() && !found; ++index) { + found = !currentPool[index]->isInUse(); + } + + if (found) { + --index; + currentIndex = index; + return currentPool[index]; + } else { + return nullptr; + } + } +} + +void OpenGlCommandPool::addObjectToPool(int _poolId, std::shared_ptr _object) { + _object->setPoolId(_poolId); + _object->setObjectId(m_objectPool[_poolId].size()); + m_objectPool[_poolId].push_back(_object); +} +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.h b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.h new file mode 100644 index 000000000..f4fcd5018 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + + +namespace opengl { + +class PoolObject { +public: + + PoolObject(); + + bool isInUse(); + void setInUse(bool _inUse); + + int getPoolId(); + + void setPoolId(int _poolId); + + int getObjectId(); + + void setObjectId(int _objectId); +private: + + bool m_inUse; + int m_poolId; + int m_objectId; +}; + +class OpenGlCommandPool +{ +public: + static OpenGlCommandPool& get(); + + int getNextAvailablePool(); + + std::shared_ptr getAvailableObject(int _poolId); + + void addObjectToPool(int _poolId, std::shared_ptr _object); + +private: + std::vector>> m_objectPool; + std::vector m_objectPoolIndex; +}; +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.cpp b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.cpp new file mode 100644 index 000000000..9a0075bb8 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.cpp @@ -0,0 +1,23 @@ +#include "opengl_WrappedFunctions.h" + +namespace opengl { + + std::vector GlDrawArraysUnbufferedCommand::m_attribsData; + std::vector GlDrawElementsUnbufferedCommand::m_attribsData; + GLenum GlMapBufferRangeWriteAsyncCommand::m_targetTemp; + GLintptr GlMapBufferRangeWriteAsyncCommand::m_offsetTemp; + u32 GlMapBufferRangeWriteAsyncCommand::m_lengthTemp; + GLbitfield GlMapBufferRangeWriteAsyncCommand::m_accessTemp = 0; + std::unordered_map>> GlMapBufferRangeWriteAsyncCommand::m_TempData; + splicer::ObjectPool> GlMapBufferRangeWriteAsyncCommand::m_vectorPool(128); + std::unordered_map>> GlMapBufferRangeReadAsyncCommand::m_data; + std::mutex GlMapBufferRangeReadAsyncCommand::m_mapMutex; + std::unordered_map GlVertexAttribPointerManager::m_vertexAttributePointers; + const void* GlVertexAttribPointerManager::smallestDataPtr = nullptr; + std::unordered_map GlVertexAttribPointerManager::m_vertexAttributePointersRender; + const void* GlVertexAttribPointerManager::smallestDataPtrRender = nullptr; + splicer::ObjectPool> GlVertexAttribPointerManager::m_vectorPool(128); + std::unordered_map GlBindBufferCommand::m_boundBuffersRender; + std::unordered_map GlBindBufferCommand::m_boundBuffers; + GLuint GlReadPixelsAsyncCommand::m_readPixelsBoundBuffer = 0; +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h new file mode 100644 index 000000000..ed8105f1b --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h @@ -0,0 +1,4937 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "BlockingQueue.h" +#include "Graphics/OpenGLContext/GLFunctions.h" +#include "Graphics/OpenGLContext/opengl_Attributes.h" +#include +#include +#include +#include "opengl_Command.h" +#include "splice-pool.hpp" + +#ifdef MUPENPLUSAPI +#include +#else +#include +#endif + +namespace opengl { + + class GlBlendFuncCommand : public OpenGlCommand + { + public: + GlBlendFuncCommand() : + OpenGlCommand(false, false, "glBlendFunc") + { + } + + static std::shared_ptr get(GLenum sfactor, GLenum dfactor) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(sfactor, dfactor); + return ptr; + } + + void commandToExecute() override + { + ptrBlendFunc(m_sfactor, m_dfactor); + } + private: + void set(GLenum sfactor, GLenum dfactor) + { + m_sfactor = sfactor; + m_dfactor = dfactor; + } + + GLenum m_sfactor; + GLenum m_dfactor; + }; + + class GlPixelStoreiCommand : public OpenGlCommand + { + public: + GlPixelStoreiCommand() : + OpenGlCommand(false, false, "glPixelStorei") + { + } + + static std::shared_ptr get(GLenum pname, GLint param) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(pname, param); + return ptr; + } + + void commandToExecute() override + { + ptrPixelStorei(m_pname, m_param); + } + + private: + void set(GLenum pname, GLint param) + { + m_pname = pname; + m_param = param; + } + + GLenum m_pname; + GLint m_param; + }; + + class GlClearColorCommand : public OpenGlCommand + { + public: + GlClearColorCommand() : + OpenGlCommand(false, false, "glClearColor") + { + + } + + static std::shared_ptr get(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(red, green, blue, alpha); + return ptr; + } + + void commandToExecute() override + { + ptrClearColor(m_red, m_green, m_blue, m_alpha); + } + private: + void set(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + m_red = red; + m_green = green; + m_blue = blue; + m_alpha = alpha; + } + + GLfloat m_red; + GLfloat m_green; + GLfloat m_blue; + GLfloat m_alpha; + }; + + class GlCullFaceCommand : public OpenGlCommand + { + public: + GlCullFaceCommand() : + OpenGlCommand(false, false, "glCullFace") + { + } + + static std::shared_ptr get(GLenum mode) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mode); + return ptr; + } + + void commandToExecute() override + { + ptrCullFace(m_mode); + } + + private: + void set(GLenum mode) + { + m_mode = mode; + } + + GLenum m_mode; + }; + + class GlDepthFuncCommand : public OpenGlCommand + { + public: + GlDepthFuncCommand() : + OpenGlCommand(false, false, "glDepthFunc") + { + } + + static std::shared_ptr get(GLenum func) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(func); + return ptr; + } + + void commandToExecute() override + { + ptrDepthFunc(m_func); + } + private: + void set(GLenum func) + { + m_func = func; + } + + GLenum m_func; + }; + + class GlDepthMaskCommand : public OpenGlCommand + { + public: + GlDepthMaskCommand() : + OpenGlCommand(false, false, "glDepthMask") + { + + } + + static std::shared_ptr get(GLboolean flag) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(flag); + return ptr; + } + + void commandToExecute() override + { + ptrDepthMask(m_flag); + } + private: + void set(GLboolean flag) + { + m_flag = flag; + } + + GLboolean m_flag; + }; + + class GlDisableCommand : public OpenGlCommand + { + public: + GlDisableCommand() : + OpenGlCommand(false, false, "glDisable") + { + } + + static std::shared_ptr get(GLenum cap) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(cap); + return ptr; + } + + void commandToExecute() override + { + ptrDisable(m_cap); + } + private: + void set(GLenum cap) + { + m_cap = cap; + } + + GLenum m_cap; + }; + + class GlEnableCommand : public OpenGlCommand + { + public: + GlEnableCommand() : + OpenGlCommand(false, false, "glEnable") + { + } + + static std::shared_ptr get(GLenum cap) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(cap); + return ptr; + } + + void commandToExecute() override + { + ptrEnable(m_cap); + } + private: + void set(GLenum cap) + { + m_cap = cap; + } + + GLenum m_cap; + }; + + class GlDisableiCommand : public OpenGlCommand + { + public: + GlDisableiCommand() : + OpenGlCommand(false, false, "glDisablei") + { + } + + static std::shared_ptr get(GLenum target, GLuint index) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, index); + return ptr; + } + + void commandToExecute() override + { + ptrDisablei(m_target, m_index); + } + private: + void set(GLenum target, GLuint index) + { + m_target = target; + m_index = index; + } + + GLenum m_target; + GLuint m_index; + }; + + class GlEnableiCommand : public OpenGlCommand + { + public: + GlEnableiCommand() : + OpenGlCommand(false, false, "glEnablei") + { + } + + static std::shared_ptr get(GLenum target, GLuint index) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, index); + return ptr; + } + + void commandToExecute() override + { + ptrEnablei(m_target, m_index); + } + private: + void set(GLenum target, GLuint index) + { + m_target = target; + m_index = index; + } + + GLenum m_target; + GLuint m_index; + }; + + class GlPolygonOffsetCommand : public OpenGlCommand + { + public: + GlPolygonOffsetCommand() : + OpenGlCommand(false, false, "glPolygonOffset") + { + } + + static std::shared_ptr get(GLfloat factor, GLfloat units) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(factor, units); + return ptr; + } + + void commandToExecute() override + { + ptrPolygonOffset(m_factor, m_units); + } + private: + void set(GLfloat factor, GLfloat units) + { + m_factor = factor; + m_units = units; + } + + GLfloat m_factor; + GLfloat m_units; + }; + + class GlScissorCommand : public OpenGlCommand + { + public: + GlScissorCommand() : + OpenGlCommand(false, false, "glScissor") + { + } + + static std::shared_ptr get(GLint x, GLint y, GLsizei width, GLsizei height) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(x, y, width, height); + return ptr; + } + + void commandToExecute() override + { + ptrScissor(m_x, m_y, m_width, m_height); + } + private: + void set(GLint x, GLint y, GLsizei width, GLsizei height) + { + m_x = x; + m_y = y; + m_width = width; + m_height = height; + } + + GLint m_x; + GLint m_y; + GLsizei m_width; + GLsizei m_height; + }; + + class GlViewportCommand : public OpenGlCommand + { + public: + GlViewportCommand() : + OpenGlCommand(false, false, "glViewport") + { + } + + static std::shared_ptr get(GLint x, GLint y, GLsizei width, GLsizei height) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(x, y, width, height); + return ptr; + } + + void commandToExecute() override + { + ptrViewport(m_x, m_y, m_width, m_height); + } + private: + void set(GLint x, GLint y, GLsizei width, GLsizei height) + { + m_x = x; + m_y = y; + m_width = width; + m_height = height; + } + + GLint m_x; + GLint m_y; + GLsizei m_width; + GLsizei m_height; + }; + + class GlBindTextureCommand : public OpenGlCommand + { + public: + GlBindTextureCommand() : + OpenGlCommand(false, false, "glBindTexture") + { + } + + static std::shared_ptr get(GLenum target, GLuint texture) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, texture); + return ptr; + } + + void commandToExecute() override + { + ptrBindTexture(m_target, m_texture); + } + private: + void set(GLenum target, GLuint texture) + { + m_target = target; + m_texture = texture; + } + + GLenum m_target; + GLuint m_texture; + }; + + class GlTexImage2DCommand : public OpenGlCommand + { + public: + GlTexImage2DCommand() : + OpenGlCommand(false, false, "glTexImage2D") + { + } + + static std::shared_ptr get(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, std::unique_ptr pixels) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, level, internalformat, width, height, border, format, type, std::move(pixels)); + return ptr; + } + + void commandToExecute() override + { + ptrTexImage2D(m_target, m_level, m_internalformat, m_width, m_height, m_border, m_format, m_type, + m_pixels.get()); + } + private: + void set(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, std::unique_ptr pixels) + { + m_target = target; + m_level = level; + m_internalformat = internalformat; + m_width = width; + m_height = height; + m_border = border; + m_format = format; + m_type = type; + m_pixels = std::move(pixels); + } + + GLenum m_target; + GLint m_level; + GLint m_internalformat; + GLsizei m_width; + GLsizei m_height; + GLint m_border; + GLenum m_format; + GLenum m_type; + std::unique_ptr m_pixels; + }; + + class GlTexParameteriCommand : public OpenGlCommand + { + public: + GlTexParameteriCommand() : + OpenGlCommand(false, false, "glTexParameteri") + { + } + + static std::shared_ptr get(GLenum target, GLenum pname, GLint param) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, pname, param); + return ptr; + } + + void commandToExecute() override + { + ptrTexParameteri(m_target, m_pname, m_param); + } + private: + void set(GLenum target, GLenum pname, GLint param) + { + m_target = target; + m_pname = pname; + m_param = param; + } + + GLenum m_target; + GLenum m_pname; + GLint m_param; + }; + + class GlGetIntegervCommand : public OpenGlCommand + { + public: + GlGetIntegervCommand() : + OpenGlCommand(true, false, "glGetIntegerv") + { + } + + static std::shared_ptr get(GLenum pname, GLint* data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(pname, data); + return ptr; + } + + void commandToExecute() override + { + ptrGetIntegerv(m_pname, m_data); + } + private: + void set(GLenum pname, GLint* data) + { + m_pname = pname; + m_data = data; + } + + GLenum m_pname; + GLint* m_data; + }; + + class GlGetStringCommand : public OpenGlCommand + { + public: + GlGetStringCommand() : + OpenGlCommand(true, false, "glGetString") + { + } + + static std::shared_ptr get(GLenum name, const GLubyte*& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(name, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetString(m_name); + } + private: + void set(GLenum name, const GLubyte*& returnValue) + { + m_name = name; + m_returnValue = &returnValue; + } + + GLenum m_name; + const GLubyte** m_returnValue; + }; + + class GlReadPixelsCommand : public OpenGlCommand + { + public: + GlReadPixelsCommand() : + OpenGlCommand(true, true, "glReadPixels") + { + } + + static std::shared_ptr get(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(x, y, width, height, format, type, pixels); + return ptr; + } + + void commandToExecute() override + { + ptrReadPixels(m_x, m_y, m_width, m_height, m_format, m_type, m_pixels); + } + private: + void set(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) + { + m_x = x; + m_y = y; + m_width = width; + m_height = height; + m_format = format; + m_type = type; + m_pixels = pixels; + } + + GLint m_x; + GLint m_y; + GLsizei m_width; + GLsizei m_height; + GLenum m_format; + GLenum m_type; + void* m_pixels; + }; + + class GlReadPixelsAsyncCommand : public OpenGlCommand + { + public: + GlReadPixelsAsyncCommand() : + OpenGlCommand(false, false, "GlReadPixelsAync") + { + } + + static std::shared_ptr get(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(x, y, width, height, format, type); + return ptr; + } + + void commandToExecute() override + { + ptrReadPixels(m_x, m_y, m_width, m_height, m_format, m_type, nullptr); + } + + static GLuint getBoundBuffer() + { + return m_readPixelsBoundBuffer; + } + + static void setBoundBuffer(GLuint buffer) + { + m_readPixelsBoundBuffer = buffer; + } + + private: + void set(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type) + { + m_x = x; + m_y = y; + m_width = width; + m_height = height; + m_format = format; + m_type = type; + } + + GLint m_x; + GLint m_y; + GLsizei m_width; + GLsizei m_height; + GLenum m_format; + GLenum m_type; + static GLuint m_readPixelsBoundBuffer; + }; + + class GlTexSubImage2DUnbufferedCommand : public OpenGlCommand + { + public: + GlTexSubImage2DUnbufferedCommand() : + OpenGlCommand(false, false, "glTexSubImage2D") + { + } + + static std::shared_ptr get(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, std::unique_ptr pixels) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, level, xoffset, yoffset, width, height, format, type, std::move(pixels)); + return ptr; + } + + void commandToExecute() override + { + ptrTexSubImage2D(m_target, m_level, m_xoffset, m_yoffset, m_width, m_height, m_format, m_type, m_pixels.get()); + } + private: + void set(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, std::unique_ptr pixels) + { + m_target = target; + m_level = level; + m_xoffset = xoffset; + m_yoffset = yoffset; + m_width = width; + m_height = height; + m_format = format; + m_type = type; + m_pixels = std::move(pixels); + } + + GLenum m_target; + GLint m_level; + GLint m_xoffset; + GLint m_yoffset; + GLsizei m_width; + GLsizei m_height; + GLenum m_format; + GLenum m_type; + std::unique_ptr m_pixels; + }; + + class GlDrawArraysCommand : public OpenGlCommand + { + public: + GlDrawArraysCommand() : + OpenGlCommand(false, false, "glDrawArrays") + { + } + + static std::shared_ptr get(GLenum mode, GLint first, GLsizei count) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mode, first, count); + return ptr; + } + + void commandToExecute() override + { + ptrDrawArrays(m_mode, m_first, m_count); + } + private: + void set(GLenum mode, GLint first, GLsizei count) + { + m_mode = mode; + m_first = first; + m_count = count; + } + + GLenum m_mode; + GLint m_first; + GLsizei m_count; + }; + + class GlVertexAttribPointerManager + { + public: + struct VertexAttributeData + { + GLuint m_index; + GLint m_size; + GLenum m_type; + GLboolean m_normalized; + GLsizei m_stride; + const void* m_pointer; + bool m_enabled; + bool m_updated = false; + }; + + static void enableVertexAttributeIndexRender(unsigned int index) + { + VertexAttributeData& attributeData = m_vertexAttributePointersRender[index]; + attributeData.m_enabled = true; + + updatedSmallestPtrRender(); + } + + static void disableVertexAttributeIndexRender(unsigned int index) + { + VertexAttributeData& attributeData = m_vertexAttributePointersRender[index]; + attributeData.m_enabled = false; + + updatedSmallestPtrRender(); + } + + static std::unordered_map& getVertexAttributesRender() + { + return m_vertexAttributePointersRender; + } + + static void updateRender(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) + { + VertexAttributeData &vertexAttributeData = m_vertexAttributePointersRender[index]; + vertexAttributeData.m_index = index; + vertexAttributeData.m_size = size; + vertexAttributeData.m_type = type; + vertexAttributeData.m_normalized = normalized; + vertexAttributeData.m_stride = stride; + vertexAttributeData.m_pointer = pointer; + vertexAttributeData.m_updated = true; + + updatedSmallestPtrRender(); + } + + static const char* getSmallestPtrRender() { + return reinterpret_cast(smallestDataPtrRender); + } + + static void enableVertexAttributeIndex(unsigned int index) + { + VertexAttributeData& attributeData = m_vertexAttributePointers[index]; + attributeData.m_enabled = true; + + updatedSmallestPtr(); + } + + static void disableVertexAttributeIndex(int index) + { + VertexAttributeData& attributeData = m_vertexAttributePointers[index]; + attributeData.m_enabled = false; + + updatedSmallestPtr(); + } + + static int getStride() + { + int stride = 0; + for (auto& data : m_vertexAttributePointers) { + if (data.second.m_pointer && data.second.m_enabled) { + stride = data.second.m_stride; + break; + } + } + + return stride; + } + + static void update(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) + { + VertexAttributeData &vertexAttributeData = m_vertexAttributePointers[index]; + vertexAttributeData.m_index = index; + vertexAttributeData.m_size = size; + vertexAttributeData.m_type = type; + vertexAttributeData.m_normalized = normalized; + vertexAttributeData.m_stride = stride; + vertexAttributeData.m_pointer = pointer; + + updatedSmallestPtr(); + } + + static const char* getSmallestPtr() { + return reinterpret_cast(smallestDataPtr); + } + + static splicer::Node>* getVectorFromPool() { + return m_vectorPool.acquireOne().release(); + } + + static void releaseVectorFromPool(splicer::Node>* node) { + m_vectorPool.release(node); + } + + private: + static void updatedSmallestPtrRender() + { + smallestDataPtrRender = nullptr; + + for (auto& data : m_vertexAttributePointersRender) { + if (data.second.m_pointer && data.second.m_enabled && (smallestDataPtrRender == nullptr || data.second.m_pointer < smallestDataPtrRender)) { + smallestDataPtrRender = data.second.m_pointer; + } + } + } + + static void updatedSmallestPtr() + { + smallestDataPtr = nullptr; + + for (auto& data : m_vertexAttributePointers) { + if (data.second.m_pointer && data.second.m_enabled && (smallestDataPtr == nullptr || data.second.m_pointer < smallestDataPtr)) { + smallestDataPtr = data.second.m_pointer; + } + } + } + + static std::unordered_map m_vertexAttributePointersRender; + static const void* smallestDataPtrRender; + + static std::unordered_map m_vertexAttributePointers; + static const void* smallestDataPtr; + + static splicer::ObjectPool> m_vectorPool; + }; + + class GlVertexAttribPointerUnbufferedCommand : public OpenGlCommand + { + public: + GlVertexAttribPointerUnbufferedCommand() : + OpenGlCommand(false, false, "glVertexAttribPointer") + { + } + + static std::shared_ptr get(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index, size, type, normalized, stride, pointer); + return ptr; + } + + void commandToExecute() override + { + GlVertexAttribPointerManager::updateRender(m_index, m_size, m_type, m_normalized, m_stride, m_pointer); + } + + private: + void set(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) + { + m_index = index; + m_size = size; + m_type = type; + m_normalized = normalized; + m_stride = stride; + m_pointer = pointer; + } + + GLuint m_index; + GLint m_size; + GLenum m_type; + GLboolean m_normalized; + GLsizei m_stride; + const void* m_pointer; + }; + + class GlDrawArraysUnbufferedCommand : public OpenGlCommand + { + public: + GlDrawArraysUnbufferedCommand() : + OpenGlCommand(false, false, "glDrawArraysUnbuffered") + { + static bool attribsDataInitialized = false; + + if (!attribsDataInitialized) { + m_attribsData.resize(2*1024*1024, 0); + attribsDataInitialized = true; + } + } + + static std::shared_ptr get(GLenum mode, GLint first, GLsizei count, splicer::Node>* data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mode, first, count, data); + return ptr; + } + + void commandToExecute() override + { + auto& vertexAttributes = GlVertexAttribPointerManager::getVertexAttributesRender(); + + for (auto& data : vertexAttributes) { + if (data.second.m_updated && data.second.m_enabled) { + + unsigned long ptrOffset = reinterpret_cast(data.second.m_pointer) - + GlVertexAttribPointerManager::getSmallestPtrRender(); + ptrVertexAttribPointer(data.second.m_index, data.second.m_size, data.second.m_type, data.second.m_normalized, + data.second.m_stride, reinterpret_cast(m_attribsData.data() + ptrOffset)); + data.second.m_updated = false; + } + } + std::copy_n(m_data->val().begin(), m_data->val().size(), m_attribsData.begin()); + ptrDrawArrays(m_mode, m_first, m_count); + GlVertexAttribPointerManager::releaseVectorFromPool(m_data); + } + private: + void set(GLenum mode, GLint first, GLsizei count, splicer::Node>* data) + { + m_mode = mode; + m_first = first; + m_count = count; + m_data = data; + } + + GLenum m_mode; + GLint m_first; + GLsizei m_count; + splicer::Node>* m_data; + static std::vector m_attribsData; + }; + + class GlGetErrorCommand : public OpenGlCommand + { + public: + GlGetErrorCommand() : + OpenGlCommand(true, true, "glGetError") + { + } + + static std::shared_ptr get(GLenum& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetError(); + } + private: + void set(GLenum& returnValue) + { + m_returnValue = &returnValue; + } + + GLenum* m_returnValue; + }; + + class GlDrawElementsUnbufferedCommand : public OpenGlCommand + { + public: + GlDrawElementsUnbufferedCommand() : + OpenGlCommand(false, false, "glDrawElementsUnbuffered") + { + static bool attribsDataInitialized = false; + + if (!attribsDataInitialized) { + m_attribsData.resize(2*1024*1024, 0); + attribsDataInitialized = true; + } + } + + static std::shared_ptr get(GLenum mode, GLsizei count, GLenum type, std::unique_ptr indices, + splicer::Node>* data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mode, count, type, std::move(indices), std::move(data)); + return ptr; + } + + void commandToExecute() override + { + auto& vertexAttributes = GlVertexAttribPointerManager::getVertexAttributesRender(); + int count = 0; + + for (auto& data : vertexAttributes) { + if (data.second.m_updated && data.second.m_enabled) { + unsigned long ptrOffset = reinterpret_cast(data.second.m_pointer) - + GlVertexAttribPointerManager::getSmallestPtrRender(); + ptrVertexAttribPointer(data.second.m_index, data.second.m_size, data.second.m_type, data.second.m_normalized, + data.second.m_stride, reinterpret_cast(m_attribsData.data() + ptrOffset)); + data.second.m_updated = false; + } + } + + std::copy_n(m_data->val().begin(), m_data->val().size(), m_attribsData.begin()); + ptrDrawElements(m_mode, m_count, m_type, m_indices.get()); + GlVertexAttribPointerManager::releaseVectorFromPool(m_data); + } + private: + void set(GLenum mode, GLsizei count, GLenum type, std::unique_ptr indices, + splicer::Node>* data) + { + m_mode = mode; + m_count = count; + m_type = type; + m_indices = std::move(indices); + m_data = data; + } + + GLenum m_mode; + GLsizei m_count; + GLenum m_type; + std::unique_ptr m_indices; + splicer::Node>* m_data; + static std::vector m_attribsData; + }; + + class GlLineWidthCommand : public OpenGlCommand + { + public: + GlLineWidthCommand() : + OpenGlCommand(false, false, "glLineWidth") + { + } + + static std::shared_ptr get(GLfloat width) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(width); + return ptr; + } + + void commandToExecute() override + { + ptrLineWidth(m_width); + } + private: + void set(GLfloat width) + { + m_width = width; + } + + GLfloat m_width; + }; + + class GlClearCommand : public OpenGlCommand + { + public: + GlClearCommand() : + OpenGlCommand(false, false, "glClear") + { + } + + static std::shared_ptr get(GLbitfield mask) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mask); + return ptr; + } + + void commandToExecute() override + { + ptrClear(m_mask); + } + private: + void set(GLbitfield mask) + { + m_mask = mask; + } + + GLbitfield m_mask; + }; + + class GlClearBufferfvCommand : public OpenGlCommand + { + public: + GlClearBufferfvCommand() : + OpenGlCommand(false, false, "glClearBufferfv") + { + } + + static std::shared_ptr get(GLenum buffer, GLint drawbuffer, std::unique_ptr value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(buffer, drawbuffer, std::move(value)); + return ptr; + } + + void commandToExecute() override + { + ptrClearBufferfv(m_buffer, m_drawbuffer, m_value.get()); + } + private: + void set(GLenum buffer, GLint drawbuffer, std::unique_ptr value) + { + m_buffer = buffer; + m_drawbuffer = drawbuffer; + m_value = std::move(value); + } + + GLenum m_buffer; + GLint m_drawbuffer; + std::unique_ptr m_value; + }; + + class GlGetFloatvCommand : public OpenGlCommand + { + public: + GlGetFloatvCommand() : + OpenGlCommand(true, false, "glGetFloatv") + { + } + + static std::shared_ptr get(GLenum pname, GLfloat* data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(pname, data); + return ptr; + } + + void commandToExecute() override + { + ptrGetFloatv(m_pname, m_data); + } + private: + void set(GLenum pname, GLfloat* data) + { + m_pname = pname; + m_data = data; + } + + GLenum m_pname; + GLfloat* m_data; + }; + + class GlDeleteTexturesCommand : public OpenGlCommand + { + public: + GlDeleteTexturesCommand() : + OpenGlCommand(false, false, "glDeleteTextures") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr textures) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(textures)); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteTextures(m_n, m_textures.get()); + } + private: + void set(GLsizei n, std::unique_ptr textures) + { + m_n = n; + m_textures = std::move(textures); + } + + GLsizei m_n; + std::unique_ptr m_textures; + }; + + class GlGenTexturesCommand : public OpenGlCommand + { + public: + GlGenTexturesCommand() : + OpenGlCommand(true, false, "glGenTextures") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* textures) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, textures); + return ptr; + } + + void commandToExecute() override + { + ptrGenTextures(m_n, m_textures); + } + private: + void set(GLsizei n, GLuint* textures) + { + m_n = n; + m_textures = textures; + } + + GLsizei m_n; + GLuint* m_textures; + }; + + class GlTexParameterfCommand : public OpenGlCommand + { + public: + GlTexParameterfCommand() : + OpenGlCommand(false, false, "glTexParameterf") + { + } + + static std::shared_ptr get(GLenum target, GLenum pname, GLfloat param) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, pname, param); + return ptr; + } + + void commandToExecute() override + { + ptrTexParameterf(m_target, m_pname, m_param); + } + private: + void set(GLenum target, GLenum pname, GLfloat param) + { + m_target = target; + m_pname = pname; + m_param = param; + } + + GLenum m_target; + GLenum m_pname; + GLfloat m_param; + }; + + class GlActiveTextureCommand : public OpenGlCommand + { + public: + GlActiveTextureCommand() : + OpenGlCommand(false, false, "glActiveTexture") + { + } + + static std::shared_ptr get(GLenum texture) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture); + return ptr; + } + + void commandToExecute() override + { + ptrActiveTexture(m_texture); + } + private: + void set(GLenum texture) + { + m_texture = texture; + } + + GLenum m_texture; + }; + + class GlBlendColorCommand : public OpenGlCommand + { + public: + GlBlendColorCommand() : + OpenGlCommand(false, false, "glBlendColor") + { + } + + static std::shared_ptr get(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(red, green, blue, alpha); + return ptr; + } + + void commandToExecute() override + { + ptrBlendColor(m_red, m_green, m_blue, m_alpha); + } + private: + void set(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + m_red = red; + m_green = green; + m_blue = blue; + m_alpha = alpha; + } + + GLfloat m_red; + GLfloat m_green; + GLfloat m_blue; + GLfloat m_alpha; + }; + + class GlReadBufferCommand : public OpenGlCommand + { + public: + GlReadBufferCommand() : + OpenGlCommand(false, false, "glReadBuffer") + { + } + + static std::shared_ptr get(GLenum src) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(src); + return ptr; + } + + void commandToExecute() override + { + ptrReadBuffer(m_src); + } + private: + void set(GLenum src) + { + m_src = src; + } + + GLenum m_src; + }; + + class GlCreateShaderCommand : public OpenGlCommand + { + public: + GlCreateShaderCommand() : + OpenGlCommand(true, true, "glCreateShader") + { + } + + static std::shared_ptr get(GLenum type, GLuint& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(type, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrCreateShader(m_type); + } + private: + void set(GLenum type, GLuint& returnValue) + { + m_type = type; + m_returnValue = &returnValue; + } + + GLenum m_type; + GLuint* m_returnValue; + }; + + class GlCompileShaderCommand : public OpenGlCommand + { + public: + GlCompileShaderCommand() : + OpenGlCommand(false, false, "glCompileShader") + { + } + + static std::shared_ptr get(GLuint shader) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(shader); + return ptr; + } + + void commandToExecute() override + { + ptrCompileShader(m_shader); + } + private: + void set(GLuint shader) + { + m_shader = shader; + } + + GLuint m_shader; + }; + + class GlShaderSourceCommand : public OpenGlCommand + { + public: + GlShaderSourceCommand() : + OpenGlCommand(false, false, "glShaderSource") + { + } + + static std::shared_ptr get(GLuint shader, std::vector& strings) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(shader, strings); + return ptr; + } + + void commandToExecute() override + { + const GLchar **stringData = new const GLchar*[m_strings.size()]; + for (unsigned int index = 0; index < m_strings.size(); ++index) { + stringData[index] = m_strings[index].data(); + } + + ptrShaderSource(m_shader, m_strings.size(), stringData, nullptr); + } + private: + void set(GLuint shader, std::vector& strings) + { + m_shader = shader; + m_strings = std::move(strings); + } + + GLuint m_shader; + std::vector m_strings; + }; + + class GlCreateProgramCommand : public OpenGlCommand + { + public: + GlCreateProgramCommand() : + OpenGlCommand(true, true, "glCreateProgram") + { + } + + static std::shared_ptr get(GLuint& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrCreateProgram(); + } + private: + void set(GLuint& returnValue) + { + m_returnValue = &returnValue; + } + + GLuint* m_returnValue; + }; + + class GlAttachShaderCommand : public OpenGlCommand + { + public: + GlAttachShaderCommand() : + OpenGlCommand(false, false, "glAttachShader") + { + } + + static std::shared_ptr get(GLuint program, GLuint shader) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, shader); + return ptr; + } + + void commandToExecute() override + { + ptrAttachShader(m_program, m_shader); + } + private: + void set(GLuint program, GLuint shader) + { + m_program = program; + m_shader = shader; + } + + GLuint m_program; + GLuint m_shader; + }; + + class GlLinkProgramCommand : public OpenGlCommand + { + public: + GlLinkProgramCommand() : + OpenGlCommand(false, false, "glLinkProgram") + { + } + + static std::shared_ptr get(GLuint program) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program); + return ptr; + } + + void commandToExecute() override + { + ptrLinkProgram(m_program); + } + private: + void set(GLuint program) + { + m_program = program; + } + + GLuint m_program; + }; + + class GlUseProgramCommand : public OpenGlCommand + { + public: + GlUseProgramCommand() : + OpenGlCommand(false, false, "glUseProgram") + { + } + + static std::shared_ptr get(GLuint program) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program); + return ptr; + } + + void commandToExecute() override + { + ptrUseProgram(m_program); + } + private: + void set(GLuint program) + { + m_program = program; + } + + GLuint m_program; + }; + + class GlGetUniformLocationCommand : public OpenGlCommand + { + public: + GlGetUniformLocationCommand() : + OpenGlCommand(true, true, "glGetUniformLocation") + { + } + + static std::shared_ptr get(GLuint program, const GLchar* name, GLint& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, name, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetUniformLocation(m_program, m_name); + } + private: + void set(GLuint program, const GLchar* name, GLint& returnValue) + { + m_program = program; + m_name = name; + m_returnValue = &returnValue; + } + + GLint* m_returnValue; + GLuint m_program; + const GLchar* m_name; + }; + + class GlUniform1iCommand : public OpenGlCommand + { + public: + GlUniform1iCommand() : + OpenGlCommand(false, false, "glUniform1i") + { + } + + static std::shared_ptr get(GLint location, GLint v0) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0); + return ptr; + } + + void commandToExecute() override + { + ptrUniform1i(m_location, m_v0); + } + private: + void set(GLint location, GLint v0) + { + m_location = location; + m_v0 = v0; + } + + GLint m_location; + GLint m_v0; + }; + + class GlUniform1fCommand : public OpenGlCommand + { + public: + GlUniform1fCommand() : + OpenGlCommand(false, false, "glUniform1f") + { + } + + static std::shared_ptr get(GLint location, GLfloat v0) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0); + return ptr; + } + + void commandToExecute() override + { + ptrUniform1f(m_location, m_v0); + } + private: + void set(GLint location, GLfloat v0) + { + m_location = location; + m_v0 = v0; + } + + GLint m_location; + GLfloat m_v0; + }; + + class GlUniform2fCommand : public OpenGlCommand + { + public: + GlUniform2fCommand() : + OpenGlCommand(false, false, "glUniform2f") + { + } + + static std::shared_ptr get(GLint location, GLfloat v0, GLfloat v1) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0, v1); + return ptr; + } + + void commandToExecute() override + { + ptrUniform2f(m_location, m_v0, m_v1); + } + private: + void set(GLint location, GLfloat v0, GLfloat v1) + { + m_location = location; + m_v0 = v0; + m_v1 = v1; + } + + GLint m_location; + GLfloat m_v0; + GLfloat m_v1; + }; + + class GlUniform2iCommand : public OpenGlCommand + { + public: + GlUniform2iCommand() : + OpenGlCommand(false, false, "glUniform2i") + { + } + + static std::shared_ptr get(GLint location, GLint v0, GLint v1) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0, v1); + return ptr; + } + + void commandToExecute() override + { + ptrUniform2i(m_location, m_v0, m_v1); + } + private: + void set(GLint location, GLint v0, GLint v1) + { + m_location = location; + m_v0 = v0; + m_v1 = v1; + } + + GLint m_location; + GLint m_v0; + GLint m_v1; + }; + + class GlUniform4iCommand : public OpenGlCommand + { + public: + GlUniform4iCommand() : + OpenGlCommand(false, false, "glUniform4i") + { + } + + static std::shared_ptr get(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0, v1, v2, v3); + return ptr; + } + + void commandToExecute() override + { + ptrUniform4i(m_location, m_v0, m_v1, m_v2, m_v3); + } + private: + void set(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) + { + m_location = location; + m_v0 = v0; + m_v1 = v1; + m_v2 = v2; + m_v3 = v3; + } + + GLint m_location; + GLint m_v0; + GLint m_v1; + GLint m_v2; + GLint m_v3; + }; + + class GlUniform4fCommand : public OpenGlCommand + { + public: + GlUniform4fCommand() : + OpenGlCommand(false, false, "glUniform4f") + { + } + + static std::shared_ptr get(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, v0, v1, v2, v3); + return ptr; + } + + void commandToExecute() override + { + ptrUniform4f(m_location, m_v0, m_v1, m_v2, m_v3); + } + private: + void set(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) + { + m_location = location; + m_v0 = v0; + m_v1 = v1; + m_v2 = v2; + m_v3 = v3; + } + + GLint m_location; + GLfloat m_v0; + GLfloat m_v1; + GLfloat m_v2; + GLfloat m_v3; + }; + + class GlUniform3fvCommand : public OpenGlCommand + { + public: + GlUniform3fvCommand() : + OpenGlCommand(false, false, "glUniform3fv") + { + } + + static std::shared_ptr get(GLint location, GLsizei count, std::unique_ptr value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, count, std::move(value)); + return ptr; + } + + void commandToExecute() override + { + ptrUniform3fv(m_location, m_count, m_value.get()); + } + private: + void set(GLint location, GLsizei count, std::unique_ptr value) + { + m_location = location; + m_count = count; + m_value = std::move(value); + } + + GLint m_location; + GLsizei m_count; + std::unique_ptr m_value; + }; + + class GlUniform4fvCommand : public OpenGlCommand + { + public: + GlUniform4fvCommand() : + OpenGlCommand(false, false, "glUniform4fv") + { + } + + static std::shared_ptr get(GLint location, GLsizei count, std::unique_ptr value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(location, count, std::move(value)); + return ptr; + } + + void commandToExecute() override + { + ptrUniform4fv(m_location, m_count, m_value.get()); + } + private: + void set(GLint location, GLsizei count, std::unique_ptr value) + { + m_location = location; + m_count = count; + m_value = std::move(value); + } + + GLint m_location; + GLsizei m_count; + std::unique_ptr m_value; + }; + + class GlDetachShaderCommand : public OpenGlCommand + { + public: + GlDetachShaderCommand() : + OpenGlCommand(false, false, "glDetachShader") + { + } + + static std::shared_ptr get(GLuint program, GLuint shader) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, shader); + return ptr; + } + + void commandToExecute() override + { + ptrDetachShader(m_program, m_shader); + } + private: + void set(GLuint program, GLuint shader) + { + m_program = program; + m_shader = shader; + } + + GLuint m_program; + GLuint m_shader; + }; + + class GlDeleteShaderCommand : public OpenGlCommand + { + public: + GlDeleteShaderCommand() : + OpenGlCommand(false, false, "glDeleteShader") + { + } + + static std::shared_ptr get(GLuint shader) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(shader); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteShader(m_shader); + } + private: + void set(GLuint shader) + { + m_shader = shader; + } + + GLuint m_shader; + }; + + class GlDeleteProgramCommand : public OpenGlCommand + { + public: + GlDeleteProgramCommand() : + OpenGlCommand(false, false, "glDeleteProgram") + { + } + + static std::shared_ptr get(GLuint program) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteProgram(m_program); + } + private: + void set(GLuint program) + { + m_program = program; + } + + GLuint m_program; + }; + + class GlGetProgramInfoLogCommand : public OpenGlCommand + { + public: + GlGetProgramInfoLogCommand() : + OpenGlCommand(true, true, "glGetProgramInfoLog") + { + } + + static std::shared_ptr get(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, bufSize, length, infoLog); + return ptr; + } + + void commandToExecute() override + { + ptrGetProgramInfoLog(m_program, m_bufSize, m_length, m_infoLog); + } + private: + void set(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) + { + m_program = program; + m_bufSize = bufSize; + m_length = length; + m_infoLog = infoLog; + } + + GLuint m_program; + GLsizei m_bufSize; + GLsizei* m_length; + GLchar* m_infoLog; + }; + + class GlGetShaderInfoLogCommand : public OpenGlCommand + { + public: + GlGetShaderInfoLogCommand() : + OpenGlCommand(true, true, "glGetShaderInfoLog") + { + } + + static std::shared_ptr get(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(shader, bufSize, length, infoLog); + return ptr; + } + + void commandToExecute() override + { + ptrGetShaderInfoLog(m_shader, m_bufSize, m_length, m_infoLog); + } + private: + void set(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) + { + m_shader = shader; + m_bufSize = bufSize; + m_length = length; + m_infoLog = infoLog; + } + + GLuint m_shader; + GLsizei m_bufSize; + GLsizei* m_length; + GLchar* m_infoLog; + }; + + class GlGetShaderivCommand : public OpenGlCommand + { + public: + GlGetShaderivCommand() : + OpenGlCommand(true, true, "glGetShaderiv") + { + } + + static std::shared_ptr get(GLuint shader, GLenum pname, GLint* params) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(shader, pname, params); + return ptr; + } + + void commandToExecute() override + { + ptrGetShaderiv(m_shader, m_pname, m_params); + } + private: + void set(GLuint shader, GLenum pname, GLint* params) + { + m_shader = shader; + m_pname = pname; + m_params = params; + } + + GLuint m_shader; + GLenum m_pname; + GLint* m_params; + }; + + class GlGetProgramivCommand : public OpenGlCommand + { + public: + GlGetProgramivCommand() : + OpenGlCommand(true, true, "glGetProgramiv") + { + } + + static std::shared_ptr get(GLuint program, GLenum pname, GLint*& params) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, pname, params); + return ptr; + } + + void commandToExecute() override + { + ptrGetProgramiv(m_program, m_pname, *m_params); + } + private: + void set(GLuint program, GLenum pname, GLint*& params) + { + m_program = program; + m_pname = pname; + m_params = ¶ms; + } + + GLuint m_program; + GLenum m_pname; + GLint** m_params; + }; + + class GlEnableVertexAttribArrayCommand : public OpenGlCommand + { + public: + GlEnableVertexAttribArrayCommand() : + OpenGlCommand(false, false, "glEnableVertexAttribArray") + { + } + + static std::shared_ptr get(GLuint index) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index); + return ptr; + } + + void commandToExecute() override + { + GlVertexAttribPointerManager::enableVertexAttributeIndexRender(m_index); + ptrEnableVertexAttribArray(m_index); + } + private: + void set(GLuint index) + { + m_index = index; + } + + GLuint m_index; + }; + + class GlDisableVertexAttribArrayCommand : public OpenGlCommand + { + public: + GlDisableVertexAttribArrayCommand() : + OpenGlCommand(false, false, "glDisableVertexAttribArray") + { + } + + static std::shared_ptr get(GLuint index) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index); + return ptr; + } + + void commandToExecute() override + { + GlVertexAttribPointerManager::disableVertexAttributeIndexRender(m_index); + ptrDisableVertexAttribArray(m_index); + } + private: + void set(GLuint index) + { + m_index = index; + } + + GLuint m_index; + }; + + class GlVertexAttribPointerBufferedCommand : public OpenGlCommand + { + public: + GlVertexAttribPointerBufferedCommand() : + OpenGlCommand(false, false, "glVertexAttribPointer") + { + } + + static std::shared_ptr get(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, + const GLvoid* offset) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index, size, type, normalized, stride, offset); + return ptr; + } + + void commandToExecute() override + { + ptrVertexAttribPointer(m_index, m_size, m_type, m_normalized, m_stride, m_offset); + } + private: + void set(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, + const GLvoid* offset) + { + m_index = index; + m_size = size; + m_type = type; + m_normalized = normalized; + m_stride = stride; + m_offset = offset; + } + + GLuint m_index; + GLint m_size; + GLenum m_type; + GLboolean m_normalized; + GLsizei m_stride; + const GLvoid* m_offset; + }; + + class GlBindAttribLocationCommand : public OpenGlCommand + { + public: + GlBindAttribLocationCommand() : + OpenGlCommand(false, false, "glBindAttribLocation") + { + } + + static std::shared_ptr get(GLuint program, GLuint index, const std::string name) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, index, name); + return ptr; + } + + void commandToExecute() override + { + ptrBindAttribLocation(m_program, m_index, m_name.data()); + } + private: + void set(GLuint program, GLuint index, const std::string name) + { + m_program = program; + m_index = index; + m_name = name; + } + + GLuint m_program; + GLuint m_index; + std::string m_name; + }; + + class GlVertexAttrib1fCommand : public OpenGlCommand + { + public: + GlVertexAttrib1fCommand() : + OpenGlCommand(false, false, "glVertexAttrib1f") + { + } + + static std::shared_ptr get(GLuint index, GLfloat x) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index, x); + return ptr; + } + + void commandToExecute() override + { + ptrVertexAttrib1f(m_index, m_x); + } + private: + void set(GLuint index, GLfloat x) + { + m_index = index; + m_x = x; + } + + GLuint m_index; + GLfloat m_x; + }; + + class GlVertexAttrib4fCommand : public OpenGlCommand + { + public: + GlVertexAttrib4fCommand() : + OpenGlCommand(false, false, "glVertexAttrib4f") + { + } + + static std::shared_ptr get(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index, x, y, z, w); + return ptr; + } + + void commandToExecute() override + { + ptrVertexAttrib4f(m_index, m_x, m_y, m_z, m_w); + } + private: + void set(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { + m_index = index; + m_x = x; + m_y = y; + m_z = z; + m_w = w; + } + + GLuint m_index; + GLfloat m_x; + GLfloat m_y; + GLfloat m_z; + GLfloat m_w; + }; + + class GlVertexAttrib4fvCommand : public OpenGlCommand + { + public: + GlVertexAttrib4fvCommand() : + OpenGlCommand(false, false, "glVertexAttrib4fv") + { + } + + static std::shared_ptr get(GLuint index, std::unique_ptr v) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(index, std::move(v)); + return ptr; + } + + void commandToExecute() override + { + ptrVertexAttrib4fv(m_index, m_v.get()); + } + private: + void set(GLuint index, std::unique_ptr v) + { + m_index = index; + m_v = std::move(v); + } + + GLuint m_index; + std::unique_ptr m_v; + }; + + class GlDepthRangefCommand : public OpenGlCommand + { + public: + GlDepthRangefCommand() : + OpenGlCommand(false, false, "glDepthRangef") + { + } + + static std::shared_ptr get(GLfloat n, GLfloat f) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, f); + return ptr; + } + + void commandToExecute() override + { + ptrDepthRangef(m_n,m_f); + } + private: + void set(GLfloat n, GLfloat f) + { + m_n = n; + m_f = f; + } + + GLfloat m_n; + GLfloat m_f; + }; + + class GlClearDepthfCommand : public OpenGlCommand + { + public: + GlClearDepthfCommand() : + OpenGlCommand(false, false, "glClearDepthf") + { + } + + static std::shared_ptr get(GLfloat d) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(d); + return ptr; + } + + void commandToExecute() override + { + ptrClearDepthf(m_d); + } + private: + void set(GLfloat d) + { + m_d = d; + } + + GLfloat m_d; + }; + + class GlDrawBuffersCommand : public OpenGlCommand + { + public: + GlDrawBuffersCommand() : + OpenGlCommand(false, false, "glDrawBuffers") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr bufs) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(bufs)); + return ptr; + } + + void commandToExecute() override + { + ptrDrawBuffers(m_n, m_bufs.get()); + } + private: + void set(GLsizei n, std::unique_ptr bufs) + { + m_n = n; + m_bufs = std::move(bufs); + } + + GLsizei m_n; + std::unique_ptr m_bufs; + }; + + class GlGenFramebuffersCommand : public OpenGlCommand + { + public: + GlGenFramebuffersCommand() : + OpenGlCommand(true, false, "glGenFramebuffers") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* framebuffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, framebuffers); + return ptr; + } + + void commandToExecute() override + { + ptrGenFramebuffers(m_n, m_framebuffers); + } + private: + void set(GLsizei n, GLuint* framebuffers) + { + m_n = n; + m_framebuffers = framebuffers; + } + + GLsizei m_n; + GLuint* m_framebuffers; + }; + + class GlBindFramebufferCommand : public OpenGlCommand + { + public: + GlBindFramebufferCommand() : + OpenGlCommand(false, false, "glBindFramebuffer") + { + } + + static std::shared_ptr get(GLenum target, GLuint framebuffer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, framebuffer); + return ptr; + } + + void commandToExecute() override + { + ptrBindFramebuffer(m_target, m_framebuffer); + } + private: + void set(GLenum target, GLuint framebuffer) + { + m_target = target; + m_framebuffer = framebuffer; + } + + GLenum m_target; + GLuint m_framebuffer; + }; + + class GlDeleteFramebuffersCommand : public OpenGlCommand + { + public: + GlDeleteFramebuffersCommand() : + OpenGlCommand(false, false, "glDeleteFramebuffers") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr framebuffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(framebuffers)); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteFramebuffers(m_n, m_framebuffers.get()); + } + private: + void set(GLsizei n, std::unique_ptr framebuffers) + { + m_n = n; + m_framebuffers = std::move(framebuffers); + } + + GLsizei m_n; + std::unique_ptr m_framebuffers; + }; + + class GlFramebufferTexture2DCommand : public OpenGlCommand + { + public: + GlFramebufferTexture2DCommand() : + OpenGlCommand(false, false, "glFramebufferTexture2D") + { + } + + static std::shared_ptr get(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, attachment, textarget, texture, level); + return ptr; + } + + void commandToExecute() override + { + ptrFramebufferTexture2D(m_target, m_attachment, m_textarget, m_texture, m_level); + } + private: + void set(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + m_target = target; + m_attachment = attachment; + m_textarget = textarget; + m_texture = texture; + m_level = level; + } + + GLenum m_target; + GLenum m_attachment; + GLenum m_textarget; + GLuint m_texture; + GLint m_level; + }; + + class GlTexImage2DMultisampleCommand : public OpenGlCommand + { + public: + GlTexImage2DMultisampleCommand() : + OpenGlCommand(false, false, "glTexImage2DMultisample") + { + } + + static std::shared_ptr get(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, samples, internalformat, width, height, fixedsamplelocations); + return ptr; + } + + void commandToExecute() override + { + ptrTexImage2DMultisample(m_target, m_samples, m_internalformat, m_width, m_height, m_fixedsamplelocations); + } + private: + void set(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) + { + m_target = target; + m_samples = samples; + m_internalformat = internalformat; + m_width = width; + m_height = height; + m_fixedsamplelocations = fixedsamplelocations; + } + + GLenum m_target; + GLsizei m_samples; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + GLboolean m_fixedsamplelocations; + }; + + class GlTexStorage2DMultisampleCommand : public OpenGlCommand + { + public: + GlTexStorage2DMultisampleCommand() : + OpenGlCommand(false, false, "glTexStorage2DMultisample") + { + } + + static std::shared_ptr get(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, samples, internalformat, width, height, fixedsamplelocations); + return ptr; + } + + void commandToExecute() override + { + ptrTexStorage2DMultisample(m_target, m_samples, m_internalformat, m_width, m_height, m_fixedsamplelocations); + } + private: + void set(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) + { + m_target = target; + m_samples = samples; + m_internalformat = internalformat; + m_width = width; + m_height = height; + m_fixedsamplelocations = fixedsamplelocations; + } + + GLenum m_target; + GLsizei m_samples; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + GLboolean m_fixedsamplelocations; + }; + + class GlGenRenderbuffersCommand : public OpenGlCommand + { + public: + GlGenRenderbuffersCommand() : + OpenGlCommand(true, false, "glGenRenderbuffers") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* renderbuffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, renderbuffers); + return ptr; + } + + void commandToExecute() override + { + ptrGenRenderbuffers(m_n, m_renderbuffers); + } + private: + void set(GLsizei n, GLuint* renderbuffers) + { + m_n = n; + m_renderbuffers = renderbuffers; + } + + GLsizei m_n; + GLuint* m_renderbuffers; + }; + + class GlBindRenderbufferCommand : public OpenGlCommand + { + public: + GlBindRenderbufferCommand() : + OpenGlCommand(false, false, "glBindRenderbuffer") + { + } + + static std::shared_ptr get(GLenum target, GLuint renderbuffer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, renderbuffer); + return ptr; + } + + void commandToExecute() override + { + ptrBindRenderbuffer(m_target, m_renderbuffer); + } + private: + void set(GLenum target, GLuint renderbuffer) + { + m_target = target; + m_renderbuffer = renderbuffer; + } + + GLenum m_target; + GLuint m_renderbuffer; + }; + + class GlRenderbufferStorageCommand : public OpenGlCommand + { + public: + GlRenderbufferStorageCommand() : + OpenGlCommand(false, false, "glRenderbufferStorage") + { + } + + static std::shared_ptr get(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, internalformat, width, height); + return ptr; + } + + void commandToExecute() override + { + ptrRenderbufferStorage(m_target, m_internalformat, m_width, m_height); + } + private: + void set(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + { + m_target = target; + m_internalformat = internalformat; + m_width = width; + m_height = height; + } + + GLenum m_target; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + }; + + class GlDeleteRenderbuffersCommand : public OpenGlCommand + { + public: + GlDeleteRenderbuffersCommand() : + OpenGlCommand(false, false, "glDeleteRenderbuffers") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr renderbuffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(renderbuffers)); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteRenderbuffers(m_n, m_renderbuffers.get()); + } + private: + void set(GLsizei n, std::unique_ptr renderbuffers) + { + m_n = n; + m_renderbuffers = std::move(renderbuffers); + } + + GLsizei m_n; + std::unique_ptr m_renderbuffers; + }; + + class GlFramebufferRenderbufferCommand : public OpenGlCommand + { + public: + GlFramebufferRenderbufferCommand() : + OpenGlCommand(false, false, "glFramebufferRenderbuffer") + { + } + + static std::shared_ptr get(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, attachment, renderbuffertarget, renderbuffer); + return ptr; + } + + void commandToExecute() override + { + ptrFramebufferRenderbuffer(m_target, m_attachment, m_renderbuffertarget, m_renderbuffer); + } + private: + void set(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + { + m_target = target; + m_attachment = attachment; + m_renderbuffertarget = renderbuffertarget; + m_renderbuffer = renderbuffer; + } + + GLenum m_target; + GLenum m_attachment; + GLenum m_renderbuffertarget; + GLuint m_renderbuffer; + }; + + class GlCheckFramebufferStatusCommand : public OpenGlCommand + { + public: + GlCheckFramebufferStatusCommand() : + OpenGlCommand(true, true, "glCheckFramebufferStatus") + { + } + + static std::shared_ptr get(GLenum target, GLenum& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrCheckFramebufferStatus(m_target); + } + private: + void set(GLenum target, GLenum& returnValue) + { + m_target = target; + m_returnValue = &returnValue; + } + + GLenum m_target; + GLenum* m_returnValue; + }; + + class GlBlitFramebufferCommand : public OpenGlCommand + { + public: + GlBlitFramebufferCommand() : + OpenGlCommand(false, false, "glBlitFramebuffer") + { + } + + static std::shared_ptr get(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + return ptr; + } + + void commandToExecute() override + { + ptrBlitFramebuffer(m_srcX0, m_srcY0, m_srcX1, m_srcY1, m_dstX0, m_dstY0, m_dstX1, m_dstY1, m_mask, + m_filter); + } + private: + void set(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) + { + m_srcX0 = srcX0; + m_srcY0 = srcY0; + m_srcX1 = srcX1; + m_srcY1 = srcY1; + m_dstX0 = dstX0; + m_dstY0 = dstY0; + m_dstX1 = dstX1; + m_dstY1 = dstY1; + m_mask = mask; + m_filter = filter; + } + + GLint m_srcX0; + GLint m_srcY0; + GLint m_srcX1; + GLint m_srcY1; + GLint m_dstX0; + GLint m_dstY0; + GLint m_dstX1; + GLint m_dstY1; + GLbitfield m_mask; + GLenum m_filter; + }; + + class GlGenVertexArraysCommand : public OpenGlCommand + { + public: + GlGenVertexArraysCommand() : + OpenGlCommand(true, false, "glGenVertexArrays") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* arrays) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, arrays); + return ptr; + } + + void commandToExecute() override + { + ptrGenVertexArrays(m_n, m_arrays); + } + private: + void set(GLsizei n, GLuint* arrays) + { + m_n = n; + m_arrays = arrays; + } + + GLsizei m_n; + GLuint* m_arrays; + }; + + class GlBindVertexArrayCommand : public OpenGlCommand + { + public: + GlBindVertexArrayCommand() : + OpenGlCommand(false, false, "glBindVertexArray") + { + } + + static std::shared_ptr get(GLuint array) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(array); + return ptr; + } + + void commandToExecute() override + { + ptrBindVertexArray(m_array); + } + private: + void set(GLuint array) + { + m_array = array; + } + + GLuint m_array; + }; + + class GlDeleteVertexArraysCommand : public OpenGlCommand + { + public: + GlDeleteVertexArraysCommand() : + OpenGlCommand(false, false, "glDeleteVertexArrays") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr arrays) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(arrays)); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteVertexArrays(m_n, m_arrays.get()); + } + private: + void set(GLsizei n, std::unique_ptr arrays) + { + m_n = n; + m_arrays = std::move(arrays); + } + + GLsizei m_n; + std::unique_ptr m_arrays; + }; + + class GlGenBuffersCommand : public OpenGlCommand + { + public: + GlGenBuffersCommand() : + OpenGlCommand(true, false, "glGenBuffers") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* buffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, buffers); + return ptr; + } + + void commandToExecute() override + { + ptrGenBuffers(m_n, m_buffers); + } + private: + void set(GLsizei n, GLuint* buffers) + { + m_n = n; + m_buffers = buffers; + } + + GLsizei m_n; + GLuint* m_buffers; + }; + + class GlBindBufferCommand : public OpenGlCommand + { + public: + GlBindBufferCommand() : + OpenGlCommand(false, false, "glBindBuffer") + { + } + + static std::shared_ptr get(GLenum target, GLuint buffer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, buffer); + return ptr; + } + + static GLuint getBoundBufferRender(GLenum target) + { + return m_boundBuffersRender[target]; + } + + static void setBoundBuffer(GLenum target, GLuint buffer) + { + m_boundBuffers[target] = buffer; + } + + static GLuint getBoundBuffer(GLenum target) + { + return m_boundBuffers[target]; + } + + void commandToExecute() override + { + ptrBindBuffer(m_target, m_buffer); + m_boundBuffersRender[m_target] = m_buffer; + } + private: + void set(GLenum target, GLuint buffer) + { + m_target = target; + m_buffer = buffer; + } + + GLenum m_target; + GLuint m_buffer; + + static std::unordered_map m_boundBuffersRender; + static std::unordered_map m_boundBuffers; + }; + + class GlBufferDataCommand : public OpenGlCommand + { + public: + GlBufferDataCommand() : + OpenGlCommand(false, false, "glBufferData") + { + } + + static std::shared_ptr get(GLenum target, GLsizeiptr size, std::unique_ptr data, GLenum usage) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, size, std::move(data), usage); + return ptr; + } + + void commandToExecute() override + { + ptrBufferData(m_target, m_size, m_data.get(), m_usage); + } + private: + void set(GLenum target, GLsizeiptr size, std::unique_ptr data, GLenum usage) + { + m_target = target; + m_size = size; + m_data = std::move(data); + m_usage = usage; + } + + GLenum m_target; + GLsizeiptr m_size; + std::unique_ptr m_data; + GLenum m_usage; + }; + + class GlMapBufferCommand : public OpenGlCommand + { + public: + GlMapBufferCommand() : + OpenGlCommand(false, false, "glMapBuffer") + { + } + + static std::shared_ptr get(GLenum target, GLenum access) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, access); + return ptr; + } + + void commandToExecute() override + { + ptrMapBuffer(m_target, m_access); + } + private: + void set(GLenum target, GLenum access) + { + m_target = target; + m_access = access; + } + + GLenum m_target; + GLenum m_access; + }; + + class GlMapBufferRangeCommand : public OpenGlCommand + { + public: + GlMapBufferRangeCommand() : + OpenGlCommand(true, true, "glMapBufferRange") + { + } + + static std::shared_ptr get(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, + void*& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, offset, length, access, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrMapBufferRange(m_target, m_offset, m_length, m_access); + } + private: + void set(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, + void*& returnValue) + { + m_target = target; + m_offset = offset; + m_length = length; + m_access = access; + m_returnValue = &returnValue; + } + + GLenum m_target; + GLintptr m_offset; + GLsizeiptr m_length; + GLbitfield m_access; + void** m_returnValue; + }; + + class GlMapBufferRangeWriteAsyncCommand : public OpenGlCommand + { + public: + GlMapBufferRangeWriteAsyncCommand() : + OpenGlCommand(false, false, "GlMapBufferRangeWriteAsyncCommand") + { + } + + static std::shared_ptr get(GLenum target, GLintptr offset, u32 length, + GLbitfield access, splicer::Node>* data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, offset, length, access, data); + return ptr; + } + + void commandToExecute() override + { + void* buffer_pointer = ptrMapBufferRange(m_target, m_offset, m_length, m_access); + memcpy(buffer_pointer, m_data->val().data(), m_length); + m_vectorPool.release(m_data); + } + + static std::shared_ptr> getData(GLuint buffer, u32 length) + { + verifyBuffer(buffer, length); + return m_TempData[buffer]; + } + + static void setTemp(GLenum target, GLintptr offset, u32 length, GLbitfield access) + { + m_targetTemp = target; + m_offsetTemp = offset; + m_lengthTemp = length; + m_accessTemp = access; + } + + static GLenum getTempTarget(void) + { + return m_targetTemp; + } + + static GLintptr getTempOffset(void) + { + return m_offsetTemp; + } + + static u32 getTempLength(void) + { + return m_lengthTemp; + } + + static GLbitfield getTempAccess(void) + { + return m_accessTemp; + } + + static splicer::Node>* getVectorFromPool() { + return m_vectorPool.acquireOne().release(); + } + + private: + void set(GLenum target, GLintptr offset, u32 length, GLbitfield access, splicer::Node>* data) + { + m_target = target; + m_offset = offset; + m_length = length; + m_access = access; + m_data = data; + } + + static void verifyBuffer(GLuint buffer, u32 length) + { + if (m_TempData[buffer] == nullptr || m_TempData[buffer]->size() < length) { + m_TempData[buffer] = std::make_shared>(length); + } + } + + GLenum m_target; + GLintptr m_offset; + u32 m_length; + GLbitfield m_access; + splicer::Node>* m_data; + + static GLenum m_targetTemp; + static GLintptr m_offsetTemp; + static u32 m_lengthTemp; + static GLbitfield m_accessTemp; + static std::unordered_map>> m_TempData; + static splicer::ObjectPool> m_vectorPool; + public: + static constexpr GLbitfield WRITE_ACCESS_ASYNC = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT; + }; + + class GlMapBufferRangeReadAsyncCommand : public OpenGlCommand + { + public: + GlMapBufferRangeReadAsyncCommand() : + OpenGlCommand(false, false, "GlMapBufferRangeReadAsyncCommand") + { + } + + static std::shared_ptr get(GLenum target, GLintptr offset, u32 length, + GLbitfield access) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, offset, length, access); + return ptr; + } + + void commandToExecute() override + { + void* buffer_pointer = ptrMapBufferRange(m_target, m_offset, m_length, m_access); + + if (buffer_pointer != nullptr) { + std::unique_lock lock(m_mapMutex); + GLuint buffer = GlBindBufferCommand::getBoundBufferRender(m_target); + verifyBuffer(buffer, m_length); + auto data = m_data[buffer]; + memcpy(data->data(), buffer_pointer, m_length); + } + } + + static std::shared_ptr> getData(GLuint buffer, u32 length) + { + std::unique_lock lock(m_mapMutex); + verifyBuffer(buffer, length); + return m_data[buffer]; + } + + private: + void set(GLenum target, GLintptr offset, u32 length, GLbitfield access) + { + m_target = target; + m_offset = offset; + m_length = length; + m_access = access; + } + + static void verifyBuffer(GLuint buffer, u32 length) + { + if (m_data[buffer] == nullptr || m_data[buffer]->size() < length) { + m_data[buffer] = std::make_shared>(length); + } + } + + GLenum m_target; + GLintptr m_offset; + u32 m_length; + GLbitfield m_access; + static std::unordered_map>> m_data; + static std::mutex m_mapMutex; + }; + + class GlUnmapBufferCommand : public OpenGlCommand + { + public: + GlUnmapBufferCommand() : + OpenGlCommand(true, true, "glUnmapBuffer") + { + } + + static std::shared_ptr get(GLenum target, GLboolean& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrUnmapBuffer(m_target); + } + private: + void set(GLenum target, GLboolean& returnValue) + { + m_target = target; + m_returnValue = &returnValue; + } + + GLenum m_target; + GLboolean* m_returnValue; + }; + + class GlUnmapBufferAsyncCommand : public OpenGlCommand + { + public: + GlUnmapBufferAsyncCommand() : + OpenGlCommand(false, false, "glUnmapBuffer") + { + } + + static std::shared_ptr get(GLenum target) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target); + return ptr; + } + + void commandToExecute() override + { + ptrUnmapBuffer(m_target); + } + private: + void set(GLenum target) + { + m_target = target; + } + + GLenum m_target; + }; + + class GlDeleteBuffersCommand : public OpenGlCommand + { + public: + GlDeleteBuffersCommand() : + OpenGlCommand(false, false, "glDeleteBuffers") + { + } + + static std::shared_ptr get(GLsizei n, std::unique_ptr buffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, std::move(buffers)); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteBuffers(m_n, m_buffers.get()); + } + private: + void set(GLsizei n, std::unique_ptr buffers) + { + m_n = n; + m_buffers = std::move(buffers); + } + + GLsizei m_n; + std::unique_ptr m_buffers; + }; + + class GlBindImageTextureCommand : public OpenGlCommand + { + public: + GlBindImageTextureCommand() : + OpenGlCommand(false, false, "glBindImageTexture") + { + } + + static std::shared_ptr get(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, + GLenum access, GLenum format) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(unit, texture, level, layered, layer, access, format); + return ptr; + } + + void commandToExecute() override + { + ptrBindImageTexture(m_unit, m_texture, m_level, m_layered, m_layer, m_access, m_format); + } + private: + void set(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, + GLenum access, GLenum format) + { + m_unit = unit; + m_texture = texture; + m_level = level; + m_layered = layered; + m_layer = layer; + m_access = access; + m_format = format; + } + + GLuint m_unit; + GLuint m_texture; + GLint m_level; + GLboolean m_layered; + GLint m_layer; + GLenum m_access; + GLenum m_format; + }; + + class GlMemoryBarrierCommand : public OpenGlCommand + { + public: + GlMemoryBarrierCommand() : + OpenGlCommand(false, false, "glMemoryBarrier") + { + } + + static std::shared_ptr get(GLbitfield barriers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(barriers); + return ptr; + } + + void commandToExecute() override + { + ptrMemoryBarrier(m_barriers); + } + private: + void set(GLbitfield barriers) + { + m_barriers = barriers; + } + + GLbitfield m_barriers; + }; + + class GlTextureBarrierCommand : public OpenGlCommand + { + public: + GlTextureBarrierCommand() : + OpenGlCommand(false, false, "glTextureBarrier") + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + ptrTextureBarrier(); + } + private: + void set() + { + } + }; + + class GlTextureBarrierNVCommand : public OpenGlCommand + { + public: + GlTextureBarrierNVCommand() : + OpenGlCommand(false, false, "glTextureBarrierNV") + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + ptrTextureBarrierNV(); + } + private: + void set() + { + } + }; + + class GlGetStringiCommand : public OpenGlCommand + { + public: + GlGetStringiCommand() : + OpenGlCommand(true, false, "glGetStringi") + { + } + + static std::shared_ptr get(GLenum name, GLuint index, const GLubyte*& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(name, index, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetStringi(m_name, m_index); + } + private: + void set(GLenum name, GLuint index, const GLubyte*& returnValue) + { + m_name = name; + m_index = index; + m_returnValue = &returnValue; + } + + GLenum m_name; + GLuint m_index; + const GLubyte** m_returnValue; + }; + + class GlInvalidateFramebufferCommand : public OpenGlCommand + { + public: + GlInvalidateFramebufferCommand() : + OpenGlCommand(false, false, "glInvalidateFramebuffer") + { + } + + static std::shared_ptr get(GLenum target, GLsizei numAttachments, std::unique_ptr attachments) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, numAttachments, std::move(attachments)); + return ptr; + } + + void commandToExecute() override + { + ptrInvalidateFramebuffer(m_target, m_numAttachments, m_attachments.get()); + } + private: + void set(GLenum target, GLsizei numAttachments, std::unique_ptr attachments) + { + m_target = target; + m_numAttachments = numAttachments; + m_attachments = std::move(attachments); + } + + GLenum m_target; + GLsizei m_numAttachments; + std::unique_ptr m_attachments; + }; + + class GlBufferStorageCommand : public OpenGlCommand + { + public: + GlBufferStorageCommand() : + OpenGlCommand(false, false, "glBufferStorage") + { + } + + static std::shared_ptr get(GLenum target, GLsizeiptr size, std::unique_ptr data, GLbitfield flags) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, size, std::move(data), flags); + return ptr; + } + + void commandToExecute() override + { + ptrBufferStorage(m_target, m_size, m_data.get(), m_flags); + } + private: + void set(GLenum target, GLsizeiptr size, std::unique_ptr data, GLbitfield flags) + { + m_target = target; + m_size = size; + m_data = std::move(data); + m_flags = flags; + } + + GLenum m_target; + GLsizeiptr m_size; + std::unique_ptr m_data; + GLbitfield m_flags; + }; + + class GlFenceSyncCommand : public OpenGlCommand + { + public: + GlFenceSyncCommand() : + OpenGlCommand(true, false, "glFenceSync") + { + } + + static std::shared_ptr get(GLenum condition, GLbitfield flags, GLsync& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(condition, flags, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrFenceSync(m_condition, m_flags); + } + private: + void set(GLenum condition, GLbitfield flags, GLsync& returnValue) + { + m_condition = condition; + m_flags = flags; + m_returnValue = &returnValue; + } + + GLenum m_condition; + GLbitfield m_flags; + GLsync* m_returnValue; + }; + + class GlClientWaitSyncCommand : public OpenGlCommand + { + public: + GlClientWaitSyncCommand() : + OpenGlCommand(true, false, "glClientWaitSync") + { + } + + static std::shared_ptr get(GLsync sync, GLbitfield flags, GLuint64 timeout) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(sync, flags, timeout); + return ptr; + } + + void commandToExecute() override + { + ptrClientWaitSync(m_sync, m_flags, m_timeout); + } + private: + void set(GLsync sync, GLbitfield flags, GLuint64 timeout) + { + m_sync = sync; + m_flags = flags; + m_timeout = timeout; + } + + GLsync m_sync; + GLbitfield m_flags; + GLuint64 m_timeout; + }; + + class GlDeleteSyncCommand : public OpenGlCommand + { + public: + GlDeleteSyncCommand() : + OpenGlCommand(true, false, "glDeleteSync") + { + } + + static std::shared_ptr get(GLsync sync) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(sync); + return ptr; + } + + void commandToExecute() override + { + ptrDeleteSync(m_sync); + } + private: + void set(GLsync sync) + { + m_sync = sync; + } + + GLsync m_sync; + }; + + class GlGetUniformBlockIndexCommand : public OpenGlCommand + { + public: + GlGetUniformBlockIndexCommand() : + OpenGlCommand(true, true, "glGetUniformBlockIndex") + { + } + + static std::shared_ptr get(GLuint program, const GLchar* uniformBlockName, GLuint& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, uniformBlockName, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetUniformBlockIndex(m_program, m_uniformBlockName); + } + private: + void set(GLuint program, const GLchar* uniformBlockName, GLuint& returnValue) + { + m_program = program; + m_uniformBlockName = uniformBlockName; + m_returnValue = &returnValue; + } + + GLuint m_program; + const GLchar* m_uniformBlockName; + GLuint* m_returnValue; + }; + + class GlUniformBlockBindingCommand : public OpenGlCommand + { + public: + GlUniformBlockBindingCommand() : + OpenGlCommand(false, false, "glUniformBlockBinding") + { + } + + static std::shared_ptr get(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, uniformBlockIndex, uniformBlockBinding); + return ptr; + } + + void commandToExecute() override + { + ptrUniformBlockBinding(m_program, m_uniformBlockIndex, m_uniformBlockBinding); + } + private: + void set(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) + { + m_program = program; + m_uniformBlockIndex = uniformBlockIndex; + m_uniformBlockBinding = uniformBlockBinding; + } + + GLuint m_program; + GLuint m_uniformBlockIndex; + GLuint m_uniformBlockBinding; + }; + + class GlGetActiveUniformBlockivCommand : public OpenGlCommand + { + public: + GlGetActiveUniformBlockivCommand() : + OpenGlCommand(true, true, "glGetActiveUniformBlockiv") + { + } + + static std::shared_ptr get(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, uniformBlockIndex, pname, params); + return ptr; + } + + void commandToExecute() override + { + ptrGetActiveUniformBlockiv(m_program, m_uniformBlockIndex, m_pname, m_params); + } + private: + void set(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) + { + m_program = program; + m_uniformBlockIndex = uniformBlockIndex; + m_pname = pname; + m_params = params; + } + + GLuint m_program; + GLuint m_uniformBlockIndex; + GLenum m_pname; + GLint* m_params; + }; + + class GlGetUniformIndicesCommand : public OpenGlCommand + { + public: + GlGetUniformIndicesCommand() : + OpenGlCommand(true, true, "glGetUniformIndices") + { + } + + static std::shared_ptr get(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, uniformCount, uniformNames, uniformIndices); + return ptr; + } + + void commandToExecute() override + { + ptrGetUniformIndices(m_program, m_uniformCount, m_uniformNames, m_uniformIndices); + } + private: + void set(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, + GLuint* uniformIndices) + { + m_program = program; + m_uniformCount = uniformCount; + m_uniformNames = uniformNames; + m_uniformIndices = uniformIndices; + } + + GLuint m_program; + GLsizei m_uniformCount; + const GLchar* const* m_uniformNames; + GLuint* m_uniformIndices; + }; + + class GlGetActiveUniformsivCommand : public OpenGlCommand + { + public: + GlGetActiveUniformsivCommand() : + OpenGlCommand(true, true, "glGetActiveUniformsiv") + { + } + + static std::shared_ptr get(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, + GLint* params) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, uniformCount, uniformIndices, pname, params); + return ptr; + } + + void commandToExecute() override + { + ptrGetActiveUniformsiv(m_program, m_uniformCount, m_uniformIndices, m_pname, m_params); + } + private: + void set(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, + GLint* params) + { + m_program = program; + m_uniformCount = uniformCount; + m_uniformIndices = uniformIndices; + m_pname = pname; + m_params = params; + } + + GLuint m_program; + GLsizei m_uniformCount; + const GLuint* m_uniformIndices; + GLenum m_pname; + GLint* m_params; + }; + + class GlBindBufferBaseCommand : public OpenGlCommand + { + public: + GlBindBufferBaseCommand() : + OpenGlCommand(false, false, "glBindBufferBase") + { + } + + static std::shared_ptr get(GLenum target, GLuint index, GLuint buffer) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, index, buffer); + return ptr; + } + + void commandToExecute() override + { + ptrBindBufferBase(m_target, m_index, m_buffer); + } + private: + void set(GLenum target, GLuint index, GLuint buffer) + { + m_target = target; + m_index = index; + m_buffer = buffer; + } + + GLenum m_target; + GLuint m_index; + GLuint m_buffer; + }; + + class GlBufferSubDataCommand : public OpenGlCommand + { + public: + GlBufferSubDataCommand() : + OpenGlCommand(false, false, "glBufferSubData") + { + } + + static std::shared_ptr get(GLenum target, GLintptr offset, GLsizeiptr size, std::unique_ptr data) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, offset, size, std::move(data)); + return ptr; + } + + void commandToExecute() override + { + ptrBufferSubData(m_target, m_offset, m_size, m_data.get()); + } + private: + void set(GLenum target, GLintptr offset, GLsizeiptr size, std::unique_ptr data) + { + m_target = target; + m_offset = offset; + m_size = size; + m_data = std::move(data); + } + + GLenum m_target; + GLintptr m_offset; + GLsizeiptr m_size; + std::unique_ptr m_data; + }; + + class GlGetProgramBinaryCommand : public OpenGlCommand + { + public: + GlGetProgramBinaryCommand() : + OpenGlCommand(true, true, "glGetProgramBinary") + { + } + + static std::shared_ptr get(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, bufSize, length, binaryFormat, binary); + return ptr; + } + + void commandToExecute() override + { + ptrGetProgramBinary(m_program, m_bufSize, m_length, m_binaryFormat, m_binary); + } + private: + void set(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void* binary) + { + m_program = program; + m_bufSize = bufSize; + m_length = length; + m_binaryFormat = binaryFormat; + m_binary = binary; + } + + GLuint m_program; + GLsizei m_bufSize; + GLsizei* m_length; + GLenum* m_binaryFormat; + void* m_binary; + }; + + class GlProgramBinaryCommand : public OpenGlCommand + { + public: + GlProgramBinaryCommand() : + OpenGlCommand(false, false, "glProgramBinary") + { + } + + static std::shared_ptr get(GLuint program, GLenum binaryFormat, std::unique_ptr binary, GLsizei length) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, binaryFormat, std::move(binary), length); + return ptr; + } + + void commandToExecute() override + { + ptrProgramBinary(m_program, m_binaryFormat, m_binary.get(), m_length); + } + private: + void set(GLuint program, GLenum binaryFormat, std::unique_ptr binary, GLsizei length) + { + m_program = program; + m_binaryFormat = binaryFormat; + m_binary = std::move(binary); + m_length = length; + } + + GLuint m_program; + GLenum m_binaryFormat; + std::unique_ptr m_binary; + GLsizei m_length; + }; + + class GlProgramParameteriCommand : public OpenGlCommand + { + public: + GlProgramParameteriCommand() : + OpenGlCommand(false, false, "glProgramParameteri") + { + } + + static std::shared_ptr get(GLuint program, GLenum pname, GLint value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(program, pname, value); + return ptr; + } + + void commandToExecute() override + { + ptrProgramParameteri(m_program, m_pname, m_value); + } + private: + void set(GLuint program, GLenum pname, GLint value) + { + m_program = program; + m_pname = pname; + m_value = value; + } + + GLuint m_program; + GLenum m_pname; + GLint m_value; + }; + + class GlTexStorage2DCommand : public OpenGlCommand + { + public: + GlTexStorage2DCommand() : + OpenGlCommand(false, false, "glTexStorage2D") + { + } + + static std::shared_ptr get(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, levels, internalformat, width, height); + return ptr; + } + + void commandToExecute() override + { + ptrTexStorage2D(m_target, m_levels, m_internalformat, m_width, m_height); + } + private: + void set(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + m_target = target; + m_levels = levels; + m_internalformat = internalformat; + m_width = width; + m_height = height; + } + + GLenum m_target; + GLsizei m_levels; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + }; + + class GlTextureStorage2DCommand : public OpenGlCommand + { + public: + GlTextureStorage2DCommand() : + OpenGlCommand(false, false, "glTextureStorage2D") + { + } + + static std::shared_ptr get(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture, levels, internalformat, width, height); + return ptr; + } + + void commandToExecute() override + { + ptrTextureStorage2D(m_texture, m_levels, m_internalformat, m_width, m_height); + } + private: + void set(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + m_texture = texture; + m_levels = levels; + m_internalformat = internalformat; + m_width = width; + m_height = height; + } + + GLuint m_texture; + GLsizei m_levels; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + }; + + class GlTextureSubImage2DUnbufferedCommand : public OpenGlCommand + { + public: + GlTextureSubImage2DUnbufferedCommand() : + OpenGlCommand(false, false, "glTextureSubImage2D") + { + } + + static std::shared_ptr get(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, + GLsizei height, GLenum format, GLenum type, std::unique_ptr pixels) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture, level, xoffset, yoffset, width, height, format, type, std::move(pixels)); + return ptr; + } + + void commandToExecute() override + { + ptrTextureSubImage2D(m_texture, m_level, m_xoffset, m_yoffset, m_width, m_height, m_format, m_type, + m_pixels.get()); + } + private: + void set(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, + GLsizei height, GLenum format, GLenum type, std::unique_ptr pixels) + { + m_texture = texture; + m_level = level; + m_xoffset = xoffset; + m_yoffset = yoffset; + m_width = width; + m_height = height; + m_format = format; + m_type = type; + m_pixels = std::move(pixels); + } + + GLuint m_texture; + GLint m_level; + GLint m_xoffset; + GLint m_yoffset; + GLsizei m_width; + GLsizei m_height; + GLenum m_format; + GLenum m_type; + std::unique_ptr m_pixels; + }; + + class GlTextureStorage2DMultisampleCommand : public OpenGlCommand + { + public: + GlTextureStorage2DMultisampleCommand() : + OpenGlCommand(false, false, "glTextureStorage2DMultisample") + { + } + + static std::shared_ptr get(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height, GLboolean fixedsamplelocations) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture, target, samples, internalformat, width, height, fixedsamplelocations); + return ptr; + } + + void commandToExecute() override + { + ptrTextureStorage2DMultisample(m_texture, m_target, m_samples, m_internalformat,m_width, m_height, + m_fixedsamplelocations); + } + private: + void set(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height, GLboolean fixedsamplelocations) + { + m_texture = texture; + m_target = target; + m_samples = samples; + m_internalformat = internalformat; + m_width = width; + m_height = height; + m_fixedsamplelocations = fixedsamplelocations; + } + + GLuint m_texture; + GLenum m_target; + GLsizei m_samples; + GLenum m_internalformat; + GLsizei m_width; + GLsizei m_height; + GLboolean m_fixedsamplelocations; + }; + + class GlTextureParameteriCommand : public OpenGlCommand + { + public: + GlTextureParameteriCommand() : + OpenGlCommand(false, false, "glTextureParameteri") + { + } + + static std::shared_ptr get(GLuint texture, GLenum pname, GLint param) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture, pname, param); + return ptr; + } + + void commandToExecute() override + { + ptrTextureParameteri(m_texture, m_pname, m_param); + } + private: + void set(GLuint texture, GLenum pname, GLint param) + { + m_texture = texture; + m_pname = pname; + m_param = param; + } + + GLuint m_texture; + GLenum m_pname; + GLint m_param; + }; + + class GlTextureParameterfCommand : public OpenGlCommand + { + public: + GlTextureParameterfCommand() : + OpenGlCommand(false, false, "glTextureParameterf") + { + } + + static std::shared_ptr get(GLuint texture, GLenum pname, GLfloat param) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(texture, pname, param); + return ptr; + } + + void commandToExecute() override + { + ptrTextureParameterf(m_texture, m_pname, m_param); + } + private: + void set(GLuint texture, GLenum pname, GLfloat param) + { + m_texture = texture; + m_pname = pname; + m_param = param; + } + + GLuint m_texture; + GLenum m_pname; + GLfloat m_param; + }; + + class GlCreateTexturesCommand : public OpenGlCommand + { + public: + GlCreateTexturesCommand() : + OpenGlCommand(true, false, "glCreateTextures") + { + } + + static std::shared_ptr get(GLenum target, GLsizei n, GLuint* textures) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, n, textures); + return ptr; + } + + void commandToExecute() override + { + ptrCreateTextures(m_target, m_n, m_textures); + } + private: + void set(GLenum target, GLsizei n, GLuint* textures) + { + m_target = target; + m_n = n; + m_textures = textures; + } + + GLenum m_target; + GLsizei m_n; + GLuint* m_textures; + }; + + class GlCreateBuffersCommand : public OpenGlCommand + { + public: + GlCreateBuffersCommand() : + OpenGlCommand(true, false, "glCreateBuffers") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* buffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, buffers); + return ptr; + } + + void commandToExecute() override + { + ptrCreateBuffers(m_n, m_buffers); + } + private: + void set(GLsizei n, GLuint* buffers) + { + m_n = n; + m_buffers = buffers; + } + + GLsizei m_n; + GLuint* m_buffers; + }; + + class GlCreateFramebuffersCommand : public OpenGlCommand + { + public: + GlCreateFramebuffersCommand() : + OpenGlCommand(true, false, "glCreateFramebuffers") + { + } + + static std::shared_ptr get(GLsizei n, GLuint* framebuffers) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(n, framebuffers); + return ptr; + } + + void commandToExecute() override + { + ptrCreateFramebuffers(m_n, m_framebuffers); + } + private: + void set(GLsizei n, GLuint* framebuffers) + { + m_n = n; + m_framebuffers = framebuffers; + } + + GLsizei m_n; + GLuint* m_framebuffers; + }; + + class GlNamedFramebufferTextureCommand : public OpenGlCommand + { + public: + GlNamedFramebufferTextureCommand() : + OpenGlCommand(false, false, "glNamedFramebufferTexture") + { + } + + static std::shared_ptr get(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(framebuffer, attachment, texture, level); + return ptr; + } + + void commandToExecute() override + { + ptrNamedFramebufferTexture(m_framebuffer, m_attachment, m_texture, m_level); + } + private: + void set(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) + { + m_framebuffer = framebuffer; + m_attachment = attachment; + m_texture = texture; + m_level = level; + } + + GLuint m_framebuffer; + GLenum m_attachment; + GLuint m_texture; + GLint m_level; + }; + + class GlDrawRangeElementsBaseVertexCommand : public OpenGlCommand + { + public: + GlDrawRangeElementsBaseVertexCommand() : + OpenGlCommand(false, false, "glDrawRangeElementsBaseVertex") + { + } + + static std::shared_ptr get(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const u16* indices, GLint basevertex) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(mode, start, end, count, type, indices, basevertex); + return ptr; + } + + void commandToExecute() override + { + ptrDrawRangeElementsBaseVertex(m_mode, m_start, m_end, m_count, m_type, m_indices, m_basevertex); + } + private: + void set(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const u16* indices, GLint basevertex) + { + m_mode = mode; + m_start = start; + m_end = end; + m_count = count; + m_type = type; + m_indices = indices; + m_basevertex = basevertex; + } + + GLenum m_mode; + GLuint m_start; + GLuint m_end; + GLsizei m_count; + GLenum m_type; + const u16* m_indices; + GLint m_basevertex; + }; + + class GlFlushMappedBufferRangeCommand : public OpenGlCommand + { + public: + GlFlushMappedBufferRangeCommand() : + OpenGlCommand(false, false, "glFlushMappedBufferRange") + { + } + + static std::shared_ptr get(GLenum target, GLintptr offset, GLsizeiptr length) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, offset, length); + return ptr; + } + + void commandToExecute() override + { + ptrFlushMappedBufferRange(m_target, m_offset, m_length); + } + private: + void set(GLenum target, GLintptr offset, GLsizeiptr length) + { + m_target = target; + m_offset = offset; + m_length = length; + } + + GLenum m_target; + GLintptr m_offset; + GLsizeiptr m_length; + }; + + class GlFinishCommand : public OpenGlCommand + { + public: + GlFinishCommand() : + OpenGlCommand(true, true, "glFinish") + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + ptrFinish(); + } + private: + void set() + { + + } + }; + + class GlEGLImageTargetTexture2DOESCommand : public OpenGlCommand + { + public: + GlEGLImageTargetTexture2DOESCommand() : + OpenGlCommand(false, false, "glEGLImageTargetTexture2DOES") + { + } + + static std::shared_ptr get(GLenum target, void* image) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(target, image); + return ptr; + } + + void commandToExecute() override + { + ptrEGLImageTargetTexture2DOES(m_target, m_image); + } + private: + void set(GLenum target, void* image) + { + m_target = target; + m_image = image; + } + + GLenum m_target; + void* m_image; + }; + +#if defined(OS_ANDROID) + class EglGetNativeClientBufferANDROIDCommand : public OpenGlCommand + { + public: + EglGetNativeClientBufferANDROIDCommand() : + OpenGlCommand(true, true, "eglGetNativeClientBufferANDROID") + { + } + + static std::shared_ptr get(const AHardwareBuffer *buffer, EGLClientBuffer& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(buffer, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ptrGetNativeClientBufferANDROID(m_buffer); + } + private: + void set(const AHardwareBuffer *buffer, EGLClientBuffer& returnValue) + { + m_buffer = buffer; + m_returnValue = &returnValue; + } + + const struct AHardwareBuffer *m_buffer; + EGLClientBuffer* m_returnValue; + }; +#endif +#ifdef MUPENPLUSAPI + //Vid ext functions + class CoreVideoInitCommand : public OpenGlCommand + { + public: + CoreVideoInitCommand() : + OpenGlCommand(true, false, "CoreVideo_Init", false) + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + ::CoreVideo_Init(); + } + private: + void set() + { + } + }; + + class CoreVideoQuitCommand : public OpenGlCommand + { + public: + CoreVideoQuitCommand() : + OpenGlCommand(true, false, "CoreVideo_Quit", false) + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + ::CoreVideo_Quit(); + } + private: + void set() + { + } + }; + + class CoreVideoSetVideoModeCommand : public OpenGlCommand + { + public: + CoreVideoSetVideoModeCommand() : + OpenGlCommand(true, false, "CoreVideo_SetVideoMode", false) + { + } + + static std::shared_ptr get(int screenWidth, int screenHeight, int bitsPerPixel, m64p_video_mode mode, + m64p_video_flags flags, m64p_error& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(screenWidth, screenHeight, bitsPerPixel, mode, flags, returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = ::CoreVideo_SetVideoMode(m_screenWidth, m_screenHeight, m_bitsPerPixel, m_mode, m_flags); + + initGLFunctions(); + } + private: + void set(int screenWidth, int screenHeight, int bitsPerPixel, m64p_video_mode mode, + m64p_video_flags flags, m64p_error& returnValue) + { + m_screenWidth = screenWidth; + m_screenHeight = screenHeight; + m_bitsPerPixel = bitsPerPixel; + m_mode = mode; + m_flags = flags; + m_returnValue = &returnValue; + } + + int m_screenWidth; + int m_screenHeight; + int m_bitsPerPixel; + m64p_video_mode m_mode; + m64p_video_flags m_flags; + m64p_error* m_returnValue; + }; + + class CoreVideoGLSetAttributeCommand : public OpenGlCommand + { + public: + CoreVideoGLSetAttributeCommand() : + OpenGlCommand(true, false, "CoreVideo_GL_SetAttribute", false) + { + } + + static std::shared_ptr get(m64p_GLattr attribute, int value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(attribute, value); + return ptr; + } + + void commandToExecute() override + { + ::CoreVideo_GL_SetAttribute(m_attribute, m_value); + } + private: + void set(m64p_GLattr attribute, int value) + { + m_attribute = attribute; + m_value = value; + } + + m64p_GLattr m_attribute; + int m_value; + }; + + class CoreVideoGLGetAttributeCommand : public OpenGlCommand + { + public: + CoreVideoGLGetAttributeCommand() : + OpenGlCommand(true, false, "CoreVideo_GL_GetAttribute", false) + { + } + + static std::shared_ptr get(m64p_GLattr attribute, int* value) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(attribute, value); + return ptr; + } + + void commandToExecute() override + { + ::CoreVideo_GL_GetAttribute(m_attribute, m_value); + } + private: + void set(m64p_GLattr attribute, int* value) + { + m_attribute = attribute; + m_value = value; + } + + m64p_GLattr m_attribute; + int* m_value; + }; + + class CoreVideoGLSwapBuffersCommand : public OpenGlCommand + { + public: + CoreVideoGLSwapBuffersCommand() : + OpenGlCommand(false, false, "CoreVideo_GL_SwapBuffers", false) + { + } + + static std::shared_ptr get(std::function swapBuffersCallback) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(swapBuffersCallback); + return ptr; + } + + void commandToExecute() override + { + ::CoreVideo_GL_SwapBuffers(); + m_swapBuffersCallback(); + } + private: + void set(std::function swapBuffersCallback) + { + m_swapBuffersCallback = swapBuffersCallback; + } + + std::function m_swapBuffersCallback; + }; +#else + //Zilmar API functions + class WindowsStartCommand : public OpenGlCommand + { + public: + WindowsStartCommand() : + OpenGlCommand(true, false, "WindowsStartCommand", false) + { + } + + static std::shared_ptr get(bool& returnValue) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(returnValue); + return ptr; + } + + void commandToExecute() override + { + *m_returnValue = WindowsWGL::start(); + } + + private: + void set(bool& returnValue) + { + m_returnValue = &returnValue; + } + + bool* m_returnValue; + }; + + class WindowsStopCommand : public OpenGlCommand + { + public: + WindowsStopCommand() : + OpenGlCommand(true, false, "WindowsStopCommand", false) + { + } + + static std::shared_ptr get() + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(); + return ptr; + } + + void commandToExecute() override + { + WindowsWGL::stop(); + } + + private: + void set() + { + } + }; + + class WindowsSwapBuffersCommand : public OpenGlCommand + { + public: + WindowsSwapBuffersCommand() : + OpenGlCommand(false, false, "WindowsSwapBuffersCommand", false) + { + } + + static std::shared_ptr get(std::function swapBuffersCallback) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(swapBuffersCallback); + return ptr; + } + + void commandToExecute() override + { + WindowsWGL::swapBuffers(); + m_swapBuffersCallback(); + } + private: + void set(std::function swapBuffersCallback) + { + m_swapBuffersCallback = swapBuffersCallback; + } + + std::function m_swapBuffersCallback; + }; + +#endif +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp new file mode 100644 index 000000000..9092937f1 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp @@ -0,0 +1,1549 @@ +#include "opengl_Wrapper.h" +#include "opengl_WrappedFunctions.h" +#include "splice-pool.hpp" +#include "Graphics/OpenGLContext/GLFunctions.h" +#include + +namespace opengl { + + bool FunctionWrapper::m_threaded_wrapper = false; + bool FunctionWrapper::m_shutdown = false; + int FunctionWrapper::m_swapBuffersQueued = 0; + bool FunctionWrapper::m_fastVertexAttributes = false; + std::thread FunctionWrapper::m_commandExecutionThread; + std::mutex FunctionWrapper::m_condvarMutex; + std::condition_variable FunctionWrapper::m_condition; + BlockingQueue> FunctionWrapper::m_commandQueue; + + + void FunctionWrapper::executeCommand(std::shared_ptr _command) + { + m_commandQueue.push(_command); + _command->waitOnCommand(); + } + + void FunctionWrapper::executePriorityCommand(std::shared_ptr _command) + { + m_commandQueue.pushBack(_command); + _command->waitOnCommand(); + } + + void FunctionWrapper::commandLoop() + { + while (!m_shutdown || m_commandQueue.size() != 0) { + std::shared_ptr command; + + if (m_commandQueue.tryPop(command, std::chrono::milliseconds(10))) { + command->performCommand(); + } + } + } + + void FunctionWrapper::setThreadedMode(u32 _threaded) + { +#ifdef GL_DEBUG + //_threaded = 0; +#endif + + if (_threaded == 1) { + m_threaded_wrapper = true; + m_shutdown = false; + m_commandExecutionThread = std::thread(&FunctionWrapper::commandLoop); + } else { + m_threaded_wrapper = false; + m_shutdown = true; + } + } + + void FunctionWrapper::wrBlendFunc(GLenum sfactor, GLenum dfactor) + { + if (m_threaded_wrapper) + executeCommand(GlBlendFuncCommand::get(sfactor, dfactor)); + else + ptrBlendFunc(sfactor, dfactor); + } + + void FunctionWrapper::wrPixelStorei(GLenum pname, GLint param) + { + if (m_threaded_wrapper) + executeCommand(GlPixelStoreiCommand::get(pname, param)); + else + ptrPixelStorei(pname, param); + } + + void FunctionWrapper::wrClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + if (m_threaded_wrapper) + executeCommand(GlClearColorCommand::get(red, green, blue, alpha)); + else + ptrClearColor(red, green, blue, alpha); + } + + void FunctionWrapper::wrCullFace(GLenum mode) + { + if (m_threaded_wrapper) + executeCommand(GlCullFaceCommand::get(mode)); + else + ptrCullFace(mode); + } + + void FunctionWrapper::wrDepthFunc(GLenum func) + { + if (m_threaded_wrapper) + executeCommand(GlDepthFuncCommand::get(func)); + else + ptrDepthFunc(func); + } + + void FunctionWrapper::wrDepthMask(GLboolean flag) + { + if (m_threaded_wrapper) + executeCommand(GlDepthMaskCommand::get(flag)); + else + ptrDepthMask(flag); + } + + void FunctionWrapper::wrDisable(GLenum cap) + { + if (m_threaded_wrapper) + executeCommand(GlDisableCommand::get(cap)); + else + ptrDisable(cap); + } + + void FunctionWrapper::wrEnable(GLenum cap) + { + if (m_threaded_wrapper) + executeCommand(GlEnableCommand::get(cap)); + else + ptrEnable(cap); + } + + void FunctionWrapper::wrDisablei(GLenum target, GLuint index) + { + if (m_threaded_wrapper) + executeCommand(GlDisableiCommand::get(target, index)); + else + ptrDisablei(target, index); + } + + void FunctionWrapper::wrEnablei(GLenum target, GLuint index) + { + if (m_threaded_wrapper) + executeCommand(GlEnableiCommand::get(target, index)); + else + ptrEnablei(target, index); + } + + void FunctionWrapper::wrPolygonOffset(GLfloat factor, GLfloat units) + { + if (m_threaded_wrapper) + executeCommand(GlPolygonOffsetCommand::get(factor, units)); + else + ptrPolygonOffset(factor, units); + } + + void FunctionWrapper::wrScissor(GLint x, GLint y, GLsizei width, GLsizei height) + { + if (m_threaded_wrapper) + executeCommand(GlScissorCommand::get(x, y, width, height)); + else + ptrScissor(x, y, width, height); + } + + void FunctionWrapper::wrViewport(GLint x, GLint y, GLsizei width, GLsizei height) + { + if (m_threaded_wrapper) + executeCommand(GlViewportCommand::get(x, y, width, height)); + else + ptrViewport(x, y, width, height); + } + + void FunctionWrapper::wrBindTexture(GLenum target, GLuint texture) + { + if (m_threaded_wrapper) + executeCommand(GlBindTextureCommand::get(target, texture)); + else + ptrBindTexture(target, texture); + } + + void FunctionWrapper::wrTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) + { + if (m_threaded_wrapper) { + std::unique_ptr data(nullptr); + int totalBytes = getTextureBytes(format, type, width, height); + if(totalBytes > 0 && pixels != nullptr) { + data = std::unique_ptr(new u8[totalBytes]); + std::copy_n(reinterpret_cast(pixels), totalBytes, data.get()); + } + + if (totalBytes < 0) { + LOG(LOG_ERROR, "INVALID TEXTURE: format=%d type=%d total=%d", format, type, totalBytes); + } + + executeCommand(GlTexImage2DCommand::get(target, level, internalformat, width, height, border, + format, type, std::move(data))); + } + else + ptrTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + } + + void FunctionWrapper::wrTexParameteri(GLenum target, GLenum pname, GLint param) + { + if (m_threaded_wrapper) + executeCommand(GlTexParameteriCommand::get(target, pname, param)); + else + ptrTexParameteri(target, pname, param); + } + + void FunctionWrapper::wrGetIntegerv(GLenum pname, GLint* data) + { + if (m_threaded_wrapper) + executeCommand(GlGetIntegervCommand::get(pname, data)); + else + ptrGetIntegerv(pname, data); + } + + const GLubyte* FunctionWrapper::wrGetString(GLenum name) + { + const GLubyte* returnValue; + + if (m_threaded_wrapper) + executeCommand(GlGetStringCommand::get(name, returnValue)); + else + returnValue = ptrGetString(name); + + return returnValue; + } + + void FunctionWrapper::wrReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) + { + if (m_threaded_wrapper) + if (pixels == nullptr) { + GlReadPixelsAsyncCommand::setBoundBuffer(GlBindBufferCommand::getBoundBuffer(GL_PIXEL_PACK_BUFFER)); + executeCommand(GlReadPixelsAsyncCommand::get(x, y, width, height, format, type)); + } else { + executeCommand(GlReadPixelsCommand::get(x, y, width, height, format, type, pixels)); + } + else + ptrReadPixels(x, y, width, height, format, type, pixels); + } + + void FunctionWrapper::wrTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) + { + if (m_threaded_wrapper) { + int totalBytes = getTextureBytes(format, type, width, height); + std::unique_ptr data(nullptr); + if(totalBytes > 0 && pixels != nullptr) { + data = std::unique_ptr(new u8[totalBytes]); + std::copy_n(reinterpret_cast(pixels), totalBytes, data.get()); + } + + if (totalBytes < 0) { + LOG(LOG_ERROR, "INVALID TEXTURE: format=%d type=%d total=%d", format, type, totalBytes); + } + + executeCommand(GlTexSubImage2DUnbufferedCommand::get(target, level, xoffset, yoffset, width, height, format, type, std::move(data))); + } + else + ptrTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + } + + void FunctionWrapper::wrDrawArrays(GLenum mode, GLint first, GLsizei count) + { + if (m_threaded_wrapper) { + if (m_fastVertexAttributes) { + executeCommand(GlDrawArraysCommand::get(mode, first, count)); + } else { + splicer::Node>* node = GlVertexAttribPointerManager::getVectorFromPool(); + const char* ptr = GlVertexAttribPointerManager::getSmallestPtr(); + node->val().assign(ptr, ptr + (count+1)*GlVertexAttribPointerManager::getStride()); + executeCommand(GlDrawArraysUnbufferedCommand::get(mode, first, count, node)); } + }else { + ptrDrawArrays(mode, first, count); + } + } + + GLenum FunctionWrapper::wrGetError() + { +#ifdef GL_DEBUG + GLenum returnValue; + + if (m_threaded_wrapper) + executeCommand(GlGetErrorCommand::get(returnValue)); + else + returnValue = ptrGetError(); + + return returnValue; +#else + return GL_NO_ERROR; +#endif + } + + void FunctionWrapper::wrDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) + { + if (m_threaded_wrapper) + { + int typeSizeBytes; + unsigned int maxElementIndex; + + switch(type) { + case GL_UNSIGNED_BYTE: + typeSizeBytes = 1; + maxElementIndex = 0; + for (int index = 0; index < count; ++index) { + unsigned int value = reinterpret_cast(indices)[index]; + if (maxElementIndex < value) maxElementIndex = value; + } + break; + case GL_UNSIGNED_SHORT: + typeSizeBytes = 2; + maxElementIndex = 0; + for (int index = 0; index < count; ++index) { + unsigned int value = reinterpret_cast(indices)[index]; + if (maxElementIndex < value) maxElementIndex = value; + } + break; + case GL_UNSIGNED_INT: + typeSizeBytes = 4; + maxElementIndex = 0; + for (int index = 0; index < count; ++index) { + unsigned int value = reinterpret_cast(indices)[index]; + if (maxElementIndex < value) maxElementIndex = value; + } + break; + default: + typeSizeBytes = 1; + maxElementIndex = 0; + for (int index = 0; index < count; ++index) { + unsigned int value = reinterpret_cast(indices)[index]; + if (maxElementIndex < value) maxElementIndex = value; + } + } + + splicer::Node>* node = GlVertexAttribPointerManager::getVectorFromPool(); + const char* ptr = GlVertexAttribPointerManager::getSmallestPtr(); + node->val().assign(ptr, ptr + (maxElementIndex+1)*GlVertexAttribPointerManager::getStride()); + + std::unique_ptr elementsCopy(new u8[count*typeSizeBytes]); + std::copy_n(reinterpret_cast(indices), count*typeSizeBytes, elementsCopy.get()); + executeCommand(GlDrawElementsUnbufferedCommand::get(mode, count, type, std::move(elementsCopy), node)); + } + else + ptrDrawElements(mode, count, type, indices); + } + + void FunctionWrapper::wrLineWidth(GLfloat width) + { + if (m_threaded_wrapper) + executeCommand(GlLineWidthCommand::get(width)); + else + ptrLineWidth(width); + } + + void FunctionWrapper::wrClear(GLbitfield mask) + { + if (m_threaded_wrapper) + executeCommand(GlClearCommand::get(mask)); + else + ptrClear(mask); + } + + void FunctionWrapper::wrClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value) + { + if (m_threaded_wrapper) { + int numValues = 0; + + switch(buffer) { + case GL_COLOR: + numValues = 4; + break; + case GL_DEPTH: + case GL_STENCIL: + numValues = 1; + break; + default: + numValues = 1; + } + + std::unique_ptr values(new GLfloat[numValues]); + std::copy_n(value, numValues, values.get()); + executeCommand(GlClearBufferfvCommand::get(buffer, drawbuffer, std::move(values))); + } else + ptrClearBufferfv(buffer, drawbuffer, value); + } + + void FunctionWrapper::wrGetFloatv(GLenum pname, GLfloat* data) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGetFloatvCommand::get(pname, data)); + else + ptrGetFloatv(pname, data); + } + + void FunctionWrapper::wrDeleteTextures(GLsizei n, const GLuint *textures) + { + if (m_threaded_wrapper) { + std::unique_ptr texture(new GLuint[n]); + std::copy_n(textures, n, texture.get()); + executeCommand(GlDeleteTexturesCommand::get(n, std::move(texture))); + } else + ptrDeleteTextures(n, textures); + } + + void FunctionWrapper::wrGenTextures(GLsizei n, GLuint* textures) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGenTexturesCommand::get(n, textures)); + else + ptrGenTextures(n, textures); + } + + void FunctionWrapper::wrTexParameterf(GLenum target, GLenum pname, GLfloat param) + { + if (m_threaded_wrapper) + executeCommand(GlTexParameterfCommand::get(target, pname, param)); + else + ptrTexParameterf(target, pname, param); + } + + void FunctionWrapper::wrActiveTexture(GLenum texture) + { + if (m_threaded_wrapper) + executeCommand(GlActiveTextureCommand::get(texture)); + else + ptrActiveTexture(texture); + } + + void FunctionWrapper::wrBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + { + if (m_threaded_wrapper) + executeCommand(GlBlendColorCommand::get(red, green, blue, alpha)); + else + ptrBlendColor(red, green, blue, alpha); + } + + void FunctionWrapper::wrReadBuffer(GLenum src) + { + if (m_threaded_wrapper) + executeCommand(GlReadBufferCommand::get(src)); + else + ptrReadBuffer(src); + } + + GLuint FunctionWrapper::wrCreateShader(GLenum type) + { + GLuint returnValue; + + if (m_threaded_wrapper) + executeCommand(GlCreateShaderCommand::get(type, returnValue)); + else + returnValue = ptrCreateShader(type); + + return returnValue; + } + + void FunctionWrapper::wrCompileShader(GLuint shader) + { + if (m_threaded_wrapper) + executeCommand(GlCompileShaderCommand::get(shader)); + else + ptrCompileShader(shader); + } + + void FunctionWrapper::wrShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) + { + if (m_threaded_wrapper) { + std::vector stringData(count); + + if (length == nullptr) { + for (unsigned int index = 0; index < stringData.size(); ++index) { + stringData[index] = string[index]; + } + } else { + for (unsigned int index = 0; index < stringData.size(); ++index) { + std::string tempString; + tempString.assign(string[index], length[index]); + stringData[index] = tempString; + } + } + + executeCommand(GlShaderSourceCommand::get(shader, stringData)); + } else + ptrShaderSource(shader, count, string, length); + } + + GLuint FunctionWrapper::wrCreateProgram() + { + GLuint returnValue; + + if (m_threaded_wrapper) + executeCommand(GlCreateProgramCommand::get(returnValue)); + else + returnValue = ptrCreateProgram(); + + return returnValue; + } + + void FunctionWrapper::wrAttachShader(GLuint program, GLuint shader) + { + if (m_threaded_wrapper) + executeCommand(GlAttachShaderCommand::get(program, shader)); + else + ptrAttachShader(program, shader); + } + + void FunctionWrapper::wrLinkProgram(GLuint program) + { + if (m_threaded_wrapper) + executeCommand(GlLinkProgramCommand::get(program)); + else + ptrLinkProgram(program); + } + + void FunctionWrapper::wrUseProgram(GLuint program) + { + if (m_threaded_wrapper) + executeCommand(GlUseProgramCommand::get(program)); + else + ptrUseProgram(program); + } + + GLint FunctionWrapper::wrGetUniformLocation(GLuint program, const GLchar *name) + { + GLint returnValue; + + if (m_threaded_wrapper) + executeCommand(GlGetUniformLocationCommand::get(program, name, returnValue)); + else + returnValue = ptrGetUniformLocation(program, name); + + return returnValue; + } + + void FunctionWrapper::wrUniform1i(GLint location, GLint v0) + { + if (m_threaded_wrapper) + executeCommand(GlUniform1iCommand::get(location, v0)); + else + ptrUniform1i(location, v0); + } + + void FunctionWrapper::wrUniform1f(GLint location, GLfloat v0) + { + if (m_threaded_wrapper) + executeCommand(GlUniform1fCommand::get(location, v0)); + else + ptrUniform1f(location, v0); + } + + void FunctionWrapper::wrUniform2f(GLint location, GLfloat v0, GLfloat v1) + { + if (m_threaded_wrapper) + executeCommand(GlUniform2fCommand::get(location, v0, v1)); + else + ptrUniform2f(location, v0, v1); + } + + void FunctionWrapper::wrUniform2i(GLint location, GLint v0, GLint v1) + { + if (m_threaded_wrapper) + executeCommand(GlUniform2iCommand::get(location, v0, v1)); + else + ptrUniform2i(location, v0, v1); + } + + void FunctionWrapper::wrUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) + { + if (m_threaded_wrapper) + executeCommand(GlUniform4iCommand::get(location, v0, v1, v2, v3)); + else + ptrUniform4i(location, v0, v1, v2, v3); + } + + + void FunctionWrapper::wrUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) + { + if (m_threaded_wrapper) + executeCommand(GlUniform4fCommand::get(location, v0, v1, v2, v3)); + else + ptrUniform4f(location, v0, v1, v2, v3); + } + + void FunctionWrapper::wrUniform3fv(GLint location, GLsizei count, const GLfloat *value) + { + if (m_threaded_wrapper) { + std::unique_ptr values(new GLfloat[3]); + std::copy_n(value, 3, values.get()); + executeCommand(GlUniform3fvCommand::get(location, count, std::move(values))); + } else + ptrUniform3fv(location, count, value); + } + + void FunctionWrapper::wrUniform4fv(GLint location, GLsizei count, const GLfloat *value) + { + if (m_threaded_wrapper) { + std::unique_ptr values(new GLfloat[4]); + std::copy_n(value, 4, values.get()); + executeCommand(GlUniform4fvCommand::get(location, count, std::move(values))); + } else + ptrUniform4fv(location, count, value); + } + + void FunctionWrapper::wrDetachShader(GLuint program, GLuint shader) + { + if (m_threaded_wrapper) + executeCommand(GlDetachShaderCommand::get(program, shader)); + else + ptrDetachShader(program, shader); + } + + void FunctionWrapper::wrDeleteShader(GLuint shader) + { + if (m_threaded_wrapper) + executeCommand(GlDeleteShaderCommand::get(shader)); + else + ptrDeleteShader(shader); + } + + void FunctionWrapper::wrDeleteProgram(GLuint program) + { + if (m_threaded_wrapper) + executeCommand(GlDeleteProgramCommand::get(program)); + else + ptrDeleteProgram(program); + } + + void FunctionWrapper::wrGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar *infoLog) + { + if (m_threaded_wrapper) + executeCommand(GlGetProgramInfoLogCommand::get(program, bufSize, length, infoLog)); + else + ptrGetProgramInfoLog(program, bufSize, length, infoLog); + } + + void FunctionWrapper::wrGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar *infoLog) + { + if (m_threaded_wrapper) + executeCommand(GlGetShaderInfoLogCommand::get(shader, bufSize, length, infoLog)); + else + ptrGetShaderInfoLog(shader, bufSize, length, infoLog); + } + + void FunctionWrapper::wrGetShaderiv(GLuint shader, GLenum pname, GLint* params) + { + if (m_threaded_wrapper) + executeCommand(GlGetShaderivCommand::get(shader, pname, params)); + else + ptrGetShaderiv(shader, pname, params); + } + + void FunctionWrapper::wrGetProgramiv(GLuint program, GLenum pname, GLint* params) + { + if (m_threaded_wrapper) + executeCommand(GlGetProgramivCommand::get(program, pname, params)); + else + ptrGetProgramiv(program, pname, params); + } + + void FunctionWrapper::wrEnableVertexAttribArray(GLuint index) + { + if (m_threaded_wrapper) { + GlVertexAttribPointerManager::enableVertexAttributeIndex(index); + executeCommand(GlEnableVertexAttribArrayCommand::get(index)); + } + else + ptrEnableVertexAttribArray(index); + } + + void FunctionWrapper::wrDisableVertexAttribArray(GLuint index) + { + if (m_threaded_wrapper) { + GlVertexAttribPointerManager::disableVertexAttributeIndex(index); + executeCommand(GlDisableVertexAttribArrayCommand::get(index)); + } + else + ptrDisableVertexAttribArray(index); + } + + void FunctionWrapper::wrVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) + { + if (m_threaded_wrapper) { + if (m_fastVertexAttributes) { + executeCommand(GlVertexAttribPointerBufferedCommand::get(index, size, type, normalized, stride, pointer)); + } else { + GlVertexAttribPointerManager::update(index, size, type, normalized, stride, pointer); + executeCommand(GlVertexAttribPointerUnbufferedCommand::get(index, size, type, normalized, stride, pointer)); + } + } else + ptrVertexAttribPointer(index, size, type, normalized, stride, pointer); + } + + void FunctionWrapper::wrBindAttribLocation(GLuint program, GLuint index, const GLchar *name) + { + if (m_threaded_wrapper) + executeCommand(GlBindAttribLocationCommand::get(program, index, name)); + else + ptrBindAttribLocation(program, index, name); + } + + void FunctionWrapper::wrVertexAttrib1f(GLuint index, GLfloat x) + { + if (m_threaded_wrapper) + executeCommand(GlVertexAttrib1fCommand::get(index, x)); + else + ptrVertexAttrib1f(index, x); + } + + void FunctionWrapper::wrVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { + if (m_threaded_wrapper) + executeCommand(GlVertexAttrib4fCommand::get(index, x, y, z, w)); + else + ptrVertexAttrib4f(index, x, y, z, w); + } + + void FunctionWrapper::wrVertexAttrib4fv(GLuint index, const GLfloat *v) + { + if (m_threaded_wrapper) { + std::unique_ptr values(new GLfloat[4]); + std::copy_n(v, 4, values.get()); + executeCommand(GlVertexAttrib4fvCommand::get(index, std::move(values))); + } else + ptrVertexAttrib4fv(index, v); + } + + void FunctionWrapper::wrDepthRangef(GLfloat n, GLfloat f) + { + if (m_threaded_wrapper) + executeCommand(GlDepthRangefCommand::get(n, f)); + else + ptrDepthRangef(n, f); + } + + void FunctionWrapper::wrClearDepthf(GLfloat d) + { + if (m_threaded_wrapper) + executeCommand(GlClearDepthfCommand::get(d)); + else + ptrClearDepthf(d); + } + + void FunctionWrapper::wrDrawBuffers(GLsizei n, const GLenum *bufs) + { + if (m_threaded_wrapper) { + std::unique_ptr bufsPtr(new GLenum[n]); + std::copy_n(bufs, n, bufsPtr.get()); + + executeCommand(GlDrawBuffersCommand::get(n, std::move(bufsPtr))); + } else + ptrDrawBuffers(n, bufs); + } + + void FunctionWrapper::wrGenFramebuffers(GLsizei n, GLuint* framebuffers) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGenFramebuffersCommand::get(n, framebuffers)); + else + ptrGenFramebuffers(n, framebuffers); + } + + void FunctionWrapper::wrBindFramebuffer(GLenum target, GLuint framebuffer) + { + if (m_threaded_wrapper) + executeCommand(GlBindFramebufferCommand::get(target, framebuffer)); + else + ptrBindFramebuffer(target, framebuffer); + } + + void FunctionWrapper::wrDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) + { + if (m_threaded_wrapper) { + std::unique_ptr framebuffersPtr(new GLuint[n]); + std::copy_n(framebuffers, n, framebuffersPtr.get()); + executeCommand(GlDeleteFramebuffersCommand::get(n, std::move(framebuffersPtr))); + } else + ptrDeleteFramebuffers(n, framebuffers); + } + + void FunctionWrapper::wrFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + if (m_threaded_wrapper) + executeCommand(GlFramebufferTexture2DCommand::get(target, attachment, textarget, texture, level)); + else + ptrFramebufferTexture2D(target, attachment, textarget, texture, level); + } + + void FunctionWrapper::wrTexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) + { + if (m_threaded_wrapper) + executeCommand(GlTexImage2DMultisampleCommand::get(target, samples, internalformat, width, height, fixedsamplelocations)); + else + ptrTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + } + + void FunctionWrapper::wrTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) + { + if (m_threaded_wrapper) + executeCommand(GlTexStorage2DMultisampleCommand::get(target, samples, internalformat, width, height, fixedsamplelocations)); + else + ptrTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); + } + + void FunctionWrapper::wrGenRenderbuffers(GLsizei n, GLuint* renderbuffers) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGenRenderbuffersCommand::get(n, renderbuffers)); + else + ptrGenRenderbuffers(n, renderbuffers); + } + + void FunctionWrapper::wrBindRenderbuffer(GLenum target, GLuint renderbuffer) + { + if (m_threaded_wrapper) + executeCommand(GlBindRenderbufferCommand::get(target, renderbuffer)); + else + ptrBindRenderbuffer(target, renderbuffer); + } + + void FunctionWrapper::wrRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + { + if (m_threaded_wrapper) + executeCommand(GlRenderbufferStorageCommand::get(target, internalformat, width, height)); + else + ptrRenderbufferStorage(target, internalformat, width, height); + } + + void FunctionWrapper::wrDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) + { + if (m_threaded_wrapper) { + std::unique_ptr renderbuffersPtr(new GLuint[n]); + std::copy_n(renderbuffers, n, renderbuffersPtr.get()); + executeCommand(GlDeleteRenderbuffersCommand::get(n, std::move(renderbuffersPtr))); + } else + ptrDeleteRenderbuffers(n, renderbuffers); + } + + void FunctionWrapper::wrFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + { + if (m_threaded_wrapper) + executeCommand(GlFramebufferRenderbufferCommand::get(target, attachment, renderbuffertarget, renderbuffer)); + else + ptrFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); + } + + GLenum FunctionWrapper::wrCheckFramebufferStatus(GLenum target) + { +#ifdef GL_DEBUG + GLenum returnValue; + + if (m_threaded_wrapper) + executeCommand(GlCheckFramebufferStatusCommand::get(target, returnValue)); + else + returnValue = ptrCheckFramebufferStatus(target); + + return returnValue; +#else + return GL_FRAMEBUFFER_COMPLETE; +#endif + } + + void FunctionWrapper::wrBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) + { + if (m_threaded_wrapper) + executeCommand(GlBlitFramebufferCommand::get(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter)); + else + ptrBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } + + void FunctionWrapper::wrGenVertexArrays(GLsizei n, GLuint* arrays) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGenVertexArraysCommand::get(n, arrays)); + else + ptrGenVertexArrays(n, arrays); + } + + void FunctionWrapper::wrBindVertexArray(GLuint array) + { + if (m_threaded_wrapper) + executeCommand(GlBindVertexArrayCommand::get(array)); + else + ptrBindVertexArray(array); + } + + void FunctionWrapper::wrDeleteVertexArrays(GLsizei n, const GLuint *arrays) + { + if (m_threaded_wrapper) { + std::unique_ptr arraysPtr(new GLuint[n]); + std::copy_n(arrays, n, arraysPtr.get()); + executeCommand(GlDeleteVertexArraysCommand::get(n, std::move(arraysPtr))); + } else + ptrDeleteVertexArrays(n, arrays); + } + + void FunctionWrapper::wrGenBuffers(GLsizei n, GLuint* buffers) + { + if (m_threaded_wrapper) + executePriorityCommand(GlGenBuffersCommand::get(n, buffers)); + else + ptrGenBuffers(n, buffers); + } + + void FunctionWrapper::wrBindBuffer(GLenum target, GLuint buffer) + { + if (m_threaded_wrapper) { + GlBindBufferCommand::setBoundBuffer(target, buffer); + executeCommand(GlBindBufferCommand::get(target, buffer)); + } else + ptrBindBuffer(target, buffer); + } + + void FunctionWrapper::wrBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) + { + if (m_threaded_wrapper) { + if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) + m_fastVertexAttributes = true; + + std::unique_ptr dataPtr; + if (data != nullptr) { + dataPtr.reset(new u8[size]); + std::copy_n(reinterpret_cast(data), size, dataPtr.get()); + } + executeCommand(GlBufferDataCommand::get(target, size, std::move(dataPtr), usage)); + } else + ptrBufferData(target, size, data, usage); + } + + void FunctionWrapper::wrMapBuffer(GLenum target, GLenum access) + { + if (m_threaded_wrapper) + executeCommand(GlMapBufferCommand::get(target, access)); + else + ptrMapBuffer(target, access); + } + + void* FunctionWrapper::wrMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) + { + void* returnValue; + + if (m_threaded_wrapper) { + GLuint boundPixelBuffer = GlReadPixelsAsyncCommand::getBoundBuffer(); + if (target == GL_PIXEL_PACK_BUFFER && access == GL_MAP_READ_BIT && + GlBindBufferCommand::getBoundBuffer(GL_PIXEL_PACK_BUFFER) != boundPixelBuffer) { + executeCommand(GlMapBufferRangeReadAsyncCommand::get(target, offset, length, access)); + GLuint buffer = GlBindBufferCommand::getBoundBuffer(target); + returnValue = GlMapBufferRangeReadAsyncCommand::getData(buffer, length)->data(); + } else if (access == GlMapBufferRangeWriteAsyncCommand::WRITE_ACCESS_ASYNC) { + GlMapBufferRangeWriteAsyncCommand::setTemp(target, offset, length, access); + returnValue = GlMapBufferRangeWriteAsyncCommand::getData(target, length)->data(); + } else { + executeCommand(GlMapBufferRangeCommand::get(target, offset, length, access, returnValue)); + } + } else { + returnValue = ptrMapBufferRange(target, offset, length, access); + } + + return returnValue; + } + + GLboolean FunctionWrapper::wrUnmapBuffer(GLenum target) + { + GLboolean returnValue = GL_TRUE; + + if (m_threaded_wrapper) { + + GLbitfield accessTemp = GlMapBufferRangeWriteAsyncCommand::getTempAccess(); + GLenum targetTemp = GlMapBufferRangeWriteAsyncCommand::getTempTarget(); + + if (accessTemp == GlMapBufferRangeWriteAsyncCommand::WRITE_ACCESS_ASYNC && + target == targetTemp) { + GLintptr offsetTemp = GlMapBufferRangeWriteAsyncCommand::getTempOffset(); + GLsizeiptr lengthTemp = GlMapBufferRangeWriteAsyncCommand::getTempLength(); + auto dataToCopy = GlMapBufferRangeWriteAsyncCommand::getData(targetTemp, lengthTemp); + + splicer::Node>* node = GlMapBufferRangeWriteAsyncCommand::getVectorFromPool(); + node->val().assign(dataToCopy->begin(), dataToCopy->end()); + + executeCommand(GlMapBufferRangeWriteAsyncCommand::get(targetTemp, offsetTemp, lengthTemp, accessTemp, node)); + GlMapBufferRangeWriteAsyncCommand::setTemp(0, 0, 0, 0); + } + + executeCommand(GlUnmapBufferAsyncCommand::get(target)); + } + else + returnValue = ptrUnmapBuffer(target); + + return returnValue; + } + + void FunctionWrapper::wrDeleteBuffers(GLsizei n, const GLuint *buffers) + { + if (m_threaded_wrapper) { + std::unique_ptr buffersPtr(new GLuint[n]); + std::copy_n(buffers, n, buffersPtr.get()); + executeCommand(GlDeleteBuffersCommand::get(n, std::move(buffersPtr))); + } else + ptrDeleteBuffers(n, buffers); + } + + void FunctionWrapper::wrBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) + { + if (m_threaded_wrapper) + executeCommand(GlBindImageTextureCommand::get(unit, texture, level, layered, layer, access, format)); + else + ptrBindImageTexture(unit, texture, level, layered, layer, access, format); + } + + void FunctionWrapper::wrMemoryBarrier(GLbitfield barriers) + { + if (m_threaded_wrapper) + executeCommand(GlMemoryBarrierCommand::get(barriers)); + else + ptrMemoryBarrier(barriers); + } + + void FunctionWrapper::wrTextureBarrier() + { + if (m_threaded_wrapper) + executeCommand(GlTextureBarrierCommand::get()); + else + ptrTextureBarrier(); + } + + void FunctionWrapper::wrTextureBarrierNV() + { + if (m_threaded_wrapper) + executeCommand(GlTextureBarrierNVCommand::get()); + else + ptrTextureBarrierNV(); + } + + const GLubyte* FunctionWrapper::wrGetStringi(GLenum name, GLuint index) + { + const GLubyte* returnValue; + + if (m_threaded_wrapper) + executePriorityCommand(GlGetStringiCommand::get(name, index, returnValue)); + else + returnValue = ptrGetStringi(name, index); + + return returnValue; + } + + void FunctionWrapper::wrInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) + { + if (m_threaded_wrapper) { + std::unique_ptr attachmentsPtr(new GLenum[numAttachments]); + std::copy_n(attachments, numAttachments, attachmentsPtr.get()); + executeCommand(GlInvalidateFramebufferCommand::get(target, numAttachments, std::move(attachmentsPtr))); + } else + ptrInvalidateFramebuffer(target, numAttachments, attachments); + } + + void FunctionWrapper::wrBufferStorage(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags) + { + if (m_threaded_wrapper) { + if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) + m_fastVertexAttributes = true; + + std::unique_ptr dataPtr; + if (data != nullptr) { + dataPtr.reset(new u8[size]); + std::copy_n(reinterpret_cast(data), size, dataPtr.get()); + } + + executeCommand(GlBufferStorageCommand::get(target, size, std::move(dataPtr), flags)); + } else + ptrBufferStorage(target, size, data, flags); + } + + GLsync FunctionWrapper::wrFenceSync(GLenum condition, GLbitfield flags) + { + GLsync returnValue; + + if (m_threaded_wrapper) + executePriorityCommand(GlFenceSyncCommand::get(condition, flags, returnValue)); + else + returnValue = ptrFenceSync(condition, flags); + + return returnValue; + } + + void FunctionWrapper::wrClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) + { + if (m_threaded_wrapper) + executePriorityCommand(GlClientWaitSyncCommand::get(sync, flags, timeout)); + else + ptrClientWaitSync(sync, flags, timeout); + } + + void FunctionWrapper::wrDeleteSync(GLsync sync) + { + if (m_threaded_wrapper) + executeCommand(GlDeleteSyncCommand::get(sync)); + else + ptrDeleteSync(sync); + } + + GLuint FunctionWrapper::wrGetUniformBlockIndex(GLuint program, GLchar *uniformBlockName) + { + GLuint returnValue; + + if (m_threaded_wrapper) + executeCommand(GlGetUniformBlockIndexCommand::get(program, uniformBlockName, returnValue)); + else + returnValue = ptrGetUniformBlockIndex(program, uniformBlockName); + + return returnValue; + } + + void FunctionWrapper::wrUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) + { + if (m_threaded_wrapper) + executeCommand(GlUniformBlockBindingCommand::get(program, uniformBlockIndex, uniformBlockBinding)); + else + ptrUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); + } + + void FunctionWrapper::wrGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) + { + if (m_threaded_wrapper) + executeCommand(GlGetActiveUniformBlockivCommand::get(program, uniformBlockIndex, pname, params)); + else + ptrGetActiveUniformBlockiv(program, uniformBlockIndex, pname, params); + } + + void FunctionWrapper::wrGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint* uniformIndices) + { + if (m_threaded_wrapper) + executeCommand(GlGetUniformIndicesCommand::get(program, uniformCount, uniformNames, uniformIndices)); + else + ptrGetUniformIndices(program, uniformCount, uniformNames, uniformIndices); + } + + void FunctionWrapper::wrGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint* params) + { + if (m_threaded_wrapper) + executeCommand(GlGetActiveUniformsivCommand::get(program, uniformCount, uniformIndices, pname, params)); + else + ptrGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params); + } + + void FunctionWrapper::wrBindBufferBase(GLenum target, GLuint index, GLuint buffer) + { + if (m_threaded_wrapper) + executeCommand(GlBindBufferBaseCommand::get(target, index, buffer)); + else + ptrBindBufferBase(target, index, buffer); + } + + void FunctionWrapper::wrBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) + { + if (m_threaded_wrapper) { + std::unique_ptr dataPtr; + if (data != nullptr) { + dataPtr.reset(new u8[size]); + std::copy_n(reinterpret_cast(data), size, dataPtr.get()); + } + + executeCommand(GlBufferSubDataCommand::get(target, offset, size, std::move(dataPtr))); + } else + ptrBufferSubData(target, offset, size, data); + } + + void FunctionWrapper::wrGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void *binary) + { + if (m_threaded_wrapper) + executeCommand(GlGetProgramBinaryCommand::get(program, bufSize, length, binaryFormat, binary)); + else + ptrGetProgramBinary(program, bufSize, length, binaryFormat, binary); + } + + void FunctionWrapper::wrProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) + { + if (m_threaded_wrapper) { + std::unique_ptr binaryPtr(new u8[length]); + std::copy_n(reinterpret_cast(binary), length, binaryPtr.get()); + executeCommand(GlProgramBinaryCommand::get(program, binaryFormat, std::move(binaryPtr), length)); + } else + ptrProgramBinary(program, binaryFormat, binary, length); + } + + void FunctionWrapper::wrProgramParameteri(GLuint program, GLenum pname, GLint value) + { + if (m_threaded_wrapper) + executeCommand(GlProgramParameteriCommand::get(program, pname, value)); + else + ptrProgramParameteri(program, pname, value); + } + + void FunctionWrapper::wrTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + if (m_threaded_wrapper) + executeCommand(GlTexStorage2DCommand::get(target, levels, internalformat, width, height)); + else + ptrTexStorage2D(target, levels, internalformat, width, height); + } + + void FunctionWrapper::wrTextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + if (m_threaded_wrapper) + executeCommand(GlTextureStorage2DCommand::get(texture, levels, internalformat, width, height)); + else + ptrTextureStorage2D(texture, levels, internalformat, width, height); + } + + void FunctionWrapper::wrTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) + { + if (m_threaded_wrapper) { + std::unique_ptr data(nullptr); + + int totalBytes = getTextureBytes(format, type, width, height); + if(totalBytes > 0 && pixels != nullptr) { + data = std::unique_ptr(new u8[totalBytes]); + std::copy_n(reinterpret_cast(pixels), totalBytes, data.get()); + } + + if (totalBytes < 0) { + LOG(LOG_ERROR, "INVALID TEXTURE: format=%d type=%d total=%d", format, type, totalBytes); + } + + executeCommand(GlTextureSubImage2DUnbufferedCommand::get(texture, level, xoffset, yoffset, + width, height, format, type, + std::move(data))); + } else + ptrTextureSubImage2D(texture, level, xoffset, yoffset, width, height, format, type, pixels); + } + + void FunctionWrapper::wrTextureStorage2DMultisample(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) + { + if (m_threaded_wrapper) + executeCommand(GlTextureStorage2DMultisampleCommand::get(texture, target, samples, internalformat, width, height, fixedsamplelocations)); + else + ptrTextureStorage2DMultisample(texture, target, samples, internalformat, width, height, fixedsamplelocations); + } + + void FunctionWrapper::wrTextureParameteri(GLuint texture, GLenum pname, GLint param) + { + if (m_threaded_wrapper) + executeCommand(GlTextureParameteriCommand::get(texture, pname, param)); + else + ptrTextureParameteri(texture, pname, param); + } + + void FunctionWrapper::wrTextureParameterf(GLuint texture, GLenum pname, GLfloat param) + { + if (m_threaded_wrapper) + executeCommand(GlTextureParameterfCommand::get(texture, pname, param)); + else + ptrTextureParameterf(texture, pname, param); + } + + void FunctionWrapper::wrCreateTextures(GLenum target, GLsizei n, GLuint* textures) + { + if (m_threaded_wrapper) + executePriorityCommand(GlCreateTexturesCommand::get(target, n, textures)); + else + ptrCreateTextures(target, n, textures); + } + + void FunctionWrapper::wrCreateBuffers(GLsizei n, GLuint* buffers) + { + if (m_threaded_wrapper) + executePriorityCommand(GlCreateBuffersCommand::get(n, buffers)); + else + ptrCreateBuffers(n, buffers); + } + + void FunctionWrapper::wrCreateFramebuffers(GLsizei n, GLuint* framebuffers) + { + if (m_threaded_wrapper) + executePriorityCommand(GlCreateFramebuffersCommand::get(n, framebuffers)); + else + ptrCreateFramebuffers(n, framebuffers); + } + + void FunctionWrapper::wrNamedFramebufferTexture(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) + { + if (m_threaded_wrapper) + executeCommand(GlNamedFramebufferTextureCommand::get(framebuffer, attachment, texture, level)); + else + ptrNamedFramebufferTexture(framebuffer, attachment, texture, level); + } + + void FunctionWrapper::wrDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const u16* indices, GLint basevertex) + { + if (m_threaded_wrapper) + executeCommand(GlDrawRangeElementsBaseVertexCommand::get(mode, start, end, count, type, std::move(indices), basevertex)); + else + ptrDrawRangeElementsBaseVertex(mode, start, end, count, type, std::move(indices), basevertex); + } + + void FunctionWrapper::wrFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) + { + if (m_threaded_wrapper) + executeCommand(GlFlushMappedBufferRangeCommand::get(target, offset, length)); + else + ptrFlushMappedBufferRange(target, offset, length); + } + + void FunctionWrapper::wrFinish() + { + if (m_threaded_wrapper) + executeCommand(GlFinishCommand::get()); + else + ptrFinish(); + } + + void FunctionWrapper::wrEGLImageTargetTexture2DOES(GLenum target, void* image) + { + if (m_threaded_wrapper) + executeCommand(GlEGLImageTargetTexture2DOESCommand::get(target, image)); + else + ptrEGLImageTargetTexture2DOES(target, image); + } + +#if defined(OS_ANDROID) + EGLClientBuffer FunctionWrapper::ewrGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) + { + EGLClientBuffer returnValue; + + if (m_threaded_wrapper) + executeCommand(EglGetNativeClientBufferANDROIDCommand::get(buffer, returnValue)); + else + returnValue = ptrGetNativeClientBufferANDROID(buffer); + + return returnValue; + } + +#endif + +#ifdef MUPENPLUSAPI + + void FunctionWrapper::CoreVideo_Init() + { + if (m_threaded_wrapper) + executeCommand(CoreVideoInitCommand::get()); + else + CoreVideoInitCommand::get()->performCommandSingleThreaded(); + } + + void FunctionWrapper::CoreVideo_Quit() + { + if (m_threaded_wrapper) + executeCommand(CoreVideoQuitCommand::get()); + else + CoreVideoQuitCommand::get()->performCommandSingleThreaded(); + + m_shutdown = true; + + if (m_threaded_wrapper) { + m_condition.notify_all(); + m_commandExecutionThread.join(); + } + } + + m64p_error FunctionWrapper::CoreVideo_SetVideoMode(int screenWidth, int screenHeight, int bitsPerPixel, m64p_video_mode mode, m64p_video_flags flags) + { + m64p_error returnValue; + + if (m_threaded_wrapper) + executeCommand(CoreVideoSetVideoModeCommand::get(screenWidth, screenHeight, bitsPerPixel, mode, flags, returnValue)); + else + CoreVideoSetVideoModeCommand::get(screenWidth, screenHeight, bitsPerPixel, mode, flags, returnValue)->performCommandSingleThreaded(); + + return returnValue; + } + + void FunctionWrapper::CoreVideo_GL_SetAttribute(m64p_GLattr attribute, int value) + { + if (m_threaded_wrapper) + executeCommand(CoreVideoGLSetAttributeCommand::get(attribute, value)); + else + CoreVideoGLSetAttributeCommand::get(attribute, value)->performCommandSingleThreaded(); + } + + void FunctionWrapper::CoreVideo_GL_GetAttribute(m64p_GLattr attribute, int *value) + { + if (m_threaded_wrapper) + executeCommand(CoreVideoGLGetAttributeCommand::get(attribute, value)); + else + CoreVideoGLGetAttributeCommand::get(attribute, value)->performCommandSingleThreaded(); + } + + void FunctionWrapper::CoreVideo_GL_SwapBuffers() + { + ++m_swapBuffersQueued; + + if (m_threaded_wrapper) + executeCommand(CoreVideoGLSwapBuffersCommand::get([]{ReduceSwapBuffersQueued();})); + else + CoreVideoGLSwapBuffersCommand::get([]{ReduceSwapBuffersQueued();})->performCommandSingleThreaded(); + } +#else + bool FunctionWrapper::windowsStart() + { + bool returnValue; + + if (m_threaded_wrapper) + executeCommand(WindowsStartCommand::get(returnValue)); + else + WindowsStartCommand::get(returnValue)->performCommandSingleThreaded(); + + return returnValue; + } + + void FunctionWrapper::windowsStop() + { + if (m_threaded_wrapper) + executeCommand(WindowsStopCommand::get()); + else + WindowsStopCommand::get()->performCommandSingleThreaded(); + + m_shutdown = true; + + if (m_threaded_wrapper) { + m_condition.notify_all(); + m_commandExecutionThread.join(); + } + } + + void FunctionWrapper::windowsSwapBuffers() + { + ++m_swapBuffersQueued; + + if (m_threaded_wrapper) + executeCommand(WindowsSwapBuffersCommand::get([]{ReduceSwapBuffersQueued();})); + else + WindowsSwapBuffersCommand::get([]{ReduceSwapBuffersQueued();})->performCommandSingleThreaded(); + } + +#endif + + void FunctionWrapper::ReduceSwapBuffersQueued() + { + --m_swapBuffersQueued; + + if (m_swapBuffersQueued <= MAX_SWAP) { + m_condition.notify_all(); + } + } + + void FunctionWrapper::WaitForSwapBuffersQueued() + { + std::unique_lock lock(m_condvarMutex); + + if (!m_shutdown && m_swapBuffersQueued > MAX_SWAP) { + m_condition.wait(lock, []{return FunctionWrapper::m_swapBuffersQueued <= MAX_SWAP;}); + } + } + + + int FunctionWrapper::getTextureBytes(GLenum format, GLenum type, int width, int height) + { + int components = 0; + int bytesPerPixel = 0; + + switch(format) + { + case GL_RED: + components = 1; + break; + case GL_RG: + components = 2; + break; + case GL_RGB: + case GL_BGR: + components = 3; + break; + case GL_RGBA: + case GL_BGRA: + components = 4; + break; + case GL_RED_INTEGER: + components = 1; + break; + case GL_RG_INTEGER: + components = 2; + break; + case GL_RGB_INTEGER: + case GL_BGR_INTEGER: + components = 3; + break; + case GL_RGBA_INTEGER: + case GL_BGRA_INTEGER: + components = 4; + break; + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + components = 1; + break; + case GL_DEPTH_STENCIL: + components = 2; + break; + default: + components = -1; + } + + switch(type) + { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + bytesPerPixel = components*1; + break; + case GL_UNSIGNED_SHORT: + case GL_SHORT: + bytesPerPixel = components*2; + break; + case GL_UNSIGNED_INT: + case GL_INT: + bytesPerPixel = components*4; + break; + case GL_HALF_FLOAT: + bytesPerPixel = components*2; + break; + case GL_FLOAT: + bytesPerPixel = components*4; + break; + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + bytesPerPixel = 1; + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + bytesPerPixel = 2; + break; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + bytesPerPixel = 4; + break; + default: + bytesPerPixel = -1; + } + + int textureSize = bytesPerPixel*width*height; + + if (textureSize < 0) + { + std::stringstream log; + log << "Invalid texture params: component=" << std::dec << components + << " bytesPerPixel=" << bytesPerPixel + << " format=0x" << std::hex << format + << " type=0x" << type + << " width=" << std::dec << width + << " height=" << height + << " size=" << bytesPerPixel*width*height; + LOG(LOG_ERROR, log.str().c_str()); + } + + return textureSize; + } +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h new file mode 100644 index 000000000..a03a34172 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h @@ -0,0 +1,198 @@ +#pragma once + +#include "Graphics/OpenGLContext/GLFunctions.h" +#include "BlockingQueue.h" +#include "opengl_WrappedFunctions.h" +#include "splice-pool.hpp" +#include "opengl_Command.h" +#include + +#ifdef MUPENPLUSAPI +#include +#endif + +namespace opengl { + + class FunctionWrapper + { + private: + static void executeCommand(std::shared_ptr _command); + + static void executePriorityCommand(std::shared_ptr _command); + + static void commandLoop(); + + static BlockingQueue> m_commandQueue; + + static bool m_threaded_wrapper; + static bool m_shutdown; + static int m_swapBuffersQueued; + static bool m_fastVertexAttributes; + static std::thread m_commandExecutionThread; + static std::mutex m_condvarMutex; + static std::condition_variable m_condition; + + static const int MAX_SWAP = 2; + + public: + static void setThreadedMode(u32 _threaded); + + static void wrBlendFunc(GLenum sfactor, GLenum dfactor); + static void wrPixelStorei(GLenum pname, GLint param); + static void wrClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + static void wrCullFace(GLenum mode); + static void wrDepthFunc(GLenum func); + static void wrDepthMask(GLboolean flag); + static void wrDisable(GLenum cap); + static void wrEnable(GLenum cap); + static void wrDisablei(GLenum target, GLuint index); + static void wrEnablei(GLenum target, GLuint index); + static void wrPolygonOffset(GLfloat factor, GLfloat units); + + static void wrScissor(GLint x, GLint y, GLsizei width, GLsizei height); + static void wrViewport(GLint x, GLint y, GLsizei width, GLsizei height); + static void wrBindTexture(GLenum target, GLuint texture); + static void wrTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); + static void wrTexParameteri(GLenum target, GLenum pname, GLint param); + static void wrGetIntegerv(GLenum pname, GLint* data); + static const GLubyte* wrGetString(GLenum name); + + static void wrReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); + static void wrTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); + static void wrDrawArrays(GLenum mode, GLint first, GLsizei count); + static GLenum wrGetError(); + static void wrDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); + static void wrLineWidth(GLfloat width); + static void wrClear(GLbitfield mask); + static void wrClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value); + static void wrGetFloatv(GLenum pname, GLfloat* data); + static void wrDeleteTextures(GLsizei n, const GLuint *textures); + static void wrGenTextures(GLsizei n, GLuint* textures); + static void wrTexParameterf(GLenum target, GLenum pname, GLfloat param); + static void wrActiveTexture(GLenum texture); + static void wrBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + static void wrReadBuffer(GLenum src); + + static GLuint wrCreateShader(GLenum type); + static void wrCompileShader(GLuint shader); + static void wrShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); + static GLuint wrCreateProgram(); + static void wrAttachShader(GLuint program, GLuint shader); + static void wrLinkProgram(GLuint program); + static void wrUseProgram(GLuint program); + static GLint wrGetUniformLocation(GLuint program, const GLchar *name); + static void wrUniform1i(GLint location, GLint v0); + static void wrUniform1f(GLint location, GLfloat v0); + static void wrUniform2f(GLint location, GLfloat v0, GLfloat v1); + static void wrUniform2i(GLint location, GLint v0, GLint v1); + static void wrUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + + static void wrUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + static void wrUniform3fv(GLint location, GLsizei count, const GLfloat *value); + static void wrUniform4fv(GLint location, GLsizei count, const GLfloat *value); + static void wrDetachShader(GLuint program, GLuint shader); + static void wrDeleteShader(GLuint shader); + static void wrDeleteProgram(GLuint program); + static void wrGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar *infoLog); + static void wrGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar *infoLog); + static void wrGetShaderiv(GLuint shader, GLenum pname, GLint* params); + static void wrGetProgramiv(GLuint program, GLenum pname, GLint* params); + + static void wrEnableVertexAttribArray(GLuint index); + static void wrDisableVertexAttribArray(GLuint index); + static void wrVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); + static void wrBindAttribLocation(GLuint program, GLuint index, const GLchar *name); + static void wrVertexAttrib1f(GLuint index, GLfloat x); + static void wrVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + static void wrVertexAttrib4fv(GLuint index, const GLfloat *v); + + static void wrDepthRangef(GLfloat n, GLfloat f); + static void wrClearDepthf(GLfloat d); + + static void wrDrawBuffers(GLsizei n, const GLenum *bufs); + static void wrGenFramebuffers(GLsizei n, GLuint* framebuffers); + static void wrBindFramebuffer(GLenum target, GLuint framebuffer); + static void wrDeleteFramebuffers(GLsizei n, const GLuint *framebuffers); + static void wrFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + static void wrTexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); + static void wrTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); + static void wrGenRenderbuffers(GLsizei n, GLuint* renderbuffers); + static void wrBindRenderbuffer(GLenum target, GLuint renderbuffer); + static void wrRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + static void wrDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers); + static void wrFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + static GLenum wrCheckFramebufferStatus(GLenum target); + static void wrBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + static void wrGenVertexArrays(GLsizei n, GLuint* arrays); + static void wrBindVertexArray(GLuint array); + static void wrDeleteVertexArrays(GLsizei n, const GLuint *arrays); + static void wrGenBuffers(GLsizei n, GLuint* buffers); + static void wrBindBuffer(GLenum target, GLuint buffer); + static void wrBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage); + static void wrMapBuffer(GLenum target, GLenum access); + static void* wrMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + static GLboolean wrUnmapBuffer(GLenum target); + static void wrDeleteBuffers(GLsizei n, const GLuint *buffers); + static void wrBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); + static void wrMemoryBarrier(GLbitfield barriers); + static void wrTextureBarrier(); + static void wrTextureBarrierNV(); + static const GLubyte* wrGetStringi(GLenum name, GLuint index); + static void wrInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); + static void wrBufferStorage(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); + static GLsync wrFenceSync(GLenum condition, GLbitfield flags); + static void wrClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); + static void wrDeleteSync(GLsync sync); + + static GLuint wrGetUniformBlockIndex(GLuint program, GLchar *uniformBlockName); + static void wrUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + static void wrGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); + static void wrGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint* uniformIndices); + static void wrGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint* params); + static void wrBindBufferBase(GLenum target, GLuint index, GLuint buffer); + static void wrBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data); + + static void wrGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, void *binary); + static void wrProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); + static void wrProgramParameteri(GLuint program, GLenum pname, GLint value); + + static void wrTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + static void wrTextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + static void wrTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); + static void wrTextureStorage2DMultisample(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); + static void wrTextureParameteri(GLuint texture, GLenum pname, GLint param); + static void wrTextureParameterf(GLuint texture, GLenum pname, GLfloat param); + static void wrCreateTextures(GLenum target, GLsizei n, GLuint* textures); + static void wrCreateBuffers(GLsizei n, GLuint* buffers); + static void wrCreateFramebuffers(GLsizei n, GLuint* framebuffers); + static void wrNamedFramebufferTexture(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); + static void wrDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const u16* indices, GLint basevertex); + static void wrFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); + static void wrFinish(); + static void wrEGLImageTargetTexture2DOES(GLenum target, void* image); + +#if defined(OS_ANDROID) + static EGLClientBuffer ewrGetNativeClientBufferANDROID(const AHardwareBuffer *buffer); +#endif + +#ifdef MUPENPLUSAPI + //Vid_ext functions + static void CoreVideo_Init(); + static void CoreVideo_Quit(); + static m64p_error CoreVideo_SetVideoMode(int screenWidth, int screenHeight, int bitsPerPixel, m64p_video_mode mode, m64p_video_flags flags); + static void CoreVideo_GL_SetAttribute(m64p_GLattr attribute, int value); + static void CoreVideo_GL_GetAttribute(m64p_GLattr attribute, int *value); + static void CoreVideo_GL_SwapBuffers(); +#else + //Windows GL context functions + static bool windowsStart(); + static void windowsStop(); + static void windowsSwapBuffers(); +#endif + + static void ReduceSwapBuffersQueued(); + static void WaitForSwapBuffersQueued(); + + static int getTextureBytes(GLenum format, GLenum type, int width, int height); + }; +} diff --git a/src/Graphics/OpenGLContext/ThreadedOpenGl/splice-pool.hpp b/src/Graphics/OpenGLContext/ThreadedOpenGl/splice-pool.hpp new file mode 100644 index 000000000..7c9fe9018 --- /dev/null +++ b/src/Graphics/OpenGLContext/ThreadedOpenGl/splice-pool.hpp @@ -0,0 +1,1005 @@ +/****************************************************************************** + Copyright (c) 2016 Connor Manning + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +******************************************************************************/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace splicer +{ + +template class Stack; +template class SplicePool; +template class UniqueStack; + +template +class Node +{ + friend class Stack; + +public: + explicit Node(Node* next = nullptr) : m_val(), m_next(next) { } + + template + void construct(Args&&... args) + { + new (&m_val) T(std::forward(args)...); + } + + T& operator=(const T& val) + { + m_val = val; + return m_val; + } + + T& operator*() { return m_val; } + const T& operator*() const { return m_val; } + + T& val() { return m_val; } + const T& val() const { return m_val; } + + T* operator->() { return &m_val; } + const T* operator->() const { return &m_val; } + + Node* next() { return m_next; } + const Node* next() const { return m_next; } + +private: + void setNext(Node* node) { m_next = node; } + + T m_val; + Node* m_next; +}; + +template +class Stack +{ + friend class UniqueStack; + +public: + Stack() : m_tail(nullptr), m_head(nullptr), m_size(0) { } + + Stack(const Stack& other) + : m_tail(other.m_tail) + , m_head(other.m_head) + , m_size(other.m_size) + { } + + Stack& operator=(const Stack& other) + { + m_tail = other.m_tail; + m_head = other.m_head; + m_size = other.m_size; + return *this; + } + + Stack(Stack&& other) + : m_tail(other.m_tail) + , m_head(other.m_head) + , m_size(other.m_size) + { + other.clear(); + } + + Stack& operator=(Stack&& other) + { + m_tail = other.m_tail; + m_head = other.m_head; + m_size = other.m_size; + other.clear(); + return *this; + } + + void push(Node* node) + { + assert(!m_tail || m_size); + + node->setNext(m_head); + m_head = node; + + if (!m_size) m_tail = node; + ++m_size; + } + + void push(Stack& other) + { + if (other.empty()) return; + + push(other.m_tail); + m_head = other.head(); + m_size += other.size() - 1; // Tail has already been accounted for. + other.clear(); + } + + void pushBack(Node* node) + { + // The incoming node will be our new tail - make sure it ends the chain. + node->setNext(nullptr); + + if (empty()) m_head = node; + else m_tail->setNext(node); + + m_tail = node; + ++m_size; + } + + void pushBack(Stack& other) + { + if (!empty()) + { + m_tail->setNext(other.head()); + m_tail = other.tail(); + m_size += other.size(); + other.clear(); + } + else + { + push(other); + } + } + + template + bool sortedBy(Compare compare) + { + Node* node(m_head); + + while (node) + { + if (node->next() && compare(**node->next(), **node)) + { + return false; + } + + node = node->next(); + } + + return true; + } + + // Preconditions: this stack is sorted according to this comparator. + // + // This operation has complexity O(n), n being the stack size. + template + void push(Node* node, Compare compare) + { + assert(sortedBy(compare)); + + if (empty() || compare(**node, **m_head)) + { + push(node); + } + else + { + Node* before(m_head); + + while (before->next() && compare(**before->next(), **node)) + { + before = before->next(); + } + + node->setNext(before->next()); + before->setNext(node); + + ++m_size; + } + } + + // Preconditions: both this stack, and the incoming stack, are sorted + // according to this comparator. + // + // This operation has complexity O(m * n), where m and n are the sizes of + // the stacks. It is intended only for stacks known to be small. + template + void push(Stack& other, Compare compare) + { + assert(sortedBy(compare)); + assert(other.sortedBy(compare)); + + Node* a(m_head); + Node* b(other.head()); + + if (!a) + { + *this = other; + return; + } + else if (!b) + { + return; + } + + // Insert whatever we can from B prior to the start of A. + if (compare(**b, **a)) + { + while (b->next() && compare(**b->next(), **a)) + { + b = b->next(); + } + + Node* nextB(b->next()); + b->setNext(m_head); + b = nextB; + + m_head = other.head(); + } + + // At the top of this loop, the position of B needs to be inserted + // somewhere (but not necessarily immediately) after the position of A. + while (a && b) + { + // Either A < B, or !(B < A), i.e. A <= B. + assert(compare(**a, **b) || !compare(**b, **a)); + + // First, progress A to the point at which B should be inserted + // immediately after A. + while (a->next() && compare(**a->next(), **b)) + { + a = a->next(); + } + + // Then, insert the range starting with B, to the position ahead of + // B (e.g. B + n) such that compare(*(B + n), A.next()) == true. + Node* nextA(a->next()); + a->setNext(b); + a = nextA; + + if (a) + { + // Splice the applicable range from B into A. + while (b->next() && compare(**b->next(), **a)) + { + b = b->next(); + } + + Node* nextB(b->next()); + b->setNext(a); + b = nextB; + } + } + + // If B is at the end, then the insertion is complete. Otherwise, + // the rest of B needs to be appended to our tail. + if (b) m_tail = other.tail(); + + m_size += other.size(); + } + + Node* pop() + { + Node* node(m_head); + if (m_head) + { + m_head = m_head->next(); + if (!--m_size) m_tail = nullptr; + } + return node; + } + + Stack popStack(std::size_t count) + { + Stack other; + + if (count >= size()) + { + swap(other); + } + else if (count && !empty()) + { + Node* tail(m_head); + for (std::size_t i(0); i < count - 1; ++i) tail = tail->next(); + + other.m_head = m_head; + m_head = tail->next(); + + tail->setNext(nullptr); + other.m_tail = tail; + + other.m_size = count; + m_size -= count; + } + + return other; + } + + bool empty() const { return !m_head; } + std::size_t size() const { return m_size; } + + void print(std::size_t maxElements = 20) const + { + if (Node* current = m_head) + { + std::size_t i(0); + + while (current && i++ < maxElements) + { + std::cout << current->val() << " "; + current = current->next(); + } + + if (current) std::cout << "and more..."; + + std::cout << std::endl; + } + else + { + std::cout << "(empty)" << std::endl; + } + } + + void swap(Stack& other) + { + std::swap(*this, other); + } + + Node* head() { return m_head; } + const Node* head() const { return m_head; } + + class Iterator; + + class ConstIterator + { + friend class Iterator; + + public: + explicit ConstIterator(const Node* node) : m_node(node) { } + + ConstIterator& operator++() + { + m_node = m_node->next(); + return *this; + } + + ConstIterator operator++(int) + { + Iterator it(m_node); + m_node = m_node->next(); + return it; + } + + const T& operator*() const { return **m_node; } + + bool operator!=(const ConstIterator& other) const + { + return m_node != other.m_node; + } + + bool operator!=(const Iterator& other) const + { + return m_node != other.m_node; + } + + private: + const Node* m_node; + }; + + class Iterator + { + friend class ConstIterator; + + public: + explicit Iterator(Node* node) : m_node(node) { } + + Iterator& operator++() + { + m_node = m_node->next(); + return *this; + } + + Iterator operator++(int) + { + Iterator it(m_node); + m_node = m_node->next(); + return it; + } + + T& operator*() { return **m_node; } + const T& operator*() const { return **m_node; } + + bool operator!=(const ConstIterator& other) const + { + return m_node != other.m_node; + } + + bool operator!=(const Iterator& other) const + { + return m_node != other.m_node; + } + + private: + Node* m_node; + }; + + Iterator begin() { return Iterator(head()); } + ConstIterator begin() const { return ConstIterator(head()); } + ConstIterator cbegin() const { return begin(); } + + Iterator end() { return Iterator(nullptr); } + ConstIterator end() const { return ConstIterator(nullptr); } + ConstIterator cend() const { return end(); } + +protected: + void clear() + { + m_head = nullptr; + m_tail = nullptr; + m_size = 0; + } + +private: + Node* tail() { return m_tail; } + const Node* tail() const { return m_tail; } + + Node* m_tail; + Node* m_head; + std::size_t m_size; +}; + +template +class UniqueNode +{ +public: + explicit UniqueNode(SplicePool& splicePool) noexcept + : m_splicePool(splicePool) + , m_node(nullptr) + { } + + UniqueNode(SplicePool& splicePool, Node* node) noexcept + : m_splicePool(splicePool) + , m_node(node) + { } + + UniqueNode(UniqueNode&& other) + : m_splicePool(other.m_splicePool) + , m_node(other.release()) + { } + + UniqueNode& operator=(UniqueNode&& other) + { + m_node = other.release(); + return *this; + } + + UniqueNode(const UniqueNode&) = delete; + UniqueNode& operator=(const UniqueNode&) = delete; + + ~UniqueNode() { reset(); } + + bool empty() const { return m_node == nullptr; } + + Node* release() + { + Node* result(m_node); + m_node = nullptr; + return result; + } + + void reset(Node* node = nullptr) + { + if (m_node) m_splicePool.release(m_node); + m_node = node; + } + + void swap(UniqueNode& other) + { + Node* copy(m_node); + m_node = other.m_node; + other.m_node = copy; + } + + Node* get() const { return m_node; } + explicit operator bool() const { return m_node != nullptr; } + + T& operator*() { return **m_node; } + const T& operator*() const { return **m_node; } + + T* operator->() { return &m_node->val(); } + const T* operator->() const { return &m_node->val(); } + + SplicePool& pool() { return m_splicePool; } + const SplicePool& pool() const { return m_splicePool; } + +private: + SplicePool& m_splicePool; + Node* m_node; +}; + +template +class UniqueStack +{ +public: + using Iterator = typename Stack::Iterator; + using ConstIterator = typename Stack::ConstIterator; + using NodeType = typename SplicePool::NodeType; + using UniqueNodeType = typename SplicePool::UniqueNodeType; + + explicit UniqueStack(SplicePool& splicePool) + : m_splicePool(splicePool) + , m_stack() + { } + + UniqueStack(SplicePool& splicePool, Stack&& stack) + : m_splicePool(splicePool) + , m_stack(stack) + { + stack.clear(); + } + + explicit UniqueStack(UniqueNodeType&& node) + : m_splicePool(node.pool()) + , m_stack() + { + push(std::move(node)); + } + + UniqueStack(UniqueStack&& other) + : m_splicePool(other.m_splicePool) + , m_stack(other.release()) + { } + + UniqueStack& operator=(UniqueStack&& other) + { + reset(other.release()); + return *this; + } + + ~UniqueStack() { m_splicePool.release(std::move(m_stack)); } + + Stack release() + { + Stack other(m_stack); + m_stack.clear(); + return other; + } + + void reset(Stack&& other) + { + m_splicePool.release(std::move(m_stack)); + m_stack = other; + other.clear(); + } + + void reset() + { + m_splicePool.release(std::move(m_stack)); + } + + // Push to front. + void push(Node* node) { m_stack.push(node); } + void push(Stack& other) { m_stack.push(other); } + void push(Stack&& other) { m_stack.push(other); other.clear(); } + + void push(UniqueNodeType&& node) + { + Node* pushing(node.release()); + m_stack.push(pushing); + } + + void push(UniqueStack&& other) + { + Stack pushing(other.release()); + m_stack.push(pushing); + } + + // Push to back. + void pushBack(Node* node) { m_stack.pushBack(node); } + void pushBack(Stack& other) { m_stack.pushBack(other); } + void pushBack(Stack&& other) { m_stack.pushBack(other); other.clear(); } + + void pushBack(UniqueNodeType&& node) + { + Node* pushing(node.release()); + m_stack.pushBack(pushing); + } + + void pushBack(UniqueStack&& other) + { + Stack pushing(other.release()); + m_stack.pushBack(pushing); + } + + // Push sorted. + template + void push(Node* node, Compare compare) + { + m_stack.push(node, compare); + } + + template + void push(Stack& other, Compare compare) + { + m_stack.push(other, compare); + } + + template + void push(Stack&& other, Compare compare) + { + m_stack.push(other, compare); + other.clear(); + } + + template + void push(UniqueNodeType&& node, Compare compare) + { + Node* pushing(node.release()); + m_stack.push(pushing, compare); + } + + template + void push(UniqueStack&& other, Compare compare) + { + Stack pushing(other.release()); + m_stack.push(pushing, compare); + } + + template + bool sortedBy(Compare compare) + { + return m_stack.sortedBy(compare); + } + + UniqueNodeType popOne() + { + return UniqueNodeType(m_splicePool, m_stack.pop()); + } + + template + UniqueNodeType popOne(Args&&... args) + { + UniqueNodeType node(m_splicePool, m_stack.pop()); + + if (!std::is_pointer::value) + { + node.get()->construct(std::forward(args)...); + } + + return node; + } + + UniqueStack pop(std::size_t count) + { + Stack stack(m_stack.popStack(count)); + return UniqueStack(m_splicePool, std::move(stack)); + } + + bool empty() const { return m_stack.empty(); } + std::size_t size() const { return m_stack.size(); } + void swap(UniqueStack&& other) { m_stack.swap(other.m_stack); } + + void print(std::size_t maxElements = 20) const + { + m_stack.print(maxElements); + } + + Node* head() { return m_stack.head(); } + const Node* head() const { return m_stack.head(); } + + Iterator begin() { return Iterator(head()); } + ConstIterator begin() const { return ConstIterator(head()); } + ConstIterator cbegin() const { return begin(); } + + Iterator end() { return Iterator(nullptr); } + ConstIterator end() const { return ConstIterator(nullptr); } + ConstIterator cend() const { return end(); } + + SplicePool& pool() { return m_splicePool; } + +private: + UniqueStack(const UniqueStack&) = delete; + UniqueStack& operator=(UniqueStack&) = delete; + + SplicePool& m_splicePool; + Stack m_stack; +}; + +template +class SplicePool +{ +public: + using NodeType = Node; + using UniqueNodeType = UniqueNode; + + using StackType = Stack; + using UniqueStackType = UniqueStack; + + SplicePool(std::size_t blockSize) + : m_blockSize(blockSize) + , m_stack() + , m_mutex() + , m_allocated(0) + { } + + virtual ~SplicePool() { } + + std::size_t allocated() const + { + std::lock_guard lock(m_mutex); + return m_allocated; + } + + std::size_t available() const + { + std::lock_guard lock(m_mutex); + return m_stack.size(); + } + + void release(UniqueNodeType&& node) { node.reset(); } + void release(UniqueStackType&& stack) { stack.reset(); } + + void release(Node* node) + { + if (node) + { + reset(&node->val()); + + // TODO - For these single node releases, we could put them into a + // separate Stack to avoid blocking the entire pool, and only reach + // into it when some threshold is reached or the main stack is + // empty. + std::lock_guard lock(m_mutex); + m_stack.push(node); + } + } + + void release(Stack&& other) + { + if (Node* node = other.head()) + { + while (node) + { + reset(&node->val()); + node = node->next(); + } + + std::lock_guard lock(m_mutex); + m_stack.push(other); + } + } + + template + UniqueNodeType acquireOne(Args&&... args) + { + UniqueNodeType node(*this); + + { + std::lock_guard lock(m_mutex); + node.reset(m_stack.pop()); + } + + if (!node) + { + Stack newStack(doAllocate(1)); + node.reset(newStack.pop()); + + std::lock_guard lock(m_mutex); + + m_allocated += m_blockSize; + m_stack.push(newStack); + } + + if (!std::is_pointer::value) + { + node.get()->construct(std::forward(args)...); + } + + return node; + } + + UniqueStackType acquire(const std::size_t count) + { + UniqueStackType other(*this); + + std::unique_lock lock(m_mutex); + if (count >= m_stack.size()) + { + other = UniqueStackType(*this, std::move(m_stack)); + + lock.unlock(); + + if (count > other.size()) + { + const std::size_t numNodes(count - other.size()); + const std::size_t numBlocks(numNodes / m_blockSize + 1); + + Stack alloc(doAllocate(numBlocks)); + + assert(alloc.size() == numBlocks * m_blockSize); + + Stack taken(alloc.popStack(numNodes)); + other.push(taken); + + lock.lock(); + m_stack.push(alloc); + m_allocated += numBlocks * m_blockSize; + } + } + else + { + other = UniqueStackType(*this, m_stack.popStack(count)); + } + + return other; + } + +protected: + void reset(T* val) + { + destruct(val); + construct(val); + } + + virtual Stack doAllocate(std::size_t blocks) = 0; + virtual void construct(T*) const { } + virtual void destruct(T*) const { } + + const std::size_t m_blockSize; + +private: + SplicePool(const SplicePool&) = delete; + SplicePool& operator=(const SplicePool&) = delete; + + Stack m_stack; + mutable std::mutex m_mutex; + + std::size_t m_allocated; +}; + +template +class ObjectPool : public SplicePool +{ +public: + ObjectPool(std::size_t blockSize = 4096) + : SplicePool(blockSize) + , m_blocks() + , m_mutex() + { } + +private: + virtual Stack doAllocate(std::size_t blocks) override + { + Stack stack; + std::deque>>> newBlocks; + + for (std::size_t i(0); i < blocks; ++i) + { + std::unique_ptr>> newBlock( + new std::vector>(this->m_blockSize)); + newBlocks.push_back(std::move(newBlock)); + } + + for (auto& block : newBlocks) + { + auto& vec(*block); + + for (std::size_t i(0); i < vec.size(); ++i) + { + stack.push(&vec[i]); + } + } + + std::lock_guard lock(m_mutex); + + m_blocks.insert( + m_blocks.end(), + std::make_move_iterator(newBlocks.begin()), + std::make_move_iterator(newBlocks.end())); + + return stack; + } + + virtual void construct(T* val) const override + { + new (val) T(); + } + + virtual void destruct(T* val) const override + { + val->~T(); + } + + std::deque>>> m_blocks; + mutable std::mutex m_mutex; +}; + +template +class BufferPool : public SplicePool +{ +public: + BufferPool(std::size_t bufferSize, std::size_t blockSize = 4096) + : SplicePool(blockSize) + , m_bufferSize(bufferSize) + , m_bytesPerBlock(m_bufferSize * this->m_blockSize) + , m_bytes() + , m_nodes() + , m_mutex() + { } + +private: + virtual Stack doAllocate(std::size_t blocks) override + { + Stack stack; + + std::deque>> newBytes; + std::deque>>> newNodes; + + for (std::size_t i(0); i < blocks; ++i) + { + std::unique_ptr> newByteBlock( + new std::vector(m_bytesPerBlock)); + + std::unique_ptr>> newNodeBlock( + new std::vector>(this->m_blockSize)); + + newBytes.push_back(std::move(newByteBlock)); + newNodes.push_back(std::move(newNodeBlock)); + } + + for (std::size_t i(0); i < blocks; ++i) + { + std::vector& bytes(*newBytes[i]); + std::vector>& nodes(*newNodes[i]); + + for (std::size_t i(0); i < this->m_blockSize; ++i) + { + Node& node(nodes[i]); + node.val() = &bytes[m_bufferSize * i]; + stack.push(&node); + } + } + + std::lock_guard lock(m_mutex); + + m_bytes.insert( + m_bytes.end(), + std::make_move_iterator(newBytes.begin()), + std::make_move_iterator(newBytes.end())); + + m_nodes.insert( + m_nodes.end(), + std::make_move_iterator(newNodes.begin()), + std::make_move_iterator(newNodes.end())); + + return stack; + } + + virtual void construct(T** val) const override + { + std::fill(*val, *val + m_bufferSize, 0); + } + + const std::size_t m_bufferSize; + const std::size_t m_bytesPerBlock; + + std::deque>> m_bytes; + std::deque>>> m_nodes; + mutable std::mutex m_mutex; +}; + +} // namespace splicer + diff --git a/src/Graphics/OpenGLContext/mupen64plus/mupen64plus_DisplayWindow.cpp b/src/Graphics/OpenGLContext/mupen64plus/mupen64plus_DisplayWindow.cpp index 02b77eaa9..a56d22673 100644 --- a/src/Graphics/OpenGLContext/mupen64plus/mupen64plus_DisplayWindow.cpp +++ b/src/Graphics/OpenGLContext/mupen64plus/mupen64plus_DisplayWindow.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,8 @@ #include #endif +using namespace opengl; + class DisplayWindowMupen64plus : public DisplayWindow { public: @@ -49,30 +52,32 @@ void DisplayWindowMupen64plus::_setAttributes() { LOG(LOG_VERBOSE, "[gles2GlideN64]: _setAttributes\n"); - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_PROFILE_MASK, M64P_GL_CONTEXT_PROFILE_CORE); - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MAJOR_VERSION, 3); - CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MINOR_VERSION, 3); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_PROFILE_MASK, M64P_GL_CONTEXT_PROFILE_CORE); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MAJOR_VERSION, 3); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_CONTEXT_MINOR_VERSION, 3); - CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1); - CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, config.video.verticalSync); - CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 32); - CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, config.video.verticalSync); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 32); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16); if (config.video.multisampling > 0 && config.frameBufferEmulation.enable == 0) { - CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLEBUFFERS, 1); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLEBUFFERS, 1); if (config.video.multisampling <= 2) - CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 2); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 2); else if (config.video.multisampling <= 4) - CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 4); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 4); else if (config.video.multisampling <= 8) - CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 8); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 8); else - CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 16); + FunctionWrapper::CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 16); } } bool DisplayWindowMupen64plus::_start() { - CoreVideo_Init(); + FunctionWrapper::setThreadedMode(config.video.threadedVideo); + + FunctionWrapper::CoreVideo_Init(); _setAttributes(); m_bFullscreen = config.video.fullscreen > 0; @@ -83,10 +88,10 @@ bool DisplayWindowMupen64plus::_start() printf("(II) Setting video mode %dx%d...\n", m_screenWidth, m_screenHeight); const m64p_video_flags flags = M64VIDEOFLAG_SUPPORT_RESIZING; - if (CoreVideo_SetVideoMode(m_screenWidth, m_screenHeight, 0, m_bFullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, flags) != M64ERR_SUCCESS) { + if (FunctionWrapper::CoreVideo_SetVideoMode(m_screenWidth, m_screenHeight, 0, m_bFullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, flags) != M64ERR_SUCCESS) { //printf("(EE) Error setting videomode %dx%d\n", m_screenWidth, m_screenHeight); LOG(LOG_ERROR, "[gles2GlideN64]: Error setting videomode %dx%d\n", m_screenWidth, m_screenHeight); - CoreVideo_Quit(); + FunctionWrapper::CoreVideo_Quit(); return false; } LOG(LOG_VERBOSE, "[gles2GlideN64]: Create setting videomode %dx%d\n", m_screenWidth, m_screenHeight); @@ -104,7 +109,7 @@ bool DisplayWindowMupen64plus::_start() void DisplayWindowMupen64plus::_stop() { - CoreVideo_Quit(); + FunctionWrapper::CoreVideo_Quit(); } void DisplayWindowMupen64plus::_swapBuffers() @@ -119,7 +124,11 @@ void DisplayWindowMupen64plus::_swapBuffers() gDP.changed |= CHANGED_COMBINE; (*renderCallback)((gDP.changed&CHANGED_CPU_FB_WRITE) == 0 ? 1 : 0); } - CoreVideo_GL_SwapBuffers(); + + //Don't let the command queue grow too big buy waiting on no more swap buffers being queued + FunctionWrapper::WaitForSwapBuffersQueued(); + + FunctionWrapper::CoreVideo_GL_SwapBuffers(); } void DisplayWindowMupen64plus::_saveScreenshot() @@ -150,7 +159,7 @@ bool DisplayWindowMupen64plus::_resizeWindow() printf("(EE) Error setting videomode %dx%d\n", m_screenWidth, m_screenHeight); m_width = m_screenWidth = config.video.windowedWidth; m_height = m_screenHeight = config.video.windowedHeight; - CoreVideo_Quit(); + FunctionWrapper::CoreVideo_Quit(); return false; } _setBufferSize(); diff --git a/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp b/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp index 945357760..9d158863e 100644 --- a/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp +++ b/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp @@ -23,12 +23,12 @@ void CachedEnable::enable(bool _enable) return; if (_enable) { - if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(glEnablei)) + if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(Enablei)) glEnablei(GLenum(m_parameter), 0); else glEnable(GLenum(m_parameter)); } else { - if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(glDisablei)) + if (m_parameter == enable::BLEND && IS_GL_FUNCTION_VALID(Disablei)) glDisablei(GLenum(m_parameter), 0); else glDisable(GLenum(m_parameter)); @@ -40,6 +40,27 @@ u32 CachedEnable::get() return u32(m_cached); } +/*---------------CachedBindFramebuffer-------------*/ + +void CachedBindFramebuffer::bind(graphics::Parameter _target, graphics::ObjectHandle _name) { + if (update(_target, _name)) + glBindFramebuffer(GLenum(_target), GLuint(_name)); +} + +/*---------------CachedBindRenderbuffer-------------*/ + +void CachedBindRenderbuffer::bind(graphics::Parameter _target, graphics::ObjectHandle _name) { + if (update(_target, _name)) + glBindRenderbuffer(GLenum(_target), GLuint(_name)); +} + +/*---------------CachedBindBuffer-------------*/ + +void CachedBindBuffer::bind(graphics::Parameter _target, graphics::ObjectHandle _name) { + if (update(_target, _name)) + glBindBuffer(GLenum(_target), GLuint(_name)); +} + /*---------------CachedBindTexture-------------*/ void CachedBindTexture::bind(Parameter _tmuIndex, Parameter _target, ObjectHandle _name) @@ -152,9 +173,7 @@ void CachedTextureUnpackAlignment::setTextureUnpackAlignment(s32 _param) /*---------------CachedFunctions-------------*/ CachedFunctions::CachedFunctions(const GLInfo & _glinfo) -: m_bindFramebuffer(GET_GL_FUNCTION(glBindFramebuffer)) -, m_bindRenderbuffer(GET_GL_FUNCTION(glBindRenderbuffer)) -, m_bindBuffer(GET_GL_FUNCTION(glBindBuffer)) { +{ if (_glinfo.isGLESX) { // Disable parameters, not avalible for GLESX m_enables.emplace(GL_DEPTH_CLAMP, Parameter()); diff --git a/src/Graphics/OpenGLContext/opengl_CachedFunctions.h b/src/Graphics/OpenGLContext/opengl_CachedFunctions.h index 884dbc259..95f6420be 100644 --- a/src/Graphics/OpenGLContext/opengl_CachedFunctions.h +++ b/src/Graphics/OpenGLContext/opengl_CachedFunctions.h @@ -110,26 +110,23 @@ namespace opengl { }; - template - class CachedBind : public Cached2 + class CachedBindFramebuffer : public Cached2 { public: - CachedBind(Bind _bind) : m_bind(_bind) {} - - void bind(graphics::Parameter _target, graphics::ObjectHandle _name) { - if (update(_target, _name)) - m_bind(GLenum(_target), GLuint(_name)); - } - - private: - Bind m_bind; + void bind(graphics::Parameter _target, graphics::ObjectHandle _name); }; - typedef CachedBind CachedBindFramebuffer; - - typedef CachedBind CachedBindRenderbuffer; + class CachedBindRenderbuffer : public Cached2 + { + public: + void bind(graphics::Parameter _target, graphics::ObjectHandle _name); + }; - typedef CachedBind CachedBindBuffer; + class CachedBindBuffer : public Cached2 + { + public: + void bind(graphics::Parameter _target, graphics::ObjectHandle _name); + }; class CachedBindTexture : public Cached2 { diff --git a/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.cpp b/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.cpp index 32a02f28b..d82d51351 100644 --- a/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.cpp +++ b/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.cpp @@ -30,7 +30,6 @@ void ColorBufferReaderWithBufferStorage::_initBuffers() // Initialize Pixel Buffer Objects for (u32 index = 0; index < m_numPBO; ++index) { m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[index])); - m_fence[index] = 0; glBufferStorage(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_CLIENT_STORAGE_BIT); m_PBOData[index] = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pTexture->textureBytes, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); } @@ -44,7 +43,6 @@ void ColorBufferReaderWithBufferStorage::_destroyBuffers() for (u32 index = 0; index < m_numPBO; ++index) { m_PBO[index] = 0; - glDeleteSync(m_fence[index]); } } @@ -55,18 +53,11 @@ const u8 * ColorBufferReaderWithBufferStorage::_readPixels(const ReadColorBuffer GLenum type = GLenum(_params.colorType); m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex])); - glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0); + + glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, nullptr); if (!_params.sync) { - //Setup a fence sync object so that we know when glReadPixels completes - m_fence[m_curIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); m_curIndex = (m_curIndex + 1) % m_numPBO; - //Wait for glReadPixels to complete for the currently selected PBO - if (m_fence[m_curIndex] != 0) { - glClientWaitSync(m_fence[m_curIndex], 0, 100000000); - glDeleteSync(m_fence[m_curIndex]); - m_fence[m_curIndex] = 0; - } } else { glFinish(); } diff --git a/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.h b/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.h index 499bd5815..e871fea62 100644 --- a/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.h +++ b/src/Graphics/OpenGLContext/opengl_ColorBufferReaderWithBufferStorage.h @@ -29,7 +29,6 @@ namespace opengl { GLuint m_PBO[_maxPBO]; void* m_PBOData[_maxPBO]; u32 m_curIndex; - GLsync m_fence[_maxPBO]; }; } diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp index f7e7a0453..32f59bb52 100644 --- a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp +++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp @@ -25,7 +25,7 @@ using namespace opengl; ContextImpl::ContextImpl() : m_clampMode(graphics::ClampMode::ClippingEnabled) { - initGLFunctions(); + } diff --git a/src/Graphics/OpenGLContext/opengl_GLInfo.cpp b/src/Graphics/OpenGLContext/opengl_GLInfo.cpp index 7e65c2f2d..8275e5e6c 100644 --- a/src/Graphics/OpenGLContext/opengl_GLInfo.cpp +++ b/src/Graphics/OpenGLContext/opengl_GLInfo.cpp @@ -108,20 +108,20 @@ void GLInfo::init() { bool ext_draw_buffers_indexed = isGLESX && (Utils::isExtensionSupported(*this, "GL_EXT_draw_buffers_indexed") || numericVersion >= 32); #ifdef EGL if (isGLESX && bufferStorage) - g_glBufferStorage = (PFNGLBUFFERSTORAGEPROC) eglGetProcAddress("glBufferStorageEXT"); + ptrBufferStorage = (PFNGLBUFFERSTORAGEPROC) eglGetProcAddress("glBufferStorageEXT"); if (isGLESX && numericVersion < 32) { if (ext_draw_buffers_indexed) { - g_glEnablei = (PFNGLENABLEIPROC) eglGetProcAddress("glEnableiEXT"); - g_glDisablei = (PFNGLDISABLEIPROC) eglGetProcAddress("glDisableiEXT"); + ptrEnablei = (PFNGLENABLEIPROC) eglGetProcAddress("glEnableiEXT"); + ptrDisablei = (PFNGLDISABLEIPROC) eglGetProcAddress("glDisableiEXT"); } else { - g_glEnablei = nullptr; - g_glDisablei = nullptr; + ptrEnablei = nullptr; + ptrDisablei = nullptr; } } if (isGLES2 && shaderStorage) { - g_glProgramBinary = (PFNGLPROGRAMBINARYPROC) eglGetProcAddress("glProgramBinaryOES"); - g_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) eglGetProcAddress("glGetProgramBinaryOES"); - g_glProgramParameteri = nullptr; + ptrProgramBinary = (PFNGLPROGRAMBINARYPROC) eglGetProcAddress("glProgramBinaryOES"); + ptrGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) eglGetProcAddress("glGetProgramBinaryOES"); + ptrProgramParameteri = nullptr; } #endif #ifndef OS_ANDROID diff --git a/src/Graphics/OpenGLContext/windows/WindowsWGL.cpp b/src/Graphics/OpenGLContext/windows/WindowsWGL.cpp new file mode 100644 index 000000000..0814ffb92 --- /dev/null +++ b/src/Graphics/OpenGLContext/windows/WindowsWGL.cpp @@ -0,0 +1,152 @@ +#include "WindowsWGL.h" +#include +#include +#include + +HGLRC WindowsWGL::hRC = NULL; +HDC WindowsWGL::hDC = NULL; + +bool WindowsWGL::start() +{ + int pixelFormat; + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST1\n"); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 32, // color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + LOG(LOG_APIFUNC, "WindowsWGL::start TEST2\n"); + + if (hWnd == NULL) + hWnd = GetActiveWindow(); + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST3\n"); + if ((hDC = GetDC(hWnd)) == NULL) { + MessageBox(hWnd, L"Error while getting a device context!", pluginNameW, MB_ICONERROR | MB_OK); + return false; + } + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST4\n"); + if ((pixelFormat = ChoosePixelFormat(hDC, &pfd)) == 0) { + MessageBox(hWnd, L"Unable to find a suitable pixel format!", pluginNameW, MB_ICONERROR | MB_OK); + stop(); + return false; + } + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST5\n"); + if ((SetPixelFormat(hDC, pixelFormat, &pfd)) == FALSE) { + MessageBox(hWnd, L"Error while setting pixel format!", pluginNameW, MB_ICONERROR | MB_OK); + stop(); + return false; + } + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST6\n"); + if ((hRC = wglCreateContext(hDC)) == NULL) { + MessageBox(hWnd, L"Error while creating OpenGL context!", pluginNameW, MB_ICONERROR | MB_OK); + stop(); + return false; + } + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST7\n"); + if ((wglMakeCurrent(hDC, hRC)) == FALSE) { + MessageBox(hWnd, L"Error while making OpenGL context current!", pluginNameW, MB_ICONERROR | MB_OK); + stop(); + return false; + } + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST7.1\n"); + initGLFunctions(); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST7.2\n"); + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST8\n"); + PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = + (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9\n"); + if (wglGetExtensionsStringARB != NULL) { + const char * wglextensions = wglGetExtensionsStringARB(hDC); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.1\n"); + + if (strstr(wglextensions, "WGL_ARB_create_context_profile") != nullptr) { + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.1.1\n"); + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = + (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.2\n"); + + GLint majorVersion = 0; + ptrGetIntegerv(GL_MAJOR_VERSION, &majorVersion); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.3\n"); + GLint minorVersion = 0; + ptrGetIntegerv(GL_MINOR_VERSION, &minorVersion); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.4\n"); + + const int attribList[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, majorVersion, + WGL_CONTEXT_MINOR_VERSION_ARB, minorVersion, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 //End + }; + + HGLRC coreHrc = wglCreateContextAttribsARB(hDC, 0, attribList); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.5\n"); + if (coreHrc != NULL) { + wglDeleteContext(hRC); + wglMakeCurrent(hDC, coreHrc); + hRC = coreHrc; + } + } + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.1.1\n"); + + if (strstr(wglextensions, "WGL_EXT_swap_control") != nullptr) { + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.6\n"); + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.7\n"); + wglSwapIntervalEXT(config.video.verticalSync); + LOG(LOG_APIFUNC, "WindowsWGL::start TEST9.8\n"); + } + } + + return true; +} + +void WindowsWGL::stop() +{ + wglMakeCurrent(NULL, NULL); + + if (hRC != NULL) { + wglDeleteContext(hRC); + hRC = NULL; + } + + if (hDC != NULL) { + ReleaseDC(hWnd, hDC); + hDC = NULL; + } +} + +void WindowsWGL::swapBuffers() +{ + if (hDC == NULL) + SwapBuffers(wglGetCurrentDC()); + else + SwapBuffers(hDC); +} + diff --git a/src/Graphics/OpenGLContext/windows/WindowsWGL.h b/src/Graphics/OpenGLContext/windows/WindowsWGL.h new file mode 100644 index 000000000..4fc2a1af8 --- /dev/null +++ b/src/Graphics/OpenGLContext/windows/WindowsWGL.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include +#include +#include + +class WindowsWGL +{ +public: + static bool start(); + static void stop(); + static void swapBuffers(); + +private: + + static HGLRC hRC; + static HDC hDC; +}; + diff --git a/src/Graphics/OpenGLContext/windows/windows_DisplayWindow.cpp b/src/Graphics/OpenGLContext/windows/windows_DisplayWindow.cpp index 92ca18633..767d7c834 100644 --- a/src/Graphics/OpenGLContext/windows/windows_DisplayWindow.cpp +++ b/src/Graphics/OpenGLContext/windows/windows_DisplayWindow.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include @@ -11,11 +8,14 @@ #include #include #include +#include + +using namespace opengl; class DisplayWindowWindows : public DisplayWindow { public: - DisplayWindowWindows() : hRC(NULL), hDC(NULL) {} + DisplayWindowWindows() = default; private: bool _start() override; @@ -28,9 +28,6 @@ class DisplayWindowWindows : public DisplayWindow void _readScreen(void **_pDest, long *_pWidth, long *_pHeight) override; void _readScreen2(void * _dest, int * _width, int * _height, int _front) override {} graphics::ObjectHandle _getDefaultFramebuffer() override; - - HGLRC hRC; - HDC hDC; }; DisplayWindow & DisplayWindow::get() @@ -41,122 +38,23 @@ DisplayWindow & DisplayWindow::get() bool DisplayWindowWindows::_start() { - int pixelFormat; - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - PFD_DRAW_TO_WINDOW | // support window - PFD_SUPPORT_OPENGL | // support OpenGL - PFD_DOUBLEBUFFER, // double buffered - PFD_TYPE_RGBA, // RGBA type - 32, // color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // z-buffer - 0, // no stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - - if (hWnd == NULL) - hWnd = GetActiveWindow(); - - if ((hDC = GetDC( hWnd )) == NULL) { - MessageBox( hWnd, L"Error while getting a device context!", pluginNameW, MB_ICONERROR | MB_OK ); - return false; - } - - if ((pixelFormat = ChoosePixelFormat(hDC, &pfd )) == 0) { - MessageBox( hWnd, L"Unable to find a suitable pixel format!", pluginNameW, MB_ICONERROR | MB_OK ); - _stop(); - return false; - } - - if ((SetPixelFormat(hDC, pixelFormat, &pfd )) == FALSE) { - MessageBox( hWnd, L"Error while setting pixel format!", pluginNameW, MB_ICONERROR | MB_OK ); - _stop(); - return false; - } - - if ((hRC = wglCreateContext(hDC)) == NULL) { - MessageBox( hWnd, L"Error while creating OpenGL context!", pluginNameW, MB_ICONERROR | MB_OK ); - _stop(); - return false; - } - - if ((wglMakeCurrent(hDC, hRC)) == FALSE) { - MessageBox( hWnd, L"Error while making OpenGL context current!", pluginNameW, MB_ICONERROR | MB_OK ); - _stop(); - return false; - } - - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = - (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); - - if (wglGetExtensionsStringARB != NULL) { - const char * wglextensions = wglGetExtensionsStringARB(hDC); - - if (strstr(wglextensions, "WGL_ARB_create_context_profile") != nullptr) { - PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = - (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); - - GLint majorVersion = 0; - glGetIntegerv(GL_MAJOR_VERSION, &majorVersion); - GLint minorVersion = 0; - glGetIntegerv(GL_MINOR_VERSION, &minorVersion); - - const int attribList[] = - { - WGL_CONTEXT_MAJOR_VERSION_ARB, majorVersion, - WGL_CONTEXT_MINOR_VERSION_ARB, minorVersion, - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 //End - }; - - HGLRC coreHrc = wglCreateContextAttribsARB(hDC, 0, attribList); - if (coreHrc != NULL) { - wglDeleteContext(hRC); - wglMakeCurrent(hDC, coreHrc); - hRC = coreHrc; - } - } - - if (strstr(wglextensions, "WGL_EXT_swap_control") != nullptr) { - PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); - wglSwapIntervalEXT(config.video.verticalSync); - } - } + FunctionWrapper::setThreadedMode(config.video.threadedVideo); + FunctionWrapper::windowsStart(); return _resizeWindow(); } void DisplayWindowWindows::_stop() { - wglMakeCurrent( NULL, NULL ); - - if (hRC != NULL) { - wglDeleteContext(hRC); - hRC = NULL; - } - - if (hDC != NULL) { - ReleaseDC(hWnd, hDC); - hDC = NULL; - } + FunctionWrapper::windowsStop(); } void DisplayWindowWindows::_swapBuffers() { - if (hDC == NULL) - SwapBuffers( wglGetCurrentDC() ); - else - SwapBuffers( hDC ); + //Don't let the command queue grow too big buy waiting on no more swap buffers being queued + FunctionWrapper::WaitForSwapBuffersQueued(); + + FunctionWrapper::windowsSwapBuffers(); } void DisplayWindowWindows::_saveScreenshot() diff --git a/src/mupen64plus-video-gliden64.mk b/src/mupen64plus-video-gliden64.mk index 03fffc785..746f484eb 100644 --- a/src/mupen64plus-video-gliden64.mk +++ b/src/mupen64plus-video-gliden64.mk @@ -67,6 +67,10 @@ MY_LOCAL_SRC_FILES := $(SRCDIR)/Graphics/CombinerProgram.cpp \ $(SRCDIR)/Graphics/ObjectHandle.cpp \ $(SRCDIR)/Graphics/OpenGLContext/GLFunctions.cpp \ + $(SRCDIR)/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp \ + $(SRCDIR)/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.cpp \ + $(SRCDIR)/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Command.cpp \ + $(SRCDIR)/Graphics/OpenGLContext/ThreadedOpenGl/opengl_ObjectPool.cpp \ $(SRCDIR)/Graphics/OpenGLContext/opengl_Attributes.cpp \ $(SRCDIR)/Graphics/OpenGLContext/opengl_BufferedDrawer.cpp \ $(SRCDIR)/Graphics/OpenGLContext/opengl_BufferManipulationObjectFactory.cpp \ diff --git a/src/mupenplus/Config_mupenplus.cpp b/src/mupenplus/Config_mupenplus.cpp index 12d1d594b..cee53be05 100644 --- a/src/mupenplus/Config_mupenplus.cpp +++ b/src/mupenplus/Config_mupenplus.cpp @@ -45,6 +45,9 @@ bool Config_SetDefault() res = ConfigSetDefaultInt(g_configVideoGliden64, "configVersion", CONFIG_VERSION_CURRENT, "Settings version. Don't touch it."); assert(res == M64ERR_SUCCESS); + res = ConfigSetDefaultBool(g_configVideoGliden64, "ThreadedVideo", config.video.threadedVideo, "Enable threaded video backend"); + assert(res == M64ERR_SUCCESS); + res = ConfigSetDefaultInt(g_configVideoGliden64, "MultiSampling", config.video.multisampling, "Enable/Disable MultiSampling (0=off, 2,4,8,16=quality)"); assert(res == M64ERR_SUCCESS); res = ConfigSetDefaultBool(g_configVideoGliden64, "FXAA", config.video.fxaa, "Enable/Disable Fast Approximate Anti-Aliasing FXAA"); @@ -358,7 +361,7 @@ void Config_LoadConfig() config.video.windowedWidth = ConfigGetParamInt(g_configVideoGeneral, "ScreenWidth"); config.video.windowedHeight = ConfigGetParamInt(g_configVideoGeneral, "ScreenHeight"); config.video.verticalSync = ConfigGetParamBool(g_configVideoGeneral, "VerticalSync"); - + config.video.threadedVideo = ConfigGetParamBool(g_configVideoGliden64, "ThreadedVideo"); const u32 multisampling = ConfigGetParamInt(g_configVideoGliden64, "MultiSampling"); config.video.multisampling = multisampling == 0 ? 0 : pow2(multisampling); config.video.fxaa = ConfigGetParamBool(g_configVideoGliden64, "FXAA"); @@ -389,7 +392,7 @@ void Config_LoadConfig() //#2D graphics Settings config.graphics2D.correctTexrectCoords = ConfigGetParamInt(g_configVideoGliden64, "CorrectTexrectCoords"); config.graphics2D.enableNativeResTexrects = ConfigGetParamBool(g_configVideoGliden64, "EnableNativeResTexrects"); - config.graphics2D.bgMode = ConfigGetParamInt(g_configVideoGliden64, "BackgroundsMode"); + config.graphics2D.bgMode = ConfigGetParamBool(g_configVideoGliden64, "BackgroundsMode"); //#Frame Buffer Settings:" config.frameBufferEmulation.enable = ConfigGetParamBool(g_configVideoGliden64, "EnableFBEmulation"); config.frameBufferEmulation.copyAuxToRDRAM = ConfigGetParamBool(g_configVideoGliden64, "EnableCopyAuxiliaryToRDRAM");