2022-01-13 14:05:24 +08:00
|
|
|
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
2021-10-21 19:04:49 +08:00
|
|
|
*
|
|
|
|
* 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 <GLES3/gl31.h>
|
|
|
|
//#include <GLES3/gl3ext.h> // not (yet) needed
|
|
|
|
#include <EGL/egl.h>
|
|
|
|
#include <EGL/eglext.h>
|
|
|
|
|
|
|
|
#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);
|
|
|
|
}
|