/* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of NVIDIA CORPORATION nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // These are helper functions for the SDK samples (OpenGL) #ifndef HELPER_GL_H #define HELPER_GL_H #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) #include #endif #if defined(__APPLE__) || defined(MACOSX) #include #else #include #ifdef __linux__ #include #endif /* __linux__ */ #endif #include #include #include #include #include #include #include #include /* Prototypes */ namespace __HelperGL { static int isGLVersionSupported(unsigned reqMajor, unsigned reqMinor); static int areGLExtensionsSupported(const std::string &); #ifdef __linux__ #ifndef HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION #define USE_GL_FUNC(name, proto) proto name = (proto) glXGetProcAddress ((const GLubyte *)#name) #else #define USE_GL_FUNC(name, proto) extern proto name #endif USE_GL_FUNC(glBindBuffer, PFNGLBINDBUFFERPROC); USE_GL_FUNC(glDeleteBuffers, PFNGLDELETEBUFFERSPROC); USE_GL_FUNC(glBufferData, PFNGLBUFFERDATAPROC); USE_GL_FUNC(glBufferSubData, PFNGLBUFFERSUBDATAPROC); USE_GL_FUNC(glGenBuffers, PFNGLGENBUFFERSPROC); USE_GL_FUNC(glCreateProgram, PFNGLCREATEPROGRAMPROC); USE_GL_FUNC(glBindProgramARB, PFNGLBINDPROGRAMARBPROC); USE_GL_FUNC(glGenProgramsARB, PFNGLGENPROGRAMSARBPROC); USE_GL_FUNC(glDeleteProgramsARB, PFNGLDELETEPROGRAMSARBPROC); USE_GL_FUNC(glDeleteProgram, PFNGLDELETEPROGRAMPROC); USE_GL_FUNC(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC); USE_GL_FUNC(glGetProgramiv, PFNGLGETPROGRAMIVPROC); USE_GL_FUNC(glProgramParameteriEXT, PFNGLPROGRAMPARAMETERIEXTPROC); USE_GL_FUNC(glProgramStringARB, PFNGLPROGRAMSTRINGARBPROC); USE_GL_FUNC(glUnmapBuffer, PFNGLUNMAPBUFFERPROC); USE_GL_FUNC(glMapBuffer, PFNGLMAPBUFFERPROC); USE_GL_FUNC(glGetBufferParameteriv, PFNGLGETBUFFERPARAMETERIVPROC); USE_GL_FUNC(glLinkProgram, PFNGLLINKPROGRAMPROC); USE_GL_FUNC(glUseProgram, PFNGLUSEPROGRAMPROC); USE_GL_FUNC(glAttachShader, PFNGLATTACHSHADERPROC); USE_GL_FUNC(glCreateShader, PFNGLCREATESHADERPROC); USE_GL_FUNC(glShaderSource, PFNGLSHADERSOURCEPROC); USE_GL_FUNC(glCompileShader, PFNGLCOMPILESHADERPROC); USE_GL_FUNC(glDeleteShader, PFNGLDELETESHADERPROC); USE_GL_FUNC(glGetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC); USE_GL_FUNC(glGetShaderiv, PFNGLGETSHADERIVPROC); USE_GL_FUNC(glUniform1i, PFNGLUNIFORM1IPROC); USE_GL_FUNC(glUniform1f, PFNGLUNIFORM1FPROC); USE_GL_FUNC(glUniform2f, PFNGLUNIFORM2FPROC); USE_GL_FUNC(glUniform3f, PFNGLUNIFORM3FPROC); USE_GL_FUNC(glUniform4f, PFNGLUNIFORM4FPROC); USE_GL_FUNC(glUniform1fv, PFNGLUNIFORM1FVPROC); USE_GL_FUNC(glUniform2fv, PFNGLUNIFORM2FVPROC); USE_GL_FUNC(glUniform3fv, PFNGLUNIFORM3FVPROC); USE_GL_FUNC(glUniform4fv, PFNGLUNIFORM4FVPROC); USE_GL_FUNC(glUniformMatrix4fv, PFNGLUNIFORMMATRIX4FVPROC); USE_GL_FUNC(glSecondaryColor3fv, PFNGLSECONDARYCOLOR3FVPROC); USE_GL_FUNC(glGetUniformLocation, PFNGLGETUNIFORMLOCATIONPROC); USE_GL_FUNC(glGenFramebuffersEXT, PFNGLGENFRAMEBUFFERSEXTPROC); USE_GL_FUNC(glBindFramebufferEXT, PFNGLBINDFRAMEBUFFEREXTPROC); USE_GL_FUNC(glDeleteFramebuffersEXT, PFNGLDELETEFRAMEBUFFERSEXTPROC); USE_GL_FUNC(glCheckFramebufferStatusEXT, PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC); USE_GL_FUNC(glGetFramebufferAttachmentParameterivEXT, PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC); USE_GL_FUNC(glFramebufferTexture1DEXT, PFNGLFRAMEBUFFERTEXTURE1DEXTPROC); USE_GL_FUNC(glFramebufferTexture2DEXT, PFNGLFRAMEBUFFERTEXTURE2DEXTPROC); USE_GL_FUNC(glFramebufferTexture3DEXT, PFNGLFRAMEBUFFERTEXTURE3DEXTPROC); USE_GL_FUNC(glGenerateMipmapEXT, PFNGLGENERATEMIPMAPEXTPROC); USE_GL_FUNC(glGenRenderbuffersEXT, PFNGLGENRENDERBUFFERSEXTPROC); USE_GL_FUNC(glDeleteRenderbuffersEXT, PFNGLDELETERENDERBUFFERSEXTPROC); USE_GL_FUNC(glBindRenderbufferEXT, PFNGLBINDRENDERBUFFEREXTPROC); USE_GL_FUNC(glRenderbufferStorageEXT, PFNGLRENDERBUFFERSTORAGEEXTPROC); USE_GL_FUNC(glFramebufferRenderbufferEXT, PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC); USE_GL_FUNC(glClampColorARB, PFNGLCLAMPCOLORARBPROC); USE_GL_FUNC(glBindFragDataLocationEXT, PFNGLBINDFRAGDATALOCATIONEXTPROC); #if !defined(GLX_EXTENSION_NAME) || !defined(GL_VERSION_1_3) USE_GL_FUNC(glActiveTexture, PFNGLACTIVETEXTUREPROC); USE_GL_FUNC(glClientActiveTexture, PFNGLACTIVETEXTUREPROC); #endif #undef USE_GL_FUNC #endif /*__linux__ */ } namespace __HelperGL { namespace __Int { static std::vector split(const std::string &str) { std::istringstream ss(str); std::istream_iterator it(ss); return std::vector (it, std::istream_iterator()); } /* Sort the vector passed by reference */ template static inline void sort(std::vector &a) { std::sort(a.begin(), a.end()); } /* Compare two vectors */ template static int equals(std::vector a, std::vector b) { if (a.size() != b.size()) return 0; sort(a); sort(b); return std::equal(a.begin(), a.end(), b.begin()); } template static std::vector getIntersection(std::vector a, std::vector b) { sort(a); sort(b); std::vector rc; std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter >(rc)); return rc; } static std::vector getGLExtensions() { std::string extensionsStr( (const char *)glGetString(GL_EXTENSIONS)); return split (extensionsStr); } } static int areGLExtensionsSupported(const std::string &extensions) { std::vector all = __Int::getGLExtensions(); std::vector requested = __Int::split(extensions); std::vector matched = __Int::getIntersection(all, requested); return __Int::equals(matched, requested); } static int isGLVersionSupported(unsigned reqMajor, unsigned reqMinor) { #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) if (glewInit() != GLEW_OK) { std::cerr << "glewInit() failed!" << std::endl; return 0; } #endif std::string version ((const char *) glGetString (GL_VERSION)); std::stringstream stream (version); unsigned major, minor; char dot; stream >> major >> dot >> minor; assert (dot == '.'); return major > reqMajor || (major == reqMajor && minor >= reqMinor); } static inline const char* glErrorToString(GLenum err) { #define CASE_RETURN_MACRO(arg) case arg: return #arg switch(err) { CASE_RETURN_MACRO(GL_NO_ERROR); CASE_RETURN_MACRO(GL_INVALID_ENUM); CASE_RETURN_MACRO(GL_INVALID_VALUE); CASE_RETURN_MACRO(GL_INVALID_OPERATION); CASE_RETURN_MACRO(GL_OUT_OF_MEMORY); CASE_RETURN_MACRO(GL_STACK_UNDERFLOW); CASE_RETURN_MACRO(GL_STACK_OVERFLOW); #ifdef GL_INVALID_FRAMEBUFFER_OPERATION CASE_RETURN_MACRO(GL_INVALID_FRAMEBUFFER_OPERATION); #endif default: break; } #undef CASE_RETURN_MACRO return "*UNKNOWN*"; } //////////////////////////////////////////////////////////////////////////// //! Check for OpenGL error //! @return bool if no GL error has been encountered, otherwise 0 //! @param file __FILE__ macro //! @param line __LINE__ macro //! @note The GL error is listed on stderr //! @note This function should be used via the CHECK_ERROR_GL() macro //////////////////////////////////////////////////////////////////////////// inline bool sdkCheckErrorGL(const char *file, const int line) { bool ret_val = true; // check for error GLenum gl_error = glGetError(); if (gl_error != GL_NO_ERROR) { #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) char tmpStr[512]; // NOTE: "%s(%i) : " allows Visual Studio to directly jump to the file at the right line // when the user double clicks on the error line in the Output pane. Like any compile error. sprintf_s(tmpStr, 255, "\n%s(%i) : GL Error : %s\n\n", file, line, glErrorToString(gl_error)); fprintf(stderr, "%s", tmpStr); #endif fprintf(stderr, "GL Error in file '%s' in line %d :\n", file, line); fprintf(stderr, "%s\n", glErrorToString(gl_error)); ret_val = false; } return ret_val; } #define SDK_CHECK_ERROR_GL() \ if( false == sdkCheckErrorGL( __FILE__, __LINE__)) { \ exit(EXIT_FAILURE); \ } } /* of namespace __HelperGL*/ using namespace __HelperGL; #endif /*HELPER_GL_H*/