cuda-samples/Samples/5_Domain_Specific/simpleGLES_screen/graphics_interface.c
2022-01-13 11:35:24 +05:30

380 lines
11 KiB
C

/* 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.
*/
#include <GLES3/gl31.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <sys/keycodes.h>
screen_window_t screen_window;
screen_context_t screen_context;
screen_event_t screen_ev;
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSurface eglSurface = EGL_NO_SURFACE;
EGLContext eglContext = EGL_NO_CONTEXT;
void error_exit(const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(1);
}
enum { NvGlDemoKeyCode_Escape = 27 };
typedef void (*GlCloseCB)(void);
typedef void (*GlKeyCB)(char key, int state);
GlCloseCB closeCB = NULL;
GlKeyCB keyCB = NULL;
void CHECK_GLERROR() {
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
fprintf(stderr, "[%s line %d] OpenGL Error: 0x%x ", __FILE__, __LINE__,
err);
switch (err) {
case GL_INVALID_ENUM:
fprintf(stderr, "(GL_INVALID_ENUM)\n");
break;
case GL_INVALID_VALUE:
fprintf(stderr, "(GL_INVALID_VALUE)\n");
break;
case GL_INVALID_OPERATION:
fprintf(stderr, "(GL_INVALID_OPERATION)\n");
break;
case GL_OUT_OF_MEMORY:
fprintf(stderr, "(GL_OUT_OF_MEMORY)\n");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
fprintf(stderr, "(GL_INVALID_FRAMEBUFFER_OPERATION)\n");
break;
default:
break;
}
fflush(stderr);
}
}
static void UpdateEventMask(void) {
static int rc = 1;
if (rc) {
rc = screen_create_event(&screen_ev);
}
}
void SetCloseCB(GlCloseCB cb) {
// Call the eglQnxScreenConsumer module if option is enabled
closeCB = cb;
UpdateEventMask();
}
void SetKeyCB(GlKeyCB cb) {
keyCB = cb;
UpdateEventMask();
}
// Add keys here, that are used in demo apps.
static unsigned char GetKeyPress(int *screenKey) {
unsigned char key = '\0';
switch (*screenKey) {
case KEYCODE_ESCAPE:
key = NvGlDemoKeyCode_Escape;
break;
default:
/* For "normal" keys, Screen KEYCODE is just ASCII. */
if (*screenKey <= 127) {
key = *screenKey;
}
break;
}
return key;
}
void CheckEvents(void) {
static int vis = 1, val = 1;
int rc;
/**
** We start the loop by processing any events that might be in our
** queue. The only event that is of interest to us are the resize
** and close events. The timeout variable is set to 0 (no wait) or
** forever depending if the window is visible or invisible.
**/
while (!screen_get_event(screen_context, screen_ev, vis ? 0ull : ~0ull)) {
// Get QNX CAR 2.1 event property
rc = screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &val);
if (rc || val == SCREEN_EVENT_NONE) {
break;
}
switch (val) {
case SCREEN_EVENT_CLOSE:
/**
** All we have to do when we receive the close event is
** exit the application loop.
**/
if (closeCB) {
closeCB();
}
break;
case SCREEN_EVENT_KEYBOARD:
rc = screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_FLAGS,
&val);
if (rc || val == SCREEN_EVENT_NONE) {
break;
}
if (val & KEY_DOWN) {
rc = screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SYM,
&val);
if (rc || val == SCREEN_EVENT_NONE) {
break;
}
unsigned char key;
key = GetKeyPress(&val);
if (key != '\0') {
keyCB(key, 1);
}
}
break;
default:
break;
}
}
}
int graphics_setup_window(int xpos, int ypos, int width, int height,
const char *windowname, int reqdispno) {
EGLint configAttrs[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE};
EGLint contextAttrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLint windowAttrs[] = {EGL_NONE};
EGLConfig *configList = NULL;
EGLint configCount;
int displayCount = 0;
int dispno;
screen_context = 0;
screen_display_t *screenDisplayHandle = NULL;
if (screen_create_context(&screen_context, 0)) {
error_exit("Error creating screen context.\n");
}
eglDisplay = eglGetDisplay(0);
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");
}
screen_window = 0;
if (screen_create_window(&screen_window, screen_context)) {
error_exit("Error creating screen window.\n");
}
// query the total no of display avaibale from QNX CAR2 screen
if (screen_get_context_property_iv(
screen_context, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount)) {
error_exit("Error getting context property\n");
}
screenDisplayHandle =
(screen_display_t *)malloc(displayCount * sizeof(screen_display_t));
if (!screenDisplayHandle) {
error_exit("Error allocating screen memory handle is getting failed\n");
}
// query the display handle from QNX CAR2 screen
if (screen_get_context_property_pv(screen_context, SCREEN_PROPERTY_DISPLAYS,
(void **)screenDisplayHandle)) {
error_exit("Error getting display handle\n");
}
for (dispno = 0; dispno < displayCount; dispno++) {
int active = 0;
// Query the connected status from QNX CAR2 screen
screen_get_display_property_iv(screenDisplayHandle[dispno],
SCREEN_PROPERTY_ATTACHED, &active);
if (active) {
if (reqdispno == dispno) {
// Map the window buffer to user requested display port
screen_set_window_property_pv(screen_window, SCREEN_PROPERTY_DISPLAY,
(void **)&screenDisplayHandle[reqdispno]);
break;
}
}
}
if (dispno == displayCount) {
error_exit("Failed to set the requested display\n");
}
free(screenDisplayHandle);
int format = SCREEN_FORMAT_RGBA8888;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_FORMAT,
&format)) {
error_exit("Error setting SCREEN_PROPERTY_FORMAT\n");
}
int usage = SCREEN_USAGE_OPENGL_ES2;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_USAGE,
&usage)) {
error_exit("Error setting SCREEN_PROPERTY_USAGE\n");
}
EGLint interval = 1;
if (screen_set_window_property_iv(screen_window,
SCREEN_PROPERTY_SWAP_INTERVAL, &interval)) {
error_exit("Error setting SCREEN_PROPERTY_SWAP_INTERVAL\n");
}
int windowSize[2];
windowSize[0] = width;
windowSize[1] = height;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_SIZE,
windowSize)) {
error_exit("Error setting SCREEN_PROPERTY_SIZE\n");
}
int windowOffset[2];
windowOffset[0] = xpos;
windowOffset[1] = ypos;
if (screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_POSITION,
windowOffset)) {
error_exit("Error setting SCREEN_PROPERTY_POSITION\n");
}
if (screen_create_window_buffers(screen_window, 2)) {
error_exit("Error creating two window buffers.\n");
}
eglSurface =
eglCreateWindowSurface(eglDisplay, configList[0],
(EGLNativeWindowType)screen_window, windowAttrs);
if (!eglSurface) {
error_exit("EGL couldn't create window\n");
}
eglBindAPI(EGL_OPENGL_ES_API);
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\n");
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);
}
return 1;
}
void graphics_set_windowtitle(const char *windowname) {
// Do nothing on screen
}
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 (screen_window) {
screen_destroy_window(screen_window);
screen_window = NULL;
}
if (screen_context) {
screen_destroy_context(screen_context);
}
if (screen_ev) {
screen_destroy_event(screen_ev);
}
}