132001f49Smrg/* 232001f49Smrg * Copyright (C) 2010 LunarG Inc. 332001f49Smrg * 432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 532001f49Smrg * copy of this software and associated documentation files (the "Software"), 632001f49Smrg * to deal in the Software without restriction, including without limitation 732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 932001f49Smrg * Software is furnished to do so, subject to the following conditions: 1032001f49Smrg * 1132001f49Smrg * The above copyright notice and this permission notice shall be included 1232001f49Smrg * in all copies or substantial portions of the Software. 1332001f49Smrg * 1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1532001f49Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1732001f49Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1832001f49Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1932001f49Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2032001f49Smrg * DEALINGS IN THE SOFTWARE. 2132001f49Smrg * 2232001f49Smrg * Authors: 2332001f49Smrg * Chia-I Wu <olv@lunarg.com> 2432001f49Smrg */ 2532001f49Smrg 2632001f49Smrg#include <stdio.h> 2732001f49Smrg#include <stdlib.h> 2832001f49Smrg#include <string.h> 2932001f49Smrg#include <stdarg.h> 3032001f49Smrg#include <sys/time.h> 3132001f49Smrg 3232001f49Smrg#include "EGL/egl.h" 3332001f49Smrg#include "EGL/eglext.h" 3432001f49Smrg 3532001f49Smrg#include "eglutint.h" 3632001f49Smrg 3732001f49Smrgstatic struct eglut_state _eglut_state = { 3832001f49Smrg .api_mask = EGLUT_OPENGL_ES1_BIT, 3932001f49Smrg .window_width = 300, 4032001f49Smrg .window_height = 300, 4132001f49Smrg .verbose = 0, 4232001f49Smrg .num_windows = 0, 4332001f49Smrg}; 4432001f49Smrg 4532001f49Smrgstruct eglut_state *_eglut = &_eglut_state; 4632001f49Smrg 4732001f49Smrgvoid 4832001f49Smrg_eglutFatal(char *format, ...) 4932001f49Smrg{ 5032001f49Smrg va_list args; 5132001f49Smrg 5232001f49Smrg va_start(args, format); 5332001f49Smrg 5432001f49Smrg fprintf(stderr, "EGLUT: "); 5532001f49Smrg vfprintf(stderr, format, args); 5632001f49Smrg va_end(args); 5732001f49Smrg putc('\n', stderr); 5832001f49Smrg 5932001f49Smrg exit(1); 6032001f49Smrg} 6132001f49Smrg 6232001f49Smrg/* return current time (in milliseconds) */ 6332001f49Smrgint 6432001f49Smrg_eglutNow(void) 6532001f49Smrg{ 6632001f49Smrg struct timeval tv; 6732001f49Smrg#ifdef __VMS 6832001f49Smrg (void) gettimeofday(&tv, NULL ); 6932001f49Smrg#else 7032001f49Smrg struct timezone tz; 7132001f49Smrg (void) gettimeofday(&tv, &tz); 7232001f49Smrg#endif 7332001f49Smrg return tv.tv_sec * 1000 + tv.tv_usec / 1000; 7432001f49Smrg} 7532001f49Smrg 7632001f49Smrgstatic void 7732001f49Smrg_eglutDestroyWindow(struct eglut_window *win) 7832001f49Smrg{ 797ec3b29aSmrg if (_eglut->surface_type != EGL_PBUFFER_BIT) 8032001f49Smrg eglDestroySurface(_eglut->dpy, win->surface); 8132001f49Smrg 8232001f49Smrg _eglutNativeFiniWindow(win); 8332001f49Smrg 8432001f49Smrg eglDestroyContext(_eglut->dpy, win->context); 8532001f49Smrg} 8632001f49Smrg 8732001f49Smrgstatic EGLConfig 8832001f49Smrg_eglutChooseConfig(void) 8932001f49Smrg{ 9032001f49Smrg EGLConfig config; 9132001f49Smrg EGLint config_attribs[32]; 9232001f49Smrg EGLint renderable_type, num_configs, i; 9332001f49Smrg 9432001f49Smrg i = 0; 9532001f49Smrg config_attribs[i++] = EGL_RED_SIZE; 9632001f49Smrg config_attribs[i++] = 1; 9732001f49Smrg config_attribs[i++] = EGL_GREEN_SIZE; 9832001f49Smrg config_attribs[i++] = 1; 9932001f49Smrg config_attribs[i++] = EGL_BLUE_SIZE; 10032001f49Smrg config_attribs[i++] = 1; 10132001f49Smrg config_attribs[i++] = EGL_DEPTH_SIZE; 10232001f49Smrg config_attribs[i++] = 1; 10332001f49Smrg 10432001f49Smrg config_attribs[i++] = EGL_SURFACE_TYPE; 10532001f49Smrg config_attribs[i++] = _eglut->surface_type; 10632001f49Smrg 10732001f49Smrg config_attribs[i++] = EGL_RENDERABLE_TYPE; 10832001f49Smrg renderable_type = 0x0; 10932001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_BIT) 11032001f49Smrg renderable_type |= EGL_OPENGL_BIT; 11132001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_ES1_BIT) 11232001f49Smrg renderable_type |= EGL_OPENGL_ES_BIT; 11332001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) 11432001f49Smrg renderable_type |= EGL_OPENGL_ES2_BIT; 11532001f49Smrg if (_eglut->api_mask & EGLUT_OPENVG_BIT) 11632001f49Smrg renderable_type |= EGL_OPENVG_BIT; 11732001f49Smrg config_attribs[i++] = renderable_type; 11832001f49Smrg 11932001f49Smrg config_attribs[i] = EGL_NONE; 12032001f49Smrg 12132001f49Smrg if (!eglChooseConfig(_eglut->dpy, 12232001f49Smrg config_attribs, &config, 1, &num_configs) || !num_configs) 12332001f49Smrg _eglutFatal("failed to choose a config"); 12432001f49Smrg 12532001f49Smrg return config; 12632001f49Smrg} 12732001f49Smrg 12832001f49Smrgstatic struct eglut_window * 12932001f49Smrg_eglutCreateWindow(const char *title, int x, int y, int w, int h) 13032001f49Smrg{ 13132001f49Smrg struct eglut_window *win; 13232001f49Smrg EGLint context_attribs[4]; 13332001f49Smrg EGLint api, i; 13432001f49Smrg 13532001f49Smrg win = calloc(1, sizeof(*win)); 13632001f49Smrg if (!win) 13732001f49Smrg _eglutFatal("failed to allocate window"); 13832001f49Smrg 13932001f49Smrg win->config = _eglutChooseConfig(); 14032001f49Smrg 14132001f49Smrg i = 0; 14232001f49Smrg context_attribs[i] = EGL_NONE; 14332001f49Smrg 14432001f49Smrg /* multiple APIs? */ 14532001f49Smrg 14632001f49Smrg api = EGL_OPENGL_ES_API; 14732001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_BIT) { 14832001f49Smrg api = EGL_OPENGL_API; 14932001f49Smrg } 15032001f49Smrg else if (_eglut->api_mask & EGLUT_OPENVG_BIT) { 15132001f49Smrg api = EGL_OPENVG_API; 15232001f49Smrg } 15332001f49Smrg else if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) { 15432001f49Smrg context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION; 15532001f49Smrg context_attribs[i++] = 2; 15632001f49Smrg } 15732001f49Smrg 15832001f49Smrg context_attribs[i] = EGL_NONE; 15932001f49Smrg 16032001f49Smrg eglBindAPI(api); 16132001f49Smrg win->context = eglCreateContext(_eglut->dpy, 16232001f49Smrg win->config, EGL_NO_CONTEXT, context_attribs); 16332001f49Smrg if (!win->context) 16432001f49Smrg _eglutFatal("failed to create context"); 16532001f49Smrg 16632001f49Smrg _eglutNativeInitWindow(win, title, x, y, w, h); 16732001f49Smrg switch (_eglut->surface_type) { 16832001f49Smrg case EGL_WINDOW_BIT: 16932001f49Smrg win->surface = eglCreateWindowSurface(_eglut->dpy, 17032001f49Smrg win->config, win->native.u.window, NULL); 17132001f49Smrg break; 17232001f49Smrg case EGL_PIXMAP_BIT: 17332001f49Smrg win->surface = eglCreatePixmapSurface(_eglut->dpy, 17432001f49Smrg win->config, win->native.u.pixmap, NULL); 17532001f49Smrg break; 17632001f49Smrg case EGL_PBUFFER_BIT: 17732001f49Smrg win->surface = win->native.u.surface; 17832001f49Smrg break; 17932001f49Smrg default: 18032001f49Smrg break; 18132001f49Smrg } 18232001f49Smrg if (win->surface == EGL_NO_SURFACE) 18332001f49Smrg _eglutFatal("failed to create surface"); 18432001f49Smrg 18532001f49Smrg return win; 18632001f49Smrg} 18732001f49Smrg 18832001f49Smrgvoid 18932001f49SmrgeglutInitAPIMask(int mask) 19032001f49Smrg{ 19132001f49Smrg _eglut->api_mask = mask; 19232001f49Smrg} 19332001f49Smrg 19432001f49Smrgvoid 19532001f49SmrgeglutInitWindowSize(int width, int height) 19632001f49Smrg{ 19732001f49Smrg _eglut->window_width = width; 19832001f49Smrg _eglut->window_height = height; 19932001f49Smrg} 20032001f49Smrg 20132001f49Smrgvoid 20232001f49SmrgeglutInit(int argc, char **argv) 20332001f49Smrg{ 20432001f49Smrg int i; 20532001f49Smrg 20632001f49Smrg for (i = 1; i < argc; i++) { 20732001f49Smrg if (strcmp(argv[i], "-display") == 0) 20832001f49Smrg _eglut->display_name = argv[++i]; 20932001f49Smrg else if (strcmp(argv[i], "-info") == 0) { 21032001f49Smrg _eglut->verbose = 1; 21132001f49Smrg } 21232001f49Smrg } 21332001f49Smrg 21432001f49Smrg _eglutNativeInitDisplay(); 21532001f49Smrg _eglut->dpy = eglGetDisplay(_eglut->native_dpy); 21632001f49Smrg 21732001f49Smrg if (!eglInitialize(_eglut->dpy, &_eglut->major, &_eglut->minor)) 21832001f49Smrg _eglutFatal("failed to initialize EGL display"); 21932001f49Smrg 22032001f49Smrg _eglut->init_time = _eglutNow(); 22132001f49Smrg 22232001f49Smrg printf("EGL_VERSION = %s\n", eglQueryString(_eglut->dpy, EGL_VERSION)); 22332001f49Smrg if (_eglut->verbose) { 22432001f49Smrg printf("EGL_VENDOR = %s\n", eglQueryString(_eglut->dpy, EGL_VENDOR)); 22532001f49Smrg printf("EGL_EXTENSIONS = %s\n", 22632001f49Smrg eglQueryString(_eglut->dpy, EGL_EXTENSIONS)); 22732001f49Smrg printf("EGL_CLIENT_APIS = %s\n", 22832001f49Smrg eglQueryString(_eglut->dpy, EGL_CLIENT_APIS)); 22932001f49Smrg } 23032001f49Smrg} 23132001f49Smrg 23232001f49Smrgint 23332001f49SmrgeglutGet(int state) 23432001f49Smrg{ 23532001f49Smrg int val; 23632001f49Smrg 23732001f49Smrg switch (state) { 23832001f49Smrg case EGLUT_ELAPSED_TIME: 23932001f49Smrg val = _eglutNow() - _eglut->init_time; 24032001f49Smrg break; 24132001f49Smrg default: 24232001f49Smrg val = -1; 24332001f49Smrg break; 24432001f49Smrg } 24532001f49Smrg 24632001f49Smrg return val; 24732001f49Smrg} 24832001f49Smrg 24932001f49Smrgvoid 25032001f49SmrgeglutIdleFunc(EGLUTidleCB func) 25132001f49Smrg{ 25232001f49Smrg _eglut->idle_cb = func; 25332001f49Smrg} 25432001f49Smrg 25532001f49Smrgvoid 25632001f49SmrgeglutPostRedisplay(void) 25732001f49Smrg{ 25832001f49Smrg _eglut->redisplay = 1; 25932001f49Smrg} 26032001f49Smrg 26132001f49Smrgvoid 26232001f49SmrgeglutMainLoop(void) 26332001f49Smrg{ 26432001f49Smrg struct eglut_window *win = _eglut->current; 26532001f49Smrg 26632001f49Smrg if (!win) 26732001f49Smrg _eglutFatal("no window is created\n"); 26832001f49Smrg 26932001f49Smrg if (win->reshape_cb) 27032001f49Smrg win->reshape_cb(win->native.width, win->native.height); 27132001f49Smrg 27232001f49Smrg _eglutNativeEventLoop(); 27332001f49Smrg} 27432001f49Smrg 27532001f49Smrgstatic void 27632001f49Smrg_eglutFini(void) 27732001f49Smrg{ 27832001f49Smrg eglTerminate(_eglut->dpy); 27932001f49Smrg _eglutNativeFiniDisplay(); 28032001f49Smrg} 28132001f49Smrg 28232001f49Smrgvoid 28332001f49SmrgeglutDestroyWindow(int win) 28432001f49Smrg{ 28532001f49Smrg struct eglut_window *window = _eglut->current; 28632001f49Smrg 28732001f49Smrg if (window->index != win) 28832001f49Smrg return; 28932001f49Smrg 2907ec3b29aSmrg eglMakeCurrent(_eglut->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 29132001f49Smrg 29232001f49Smrg _eglutDestroyWindow(_eglut->current); 29332001f49Smrg} 29432001f49Smrg 29532001f49Smrgstatic void 29632001f49Smrg_eglutDefaultKeyboard(unsigned char key) 29732001f49Smrg{ 29832001f49Smrg if (key == 27) { 29932001f49Smrg if (_eglut->current) 30032001f49Smrg eglutDestroyWindow(_eglut->current->index); 30132001f49Smrg _eglutFini(); 30232001f49Smrg 30332001f49Smrg exit(0); 30432001f49Smrg } 30532001f49Smrg} 30632001f49Smrg 30732001f49Smrgint 30832001f49SmrgeglutCreateWindow(const char *title) 30932001f49Smrg{ 31032001f49Smrg struct eglut_window *win; 31132001f49Smrg 31232001f49Smrg win = _eglutCreateWindow(title, 0, 0, 31332001f49Smrg _eglut->window_width, _eglut->window_height); 31432001f49Smrg 31532001f49Smrg win->index = _eglut->num_windows++; 31632001f49Smrg win->reshape_cb = NULL; 31732001f49Smrg win->display_cb = NULL; 31832001f49Smrg win->keyboard_cb = _eglutDefaultKeyboard; 31932001f49Smrg win->special_cb = NULL; 32032001f49Smrg 32132001f49Smrg if (!eglMakeCurrent(_eglut->dpy, win->surface, win->surface, win->context)) 32232001f49Smrg _eglutFatal("failed to make window current"); 32332001f49Smrg _eglut->current = win; 32432001f49Smrg 32532001f49Smrg return win->index; 32632001f49Smrg} 32732001f49Smrg 32832001f49Smrgint 32932001f49SmrgeglutGetWindowWidth(void) 33032001f49Smrg{ 33132001f49Smrg struct eglut_window *win = _eglut->current; 33232001f49Smrg return win->native.width; 33332001f49Smrg} 33432001f49Smrg 33532001f49Smrgint 33632001f49SmrgeglutGetWindowHeight(void) 33732001f49Smrg{ 33832001f49Smrg struct eglut_window *win = _eglut->current; 33932001f49Smrg return win->native.height; 34032001f49Smrg} 34132001f49Smrg 34232001f49Smrgvoid 34332001f49SmrgeglutDisplayFunc(EGLUTdisplayCB func) 34432001f49Smrg{ 34532001f49Smrg struct eglut_window *win = _eglut->current; 34632001f49Smrg win->display_cb = func; 34732001f49Smrg 34832001f49Smrg} 34932001f49Smrg 35032001f49Smrgvoid 35132001f49SmrgeglutReshapeFunc(EGLUTreshapeCB func) 35232001f49Smrg{ 35332001f49Smrg struct eglut_window *win = _eglut->current; 35432001f49Smrg win->reshape_cb = func; 35532001f49Smrg} 35632001f49Smrg 35732001f49Smrgvoid 35832001f49SmrgeglutKeyboardFunc(EGLUTkeyboardCB func) 35932001f49Smrg{ 36032001f49Smrg struct eglut_window *win = _eglut->current; 36132001f49Smrg win->keyboard_cb = func; 36232001f49Smrg} 36332001f49Smrg 36432001f49Smrgvoid 36532001f49SmrgeglutSpecialFunc(EGLUTspecialCB func) 36632001f49Smrg{ 36732001f49Smrg struct eglut_window *win = _eglut->current; 36832001f49Smrg win->special_cb = func; 36932001f49Smrg} 370