/* Copyright (c) 2022, 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. */ Display *display; int screen; Window win = 0; #include //#include // not (yet) needed #include #include #define GET_GLERROR(ret) \ { \ GLenum err = glGetError(); \ if (err != GL_NO_ERROR) \ { \ fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x\n", __FILE__, __LINE__, \ err); \ fflush(stderr); \ \ switch (err) \ { \ case GL_INVALID_ENUM: \ printf("GL_INVALID_ENUM\n"); \ break; \ case GL_INVALID_VALUE: \ printf("GL_INVALID_VALUE\n"); \ break; \ case GL_INVALID_OPERATION: \ printf("GL_INVALID_OPERATION\n"); \ break; \ case GL_OUT_OF_MEMORY: \ printf("GL_OUT_OF_MEMORY\n"); \ break; \ case GL_INVALID_FRAMEBUFFER_OPERATION: \ printf("GL_INVALID_FRAMEBUFFER_OPERATION\n"); \ break; \ default: \ printf("UKNOWN OPENGL ERROR CODE 0x%x\n", err); \ }; \ } \ } EGLDisplay eglDisplay = EGL_NO_DISPLAY; EGLSurface eglSurface = EGL_NO_SURFACE; EGLContext eglContext = EGL_NO_CONTEXT; #if 0 // needed for optional API call retrieval (= if libGLESv2.so wouldn't be \ // linked explicitly) - tedious! consider GLEW. typedef GLenum (* glGetErrorTYPE) (void); glGetErrorTYPE my_glGetError; typedef GL_APICALL const GLubyte (*GL_APIENTRY glGetStringTYPE) (GLenum name); glGetStringTYPE my_glGetString; typedef GL_APICALL void (*GL_APIENTRY glClearTYPE) (GLbitfield mask); glClearTYPE my_glClear; typedef GL_APICALL void (*GL_APIENTRY glGetProgramivTYPE) (GLuint program, GLenum pname, GLint *params); glGetProgramivTYPE my_glGetProgramiv; #endif int graphics_setup_window(int xpos, int ypos, int width, int height, const char *windowname) { #ifdef USE_GL // OpenGL 4.3 Core Profile creation through EGL - would be even available on // desktop, but CUDA interop doesn't yet work for OpenGL context established // through EGL EGLint configAttrs[] = {EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, // EGL_DEPTH_SIZE, 16, EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, EGL_CONFORMANT, EGL_OPENGL_BIT, // EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, // EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, 1, EGL_NONE}; EGLint contextAttrs[] = {// EGL_CONTEXT_MAJOR_VERSION_KHR, 4, // EGL_CONTEXT_MINOR_VERSION_KHR, 3, EGL_NONE}; #else // OpenGL ES 3.1 EGLint configAttrs[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 16, EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, // EGL_CONFORMANT, EGL_OPENGL_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // 3_BIT_KHR, EGL_NONE}; EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; #endif EGLint windowAttrs[] = {EGL_NONE}; EGLConfig *configList = NULL; EGLint configCount; display = XOpenDisplay(NULL); if (!display) error_exit("Error opening X display.\n"); screen = DefaultScreen(display); eglDisplay = eglGetDisplay(display); if (eglDisplay == EGL_NO_DISPLAY) error_exit("EGL failed to obtain display\n"); if (!eglInitialize(eglDisplay, 0, 0)) error_exit("EGL failed to initialize\n"); if (!eglChooseConfig(eglDisplay, configAttrs, NULL, 0, &configCount) || !configCount) error_exit("EGL failed to return any matching configurations\n"); configList = (EGLConfig *)malloc(configCount * sizeof(EGLConfig)); if (!eglChooseConfig(eglDisplay, configAttrs, configList, configCount, &configCount) || !configCount) error_exit("EGL failed to populate configuration list\n"); win = XCreateSimpleWindow(display, RootWindow(display, screen), xpos, ypos, width, height, 0, BlackPixel(display, screen), WhitePixel(display, screen)); XStoreName(display, win, windowname); XSelectInput(display, win, ExposureMask | ButtonPressMask | KeyPressMask | StructureNotifyMask | ButtonReleaseMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | VisibilityChangeMask | ColormapChangeMask); XMapWindow(display, win); eglSurface = eglCreateWindowSurface(eglDisplay, configList[0], (EGLNativeWindowType)win, windowAttrs); if (!eglSurface) error_exit("EGL couldn't create window\n"); #ifdef USE_GL eglBindAPI(EGL_OPENGL_API); #else eglBindAPI(EGL_OPENGL_ES_API); #endif eglContext = eglCreateContext(eglDisplay, configList[0], NULL, contextAttrs); if (!eglContext) error_exit("EGL couldn't create context\n"); if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) error_exit("EGL couldn't make context/surface current\n"); EGLint Context_RendererType; eglQueryContext(eglDisplay, eglContext, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType); switch (Context_RendererType) { case EGL_OPENGL_API: printf("Using OpenGL API\n"); break; case EGL_OPENGL_ES_API: printf("Using OpenGL ES API"); break; case EGL_OPENVG_API: error_exit("Context Query Returned OpenVG. This is Unsupported\n"); default: error_exit("Unknown Context Type. %04X\n", Context_RendererType); } #if 0 // obtain API function pointers _manually_ (see function pointer \ // declarations above) my_glGetError = (glGetErrorTYPE) eglGetProcAddress("glGetError"); my_glGetString = (glGetStringTYPE) eglGetProcAddress("glGetString"); my_glGetProgramiv = (glGetProgramivTYPE) eglGetProcAddress("glGetProgramiv"); GL_APICALL void (* my_glGenBuffers) (GLsizei n, GLuint *buffers); my_glGenBuffers = ((*) (GLsizei n, GLuint *buffers)) eglGetProcAddress("glGenBuffers"); GL_APICALL void (* my_glGetShaderInfoLog) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); my_glGetShaderInfoLog = ((*) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)) eglGetProcAddress("glGetShaderInfoLog"); GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); #endif return 1; } void graphics_set_windowtitle(const char *windowname) { XStoreName(display, win, windowname); } void graphics_swap_buffers() { eglSwapBuffers(eglDisplay, eglSurface); } void graphics_close_window() { if (eglDisplay != EGL_NO_DISPLAY) { eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (eglContext != EGL_NO_CONTEXT) eglDestroyContext(eglDisplay, eglContext); if (eglSurface != EGL_NO_SURFACE) eglDestroySurface(eglDisplay, eglSurface); eglTerminate(eglDisplay); } if (win) XDestroyWindow(display, win); XCloseDisplay(display); }