godot/platform/bb10/bbutil.c

514 lines
13 KiB
C

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/keycodes.h>
#include <time.h>
#include "bbutil.h"
EGLDisplay egl_disp;
EGLSurface egl_surf;
static EGLConfig egl_conf;
static EGLContext egl_ctx;
static screen_context_t screen_ctx;
static screen_window_t screen_win;
static screen_display_t screen_disp;
static void
bbutil_egl_perror(const char *msg) {
static const char *errmsg[] = {
"function succeeded",
"EGL is not initialized, or could not be initialized, for the specified display",
"cannot access a requested resource",
"failed to allocate resources for the requested operation",
"an unrecognized attribute or attribute value was passed in an attribute list",
"an EGLConfig argument does not name a valid EGLConfig",
"an EGLContext argument does not name a valid EGLContext",
"the current surface of the calling thread is no longer valid",
"an EGLDisplay argument does not name a valid EGLDisplay",
"arguments are inconsistent",
"an EGLNativePixmapType argument does not refer to a valid native pixmap",
"an EGLNativeWindowType argument does not refer to a valid native window",
"one or more argument values are invalid",
"an EGLSurface argument does not name a valid surface configured for rendering",
"a power management event has occurred",
};
fprintf(stderr, "%s: %s\n", msg, errmsg[eglGetError() - EGL_SUCCESS]);
}
EGLConfig bbutil_choose_config(EGLDisplay egl_disp, enum RENDERING_API api) {
EGLConfig egl_conf = (EGLConfig)0;
EGLConfig *egl_configs;
EGLint egl_num_configs;
EGLint val;
EGLBoolean rc;
EGLint i;
rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglGetConfigs");
return egl_conf;
}
if (egl_num_configs == 0) {
fprintf(stderr, "eglGetConfigs: could not find a configuration\n");
return egl_conf;
}
egl_configs = malloc(egl_num_configs * sizeof(*egl_configs));
if (egl_configs == NULL) {
fprintf(stderr, "could not allocate memory for %d EGL configs\n", egl_num_configs);
return egl_conf;
}
rc = eglGetConfigs(egl_disp, egl_configs,
egl_num_configs, &egl_num_configs);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglGetConfigs");
free(egl_configs);
return egl_conf;
}
for (i = 0; i < egl_num_configs; i++) {
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
if (!(val & EGL_WINDOW_BIT)) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
if (!(val & api)) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
if ((api & (GL_ES_1|GL_ES_2)) && (val == 0)) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RED_SIZE, &val);
if (val != 8) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_GREEN_SIZE, &val);
if (val != 8) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_BLUE_SIZE, &val);
if (val != 8) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_BUFFER_SIZE, &val);
if (val != 32) {
continue;
}
egl_conf = egl_configs[i];
break;
}
free(egl_configs);
if (egl_conf == (EGLConfig)0) {
fprintf(stderr, "bbutil_choose_config: could not find a matching configuration\n");
}
return egl_conf;
}
int
bbutil_init_egl(screen_context_t ctx, enum RENDERING_API api) {
int usage;
int format = SCREEN_FORMAT_RGBX8888;
int nbuffers = 2;
EGLint interval = 1;
int rc;
EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
if (api == GL_ES_1) {
usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION;
} else if (api == GL_ES_2) {
usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION;
} else if (api == VG) {
usage = SCREEN_USAGE_OPENVG | SCREEN_USAGE_ROTATION;
} else {
fprintf(stderr, "invalid api setting\n");
return EXIT_FAILURE;
}
//Simple egl initialization
screen_ctx = ctx;
egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (egl_disp == EGL_NO_DISPLAY) {
bbutil_egl_perror("eglGetDisplay");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = eglInitialize(egl_disp, NULL, NULL);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglInitialize");
bbutil_terminate();
return EXIT_FAILURE;
}
if ((api == GL_ES_1) || (api == GL_ES_2)) {
rc = eglBindAPI(EGL_OPENGL_ES_API);
} else if (api == VG) {
rc = eglBindAPI(EGL_OPENVG_API);
}
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglBindApi");
bbutil_terminate();
return EXIT_FAILURE;
}
egl_conf = bbutil_choose_config(egl_disp, api);
if (egl_conf == (EGLConfig)0) {
bbutil_terminate();
return EXIT_FAILURE;
}
if (api == GL_ES_2) {
egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes);
} else {
egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, NULL);
}
if (egl_ctx == EGL_NO_CONTEXT) {
bbutil_egl_perror("eglCreateContext");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_create_window(&screen_win, screen_ctx);
if (rc) {
perror("screen_create_window");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format);
if (rc) {
perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
if (rc) {
perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp);
if (rc) {
perror("screen_get_window_property_pv");
bbutil_terminate();
return EXIT_FAILURE;
}
int screen_resolution[2];
rc = screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution);
if (rc) {
perror("screen_get_display_property_iv");
bbutil_terminate();
return EXIT_FAILURE;
}
int angle = atoi(getenv("ORIENTATION"));
screen_display_mode_t screen_mode;
rc = screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode);
if (rc) {
perror("screen_get_display_property_pv");
bbutil_terminate();
return EXIT_FAILURE;
}
int size[2];
rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
if (rc) {
perror("screen_get_window_property_iv");
bbutil_terminate();
return EXIT_FAILURE;
}
int buffer_size[2] = {size[0], size[1]};
if ((angle == 0) || (angle == 180)) {
if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) ||
((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) {
buffer_size[1] = size[0];
buffer_size[0] = size[1];
}
} else if ((angle == 90) || (angle == 270)){
if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) ||
((screen_mode.width < screen_mode.height && size[0] < size[1]))) {
buffer_size[1] = size[0];
buffer_size[0] = size[1];
}
} else {
fprintf(stderr, "Navigator returned an unexpected orientation angle.\n");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size);
if (rc) {
perror("screen_set_window_property_iv");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle);
if (rc) {
perror("screen_set_window_property_iv");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_create_window_buffers(screen_win, nbuffers);
if (rc) {
perror("screen_create_window_buffers");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = screen_create_window_group(screen_win, get_window_group_id());
if (rc) {
perror("screen_create_window_group");
bbutil_terminate();
return EXIT_FAILURE;
}
/* if (screen_create_window_group(screen_win, get_window_group_id()) != 0) goto fail; */
int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode);
egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
if (egl_surf == EGL_NO_SURFACE) {
bbutil_egl_perror("eglCreateWindowSurface");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglMakeCurrent");
bbutil_terminate();
return EXIT_FAILURE;
}
rc = eglSwapInterval(egl_disp, interval);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglSwapInterval");
bbutil_terminate();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int
bbutil_init_gl2d() {
#if 0
EGLint surface_width, surface_height;
if ((egl_disp == EGL_NO_DISPLAY) || (egl_surf == EGL_NO_SURFACE) ){
return EXIT_FAILURE;
}
eglQuerySurface(egl_disp, egl_surf, EGL_WIDTH, &surface_width);
eglQuerySurface(egl_disp, egl_surf, EGL_HEIGHT, &surface_height);
glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glViewport(0, 0, surface_width, surface_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, (float)(surface_width) / (float)(surface_height), 0.0f, 1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif
return EXIT_SUCCESS;
}
int
bbutil_init(screen_context_t ctx, enum RENDERING_API api) {
if (EXIT_SUCCESS != bbutil_init_egl(ctx, api)) {
return EXIT_FAILURE;
}
if ((GL_ES_1 == api) && (EXIT_SUCCESS != bbutil_init_gl2d())) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int bbutil_is_flipped() {
int ret;
screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_FLIP, &ret);
return ret;
};
int bbutil_get_rotation() {
int ret;
screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &ret);
return ret;
};
void
bbutil_terminate() {
//Typical EGL cleanup
if (egl_disp != EGL_NO_DISPLAY) {
eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (egl_surf != EGL_NO_SURFACE) {
eglDestroySurface(egl_disp, egl_surf);
egl_surf = EGL_NO_SURFACE;
}
if (egl_ctx != EGL_NO_CONTEXT) {
eglDestroyContext(egl_disp, egl_ctx);
egl_ctx = EGL_NO_CONTEXT;
}
if (screen_win != NULL) {
screen_destroy_window(screen_win);
screen_win = NULL;
}
eglTerminate(egl_disp);
egl_disp = EGL_NO_DISPLAY;
}
eglReleaseThread();
}
void
bbutil_swap() {
int rc = eglSwapBuffers(egl_disp, egl_surf);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglSwapBuffers");
}
}
void
bbutil_clear() {
glClear(GL_COLOR_BUFFER_BIT);
}
char *
get_window_group_id()
{
static char s_window_group_id[16] = "";
if (s_window_group_id[0] == '\0') {
snprintf(s_window_group_id, sizeof(s_window_group_id), "%d", getpid());
}
return s_window_group_id;
}
int bbutil_rotate_screen_surface(int angle) {
int rc, rotation, skip = 1, temp;
EGLint interval = 1;
int size[2];
if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
fprintf(stderr, "Invalid angle\n");
return EXIT_FAILURE;
}
rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &rotation);
if (rc) {
perror("screen_set_window_property_iv");
return EXIT_FAILURE;
}
rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
if (rc) {
perror("screen_set_window_property_iv");
return EXIT_FAILURE;
}
switch (angle - rotation) {
case -270:
case -90:
case 90:
case 270:
temp = size[0];
size[0] = size[1];
size[1] = temp;
skip = 0;
break;
}
if (!skip) {
rc = eglMakeCurrent(egl_disp, NULL, NULL, NULL);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglMakeCurrent");
return EXIT_FAILURE;
}
rc = eglDestroySurface(egl_disp, egl_surf);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglMakeCurrent");
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_SIZE, size);
if (rc) {
perror("screen_set_window_property_iv");
return EXIT_FAILURE;
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size);
if (rc) {
perror("screen_set_window_property_iv");
return EXIT_FAILURE;
}
egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, NULL);
if (egl_surf == EGL_NO_SURFACE) {
bbutil_egl_perror("eglCreateWindowSurface");
return EXIT_FAILURE;
}
rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglMakeCurrent");
return EXIT_FAILURE;
}
rc = eglSwapInterval(egl_disp, interval);
if (rc != EGL_TRUE) {
bbutil_egl_perror("eglSwapInterval");
return EXIT_FAILURE;
}
}
rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle);
if (rc) {
perror("screen_set_window_property_iv");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}