529 lines
14 KiB
C
529 lines
14 KiB
C
/*
|
|
* Copyright (c) 2011-2013 Research In Motion Limited.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#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;
|
|
}
|
|
|