/* * Copyright (C) 2011-2014 Gregory hainaut * Copyright (C) 2007-2009 Gabest * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "GLLoader.h" #include "GSdx.h" PFNGLACTIVETEXTUREPROC gl_ActiveTexture = NULL; PFNGLBLENDCOLORPROC gl_BlendColor = NULL; PFNGLATTACHSHADERPROC gl_AttachShader = NULL; PFNGLBINDBUFFERPROC gl_BindBuffer = NULL; PFNGLBINDBUFFERBASEPROC gl_BindBufferBase = NULL; PFNGLBINDBUFFERRANGEPROC gl_BindBufferRange = NULL; PFNGLBINDFRAMEBUFFERPROC gl_BindFramebuffer = NULL; PFNGLBINDSAMPLERPROC gl_BindSampler = NULL; PFNGLBINDVERTEXARRAYPROC gl_BindVertexArray = NULL; PFNGLBLENDEQUATIONSEPARATEIARBPROC gl_BlendEquationSeparateiARB = NULL; PFNGLBLENDFUNCSEPARATEIARBPROC gl_BlendFuncSeparateiARB = NULL; PFNGLBLITFRAMEBUFFERPROC gl_BlitFramebuffer = NULL; PFNGLBUFFERDATAPROC gl_BufferData = NULL; PFNGLCHECKFRAMEBUFFERSTATUSPROC gl_CheckFramebufferStatus = NULL; PFNGLCLEARBUFFERFVPROC gl_ClearBufferfv = NULL; PFNGLCLEARBUFFERIVPROC gl_ClearBufferiv = NULL; PFNGLCLEARBUFFERUIVPROC gl_ClearBufferuiv = NULL; PFNGLCOLORMASKIPROC gl_ColorMaski = NULL; PFNGLCOMPILESHADERPROC gl_CompileShader = NULL; PFNGLCREATEPROGRAMPROC gl_CreateProgram = NULL; PFNGLCREATESHADERPROC gl_CreateShader = NULL; PFNGLCREATESHADERPROGRAMVPROC gl_CreateShaderProgramv = NULL; PFNGLDELETEBUFFERSPROC gl_DeleteBuffers = NULL; PFNGLDELETEFRAMEBUFFERSPROC gl_DeleteFramebuffers = NULL; PFNGLDELETEPROGRAMPROC gl_DeleteProgram = NULL; PFNGLDELETESAMPLERSPROC gl_DeleteSamplers = NULL; PFNGLDELETESHADERPROC gl_DeleteShader = NULL; PFNGLDELETEVERTEXARRAYSPROC gl_DeleteVertexArrays = NULL; PFNGLDETACHSHADERPROC gl_DetachShader = NULL; PFNGLDRAWBUFFERSPROC gl_DrawBuffers = NULL; PFNGLDRAWELEMENTSBASEVERTEXPROC gl_DrawElementsBaseVertex = NULL; PFNGLENABLEVERTEXATTRIBARRAYPROC gl_EnableVertexAttribArray = NULL; PFNGLFRAMEBUFFERRENDERBUFFERPROC gl_FramebufferRenderbuffer = NULL; PFNGLFRAMEBUFFERTEXTURE2DPROC gl_FramebufferTexture2D = NULL; PFNGLGENBUFFERSPROC gl_GenBuffers = NULL; PFNGLGENFRAMEBUFFERSPROC gl_GenFramebuffers = NULL; PFNGLGENSAMPLERSPROC gl_GenSamplers = NULL; PFNGLGENVERTEXARRAYSPROC gl_GenVertexArrays = NULL; PFNGLGETBUFFERPARAMETERIVPROC gl_GetBufferParameteriv = NULL; PFNGLGETDEBUGMESSAGELOGARBPROC gl_GetDebugMessageLogARB = NULL; PFNGLDEBUGMESSAGECALLBACKPROC gl_DebugMessageCallback = NULL; PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog = NULL; PFNGLGETPROGRAMIVPROC gl_GetProgramiv = NULL; PFNGLGETSHADERIVPROC gl_GetShaderiv = NULL; PFNGLGETSTRINGIPROC gl_GetStringi = NULL; PFNGLISFRAMEBUFFERPROC gl_IsFramebuffer = NULL; PFNGLLINKPROGRAMPROC gl_LinkProgram = NULL; PFNGLMAPBUFFERPROC gl_MapBuffer = NULL; PFNGLMAPBUFFERRANGEPROC gl_MapBufferRange = NULL; PFNGLPROGRAMPARAMETERIPROC gl_ProgramParameteri = NULL; PFNGLSAMPLERPARAMETERFPROC gl_SamplerParameterf = NULL; PFNGLSAMPLERPARAMETERIPROC gl_SamplerParameteri = NULL; PFNGLSHADERSOURCEPROC gl_ShaderSource = NULL; PFNGLUNIFORM1IPROC gl_Uniform1i = NULL; PFNGLUNMAPBUFFERPROC gl_UnmapBuffer = NULL; PFNGLUSEPROGRAMSTAGESPROC gl_UseProgramStages = NULL; PFNGLVERTEXATTRIBIPOINTERPROC gl_VertexAttribIPointer = NULL; PFNGLVERTEXATTRIBPOINTERPROC gl_VertexAttribPointer = NULL; PFNGLBUFFERSUBDATAPROC gl_BufferSubData = NULL; PFNGLFENCESYNCPROC gl_FenceSync = NULL; PFNGLDELETESYNCPROC gl_DeleteSync = NULL; PFNGLCLIENTWAITSYNCPROC gl_ClientWaitSync = NULL; PFNGLFLUSHMAPPEDBUFFERRANGEPROC gl_FlushMappedBufferRange = NULL; PFNGLBLENDEQUATIONSEPARATEPROC gl_BlendEquationSeparate = NULL; PFNGLBLENDFUNCSEPARATEPROC gl_BlendFuncSeparate = NULL; // GL4.0 // GL4.1 PFNGLBINDPROGRAMPIPELINEPROC gl_BindProgramPipeline = NULL; PFNGLGENPROGRAMPIPELINESPROC gl_GenProgramPipelines = NULL; PFNGLDELETEPROGRAMPIPELINESPROC gl_DeleteProgramPipelines = NULL; PFNGLGETPROGRAMPIPELINEIVPROC gl_GetProgramPipelineiv = NULL; PFNGLVALIDATEPROGRAMPIPELINEPROC gl_ValidateProgramPipeline = NULL; PFNGLGETPROGRAMPIPELINEINFOLOGPROC gl_GetProgramPipelineInfoLog = NULL; PFNGLGETPROGRAMBINARYPROC gl_GetProgramBinary = NULL; // NO GL4.1 PFNGLUSEPROGRAMPROC gl_UseProgram = NULL; PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog = NULL; PFNGLPROGRAMUNIFORM1IPROC gl_ProgramUniform1i = NULL; // GL4.3 PFNGLCOPYIMAGESUBDATAPROC gl_CopyImageSubData = NULL; PFNGLINVALIDATETEXIMAGEPROC gl_InvalidateTexImage = NULL; PFNGLPUSHDEBUGGROUPPROC gl_PushDebugGroup = NULL; PFNGLPOPDEBUGGROUPPROC gl_PopDebugGroup = NULL; PFNGLDEBUGMESSAGEINSERTPROC gl_DebugMessageInsert = NULL; // GL4.2 PFNGLBINDIMAGETEXTUREPROC gl_BindImageTexture = NULL; PFNGLMEMORYBARRIERPROC gl_MemoryBarrier = NULL; PFNGLTEXSTORAGE2DPROC gl_TexStorage2D = NULL; // GL4.4 PFNGLCLEARTEXIMAGEPROC gl_ClearTexImage = NULL; PFNGLBUFFERSTORAGEPROC gl_BufferStorage = NULL; // GL4.5 PFNGLCREATETEXTURESPROC gl_CreateTextures = NULL; PFNGLTEXTURESTORAGE2DPROC gl_TextureStorage2D = NULL; PFNGLTEXTURESUBIMAGE2DPROC gl_TextureSubImage2D = NULL; PFNGLCOPYTEXTURESUBIMAGE2DPROC gl_CopyTextureSubImage2D = NULL; PFNGLBINDTEXTUREUNITPROC gl_BindTextureUnit = NULL; PFNGLGETTEXTUREIMAGEPROC gl_GetTextureImage = NULL; PFNGLTEXTUREPARAMETERIPROC gl_TextureParameteri = NULL; PFNGLCREATEFRAMEBUFFERSPROC gl_CreateFramebuffers = NULL; PFNGLCLEARNAMEDFRAMEBUFFERFVPROC gl_ClearNamedFramebufferfv = NULL; PFNGLCLEARNAMEDFRAMEBUFFERIVPROC gl_ClearNamedFramebufferiv = NULL; PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC gl_ClearNamedFramebufferuiv = NULL; PFNGLNAMEDFRAMEBUFFERTEXTUREPROC gl_NamedFramebufferTexture = NULL; PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC gl_NamedFramebufferDrawBuffers = NULL; PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC gl_NamedFramebufferReadBuffer = NULL; PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC gl_CheckNamedFramebufferStatus = NULL; PFNGLCREATEBUFFERSPROC gl_CreateBuffers = NULL; PFNGLNAMEDBUFFERSTORAGEPROC gl_NamedBufferStorage = NULL; PFNGLNAMEDBUFFERDATAPROC gl_NamedBufferData = NULL; PFNGLNAMEDBUFFERSUBDATAPROC gl_NamedBufferSubData = NULL; PFNGLMAPNAMEDBUFFERPROC gl_MapNamedBuffer = NULL; PFNGLMAPNAMEDBUFFERRANGEPROC gl_MapNamedBufferRange = NULL; PFNGLUNMAPNAMEDBUFFERPROC gl_UnmapNamedBuffer = NULL; PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC gl_FlushMappedNamedBufferRange = NULL; PFNGLCREATESAMPLERSPROC gl_CreateSamplers = NULL; PFNGLCREATEPROGRAMPIPELINESPROC gl_CreateProgramPipelines = NULL; PFNGLCLIPCONTROLPROC gl_ClipControl = NULL; PFNGLTEXTUREBARRIERPROC gl_TextureBarrier = NULL; namespace Emulate_DSA { // Texture entry point void APIENTRY BindTextureUnit(GLuint unit, GLuint texture) { gl_ActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, texture); } void APIENTRY CreateTexture(GLenum target, GLsizei n, GLuint *textures) { glGenTextures(1, textures); } void APIENTRY TextureStorage(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { BindTextureUnit(7, texture); gl_TexStorage2D(GL_TEXTURE_2D, levels, internalformat, width, height); } void APIENTRY TextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) { BindTextureUnit(7, texture); glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height, format, type, pixels); } void APIENTRY CopyTextureSubImage(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { BindTextureUnit(7, texture); glCopyTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, x, y, width, height); } void APIENTRY GetTexureImage(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels) { BindTextureUnit(7, texture); glGetTexImage(GL_TEXTURE_2D, level, format, type, pixels); } void APIENTRY TextureParameteri (GLuint texture, GLenum pname, GLint param) { BindTextureUnit(7, texture); glTexParameteri(GL_TEXTURE_2D, pname, param); } // Framebuffer entry point GLenum fb_target = 0; void SetFramebufferTarget(GLenum target) { fb_target = target; } void APIENTRY CreateFramebuffers(GLsizei n, GLuint *framebuffers) { gl_GenFramebuffers(n, framebuffers); } void APIENTRY ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value) { gl_BindFramebuffer(fb_target, framebuffer); gl_ClearBufferfv(buffer, drawbuffer, value); } void APIENTRY ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value) { gl_BindFramebuffer(fb_target, framebuffer); gl_ClearBufferiv(buffer, drawbuffer, value); } void APIENTRY ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value) { gl_BindFramebuffer(fb_target, framebuffer); gl_ClearBufferuiv(buffer, drawbuffer, value); } void APIENTRY NamedFramebufferTexture(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) { gl_BindFramebuffer(fb_target, framebuffer); gl_FramebufferTexture2D(fb_target, attachment, GL_TEXTURE_2D, texture, level); } void APIENTRY NamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, const GLenum *bufs) { gl_BindFramebuffer(fb_target, framebuffer); gl_DrawBuffers(n, bufs); } void APIENTRY NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src) { gl_BindFramebuffer(fb_target, framebuffer); glReadBuffer(src); gl_BindFramebuffer(fb_target, 0); } GLenum APIENTRY CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target) { gl_BindFramebuffer(fb_target, framebuffer); return gl_CheckFramebufferStatus(fb_target); } // Buffer entry point GLenum buffer_target = 0; void SetBufferTarget(GLenum target) { buffer_target = target; } void APIENTRY CreateBuffers(GLsizei n, GLuint *buffers) { gl_GenBuffers(1, buffers); } void APIENTRY NamedBufferStorage(GLuint buffer, GLsizei size, const void *data, GLbitfield flags) { gl_BindBuffer(buffer_target, buffer); gl_BufferStorage(buffer_target, size, data, flags); } void APIENTRY NamedBufferData(GLuint buffer, GLsizei size, const void *data, GLenum usage) { gl_BindBuffer(buffer_target, buffer); gl_BufferData(buffer_target, size, data, usage); } void APIENTRY NamedBufferSubData(GLuint buffer, GLintptr offset, GLsizei size, const void *data) { gl_BindBuffer(buffer_target, buffer); gl_BufferSubData(buffer_target, offset, size, data); } void *APIENTRY MapNamedBuffer(GLuint buffer, GLenum access) { gl_BindBuffer(buffer_target, buffer); return gl_MapBuffer(buffer_target, access); } void *APIENTRY MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizei length, GLbitfield access) { gl_BindBuffer(buffer_target, buffer); return gl_MapBufferRange(buffer_target, offset, length, access); } GLboolean APIENTRY UnmapNamedBuffer(GLuint buffer) { gl_BindBuffer(buffer_target, buffer); return gl_UnmapBuffer(buffer_target); } void APIENTRY FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, GLsizei length) { gl_BindBuffer(buffer_target, buffer); gl_FlushMappedBufferRange(buffer_target, offset, length); } // Misc entry point // (only purpose is to have a consistent API otherwise it is useless) void APIENTRY CreateProgramPipelines(GLsizei n, GLuint *pipelines) { gl_GenProgramPipelines(n, pipelines); } void APIENTRY CreateSamplers(GLsizei n, GLuint *samplers) { gl_GenSamplers(n, samplers); } // Replace function pointer to emulate DSA behavior void Init() { fprintf(stderr, "DSA is not supported. Replacing the GL function pointer to emulate it\n"); gl_BindTextureUnit = BindTextureUnit; gl_CreateTextures = CreateTexture; gl_TextureStorage2D = TextureStorage; gl_TextureSubImage2D = TextureSubImage; gl_CopyTextureSubImage2D = CopyTextureSubImage; gl_GetTextureImage = GetTexureImage; gl_TextureParameteri = TextureParameteri; gl_CreateFramebuffers = CreateFramebuffers; gl_ClearNamedFramebufferfv = ClearNamedFramebufferfv; gl_ClearNamedFramebufferiv = ClearNamedFramebufferiv; gl_ClearNamedFramebufferuiv = ClearNamedFramebufferuiv; gl_NamedFramebufferDrawBuffers = NamedFramebufferDrawBuffers; gl_NamedFramebufferReadBuffer = NamedFramebufferReadBuffer; gl_CheckNamedFramebufferStatus = CheckNamedFramebufferStatus; gl_CreateBuffers = CreateBuffers; gl_NamedBufferStorage = NamedBufferStorage; gl_NamedBufferData = NamedBufferData; gl_NamedBufferSubData = NamedBufferSubData; gl_MapNamedBuffer = MapNamedBuffer; gl_MapNamedBufferRange = MapNamedBufferRange; gl_UnmapNamedBuffer = UnmapNamedBuffer; gl_FlushMappedNamedBufferRange = FlushMappedNamedBufferRange; gl_CreateProgramPipelines = CreateProgramPipelines; gl_CreateSamplers = CreateSamplers; } } namespace GLLoader { bool fglrx_buggy_driver = false; bool mesa_amd_buggy_driver = false; bool nvidia_buggy_driver = false; bool intel_buggy_driver = false; bool in_replayer = false; // GL4 hardware (due to proprietary driver limitation) bool found_GL_ARB_separate_shader_objects = false; // Issue with Mesa and Catalyst... bool found_geometry_shader = true; // we require GL3.3 so geometry must be supported by default bool found_GL_EXT_texture_filter_anisotropic = false; bool found_GL_ARB_clear_texture = false; // Don't know if GL3 GPU can support it bool found_GL_ARB_buffer_storage = false; bool found_GL_ARB_copy_image = false; // Not sure actually maybe GL3 GPU can do it bool found_GL_ARB_gpu_shader5 = false; bool found_GL_ARB_shader_image_load_store = false; // GLES3.1 bool found_GL_ARB_texture_barrier = false; // Well maybe supported by older hardware I don't know // DX10 GPU limited driver bool found_GL_ARB_draw_buffers_blend = false; bool found_GL_ARB_clip_control = false; bool found_GL_ARB_direct_state_access = false; // Mandatory bool found_GL_ARB_texture_storage = false; bool found_GL_ARB_shading_language_420pack = false; static bool status_and_override(bool& found, const std::string& name, bool mandatory = false) { if (mandatory) { if (!found) { fprintf(stderr, "ERROR: %s is NOT SUPPORTED\n", name.c_str()); } return found; } if (!found) { fprintf(stderr, "INFO: %s is NOT SUPPORTED\n", name.c_str()); } else { fprintf(stderr, "INFO: %s is available\n", name.c_str()); } std::string opt("override_"); opt += name; if (theApp.GetConfig(opt.c_str(), -1) != -1) { found = !!theApp.GetConfig(opt.c_str(), -1); fprintf(stderr, "Override %s detection (%s)\n", name.c_str(), found ? "Enabled" : "Disabled"); } return true; } bool check_gl_version(int major, int minor) { const GLubyte* s = glGetString(GL_VERSION); if (s == NULL) { fprintf(stderr, "Error: GLLoader failed to get GL version\n"); return false; } GLuint v = 1; while (s[v] != '\0' && s[v-1] != ' ') v++; const char* vendor = (const char*)glGetString(GL_VENDOR); fprintf(stderr, "OpenGL information. GPU: %s. Vendor: %s. Driver: %s\n", glGetString(GL_RENDERER), vendor, &s[v]); // Name changed but driver is still bad! if (strstr(vendor, "ATI") || strstr(vendor, "Advanced Micro Devices")) fglrx_buggy_driver = true; if (strstr(vendor, "NVIDIA Corporation")) nvidia_buggy_driver = true; if (strstr(vendor, "Intel")) intel_buggy_driver = true; if (strstr(vendor, "X.Org") || strstr(vendor, "nouveau")) // Note: it might actually catch nouveau too, but bugs are likely to be the same anyway mesa_amd_buggy_driver = true; if (strstr(vendor, "VMware")) // Assume worst case because I don't know the real status mesa_amd_buggy_driver = intel_buggy_driver = true; if (mesa_amd_buggy_driver) { fprintf(stderr, "Buggy driver detected. Geometry shaders will be disabled\n"); found_geometry_shader = false; } if (theApp.GetConfig("override_geometry_shader", -1) != -1) { found_geometry_shader = !!theApp.GetConfig("override_geometry_shader", -1); fprintf(stderr, "Overriding geometry shaders detection\n"); } GLint major_gl = 0; GLint minor_gl = 0; glGetIntegerv(GL_MAJOR_VERSION, &major_gl); glGetIntegerv(GL_MINOR_VERSION, &minor_gl); if ( (major_gl < major) || ( major_gl == major && minor_gl < minor ) ) { fprintf(stderr, "OpenGL %d.%d is not supported. Only OpenGL %d.%d\n was found", major, minor, major_gl, minor_gl); return false; } return true; } bool check_gl_supported_extension() { int max_ext = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &max_ext); if (gl_GetStringi && max_ext) { for (GLint i = 0; i < max_ext; i++) { string ext((const char*)gl_GetStringi(GL_EXTENSIONS, i)); // Bonus if (ext.compare("GL_EXT_texture_filter_anisotropic") == 0) found_GL_EXT_texture_filter_anisotropic = true; // GL4.0 if (ext.compare("GL_ARB_gpu_shader5") == 0) found_GL_ARB_gpu_shader5 = true; if (ext.compare("GL_ARB_draw_buffers_blend") == 0) found_GL_ARB_draw_buffers_blend = true; // GL4.1 if (ext.compare("GL_ARB_separate_shader_objects") == 0) { if (!fglrx_buggy_driver && !mesa_amd_buggy_driver && !intel_buggy_driver) found_GL_ARB_separate_shader_objects = true; else fprintf(stderr, "Buggy driver detected, GL_ARB_separate_shader_objects will be disabled\n"); } // GL4.2 if (ext.compare("GL_ARB_shading_language_420pack") == 0) found_GL_ARB_shading_language_420pack = true; if (ext.compare("GL_ARB_texture_storage") == 0) found_GL_ARB_texture_storage = true; if (ext.compare("GL_ARB_shader_image_load_store") == 0) found_GL_ARB_shader_image_load_store = true; // GL4.3 if (ext.compare("GL_ARB_copy_image") == 0) found_GL_ARB_copy_image = true; // GL4.4 if (ext.compare("GL_ARB_buffer_storage") == 0) found_GL_ARB_buffer_storage = true; if (ext.compare("GL_ARB_clear_texture") == 0) found_GL_ARB_clear_texture = true; // GL4.5 if (ext.compare("GL_ARB_direct_state_access") == 0) found_GL_ARB_direct_state_access = true; if (ext.compare("GL_ARB_clip_control") == 0) found_GL_ARB_clip_control = true; if (ext.compare("GL_ARB_texture_barrier") == 0) found_GL_ARB_texture_barrier = true; //fprintf(stderr, "DEBUG ext: %s\n", ext.c_str()); } } bool status = true; fprintf(stderr, "\n"); // Bonus status &= status_and_override(found_GL_EXT_texture_filter_anisotropic, "GL_EXT_texture_filter_anisotropic"); // GL4.0 status &= status_and_override(found_GL_ARB_gpu_shader5, "GL_ARB_gpu_shader5"); status &= status_and_override(found_GL_ARB_draw_buffers_blend, "GL_ARB_draw_buffers_blend"); // GL4.1 status &= status_and_override(found_GL_ARB_separate_shader_objects, "GL_ARB_separate_shader_objects"); // GL4.2 status &= status_and_override(found_GL_ARB_shader_image_load_store, "GL_ARB_shader_image_load_store"); status &= status_and_override(found_GL_ARB_shading_language_420pack, "GL_ARB_shading_language_420pack", true); status &= status_and_override(found_GL_ARB_texture_storage, "GL_ARB_texture_storage", true); // GL4.3 status &= status_and_override(found_GL_ARB_copy_image, "GL_ARB_copy_image"); // GL4.4 status &= status_and_override(found_GL_ARB_buffer_storage,"GL_ARB_buffer_storage"); status &= status_and_override(found_GL_ARB_clear_texture,"GL_ARB_clear_texture"); // GL4.5 status &= status_and_override(found_GL_ARB_clip_control, "GL_ARB_clip_control"); status &= status_and_override(found_GL_ARB_direct_state_access, "GL_ARB_direct_state_access"); status &= status_and_override(found_GL_ARB_texture_barrier, "GL_ARB_texture_barrier"); if (!found_GL_ARB_direct_state_access) { Emulate_DSA::Init(); } if (gl_BindTextureUnit == NULL) { fprintf(stderr, "FATAL ERROR !!!! Failed to setup DSA function pointer!!!\n"); status = false; } if (!found_GL_ARB_texture_barrier) { fprintf(stderr, "Error GL_ARB_texture_barrier is not supported by your driver. You can't emulate correctly the GS blending unit! Sorry!\n"); theApp.SetConfig("accurate_blending_unit", 0); theApp.SetConfig("accurate_date", 0); } fprintf(stderr, "\n"); return status; } }