eglut.c revision 32001f49
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{ 7932001f49Smrg if (_eglut->surface_type != EGL_PBUFFER_BIT && 8032001f49Smrg _eglut->surface_type != EGL_SCREEN_BIT_MESA) 8132001f49Smrg eglDestroySurface(_eglut->dpy, win->surface); 8232001f49Smrg 8332001f49Smrg _eglutNativeFiniWindow(win); 8432001f49Smrg 8532001f49Smrg eglDestroyContext(_eglut->dpy, win->context); 8632001f49Smrg} 8732001f49Smrg 8832001f49Smrgstatic EGLConfig 8932001f49Smrg_eglutChooseConfig(void) 9032001f49Smrg{ 9132001f49Smrg EGLConfig config; 9232001f49Smrg EGLint config_attribs[32]; 9332001f49Smrg EGLint renderable_type, num_configs, i; 9432001f49Smrg 9532001f49Smrg i = 0; 9632001f49Smrg config_attribs[i++] = EGL_RED_SIZE; 9732001f49Smrg config_attribs[i++] = 1; 9832001f49Smrg config_attribs[i++] = EGL_GREEN_SIZE; 9932001f49Smrg config_attribs[i++] = 1; 10032001f49Smrg config_attribs[i++] = EGL_BLUE_SIZE; 10132001f49Smrg config_attribs[i++] = 1; 10232001f49Smrg config_attribs[i++] = EGL_DEPTH_SIZE; 10332001f49Smrg config_attribs[i++] = 1; 10432001f49Smrg 10532001f49Smrg config_attribs[i++] = EGL_SURFACE_TYPE; 10632001f49Smrg config_attribs[i++] = _eglut->surface_type; 10732001f49Smrg 10832001f49Smrg config_attribs[i++] = EGL_RENDERABLE_TYPE; 10932001f49Smrg renderable_type = 0x0; 11032001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_BIT) 11132001f49Smrg renderable_type |= EGL_OPENGL_BIT; 11232001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_ES1_BIT) 11332001f49Smrg renderable_type |= EGL_OPENGL_ES_BIT; 11432001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) 11532001f49Smrg renderable_type |= EGL_OPENGL_ES2_BIT; 11632001f49Smrg if (_eglut->api_mask & EGLUT_OPENVG_BIT) 11732001f49Smrg renderable_type |= EGL_OPENVG_BIT; 11832001f49Smrg config_attribs[i++] = renderable_type; 11932001f49Smrg 12032001f49Smrg config_attribs[i] = EGL_NONE; 12132001f49Smrg 12232001f49Smrg if (!eglChooseConfig(_eglut->dpy, 12332001f49Smrg config_attribs, &config, 1, &num_configs) || !num_configs) 12432001f49Smrg _eglutFatal("failed to choose a config"); 12532001f49Smrg 12632001f49Smrg return config; 12732001f49Smrg} 12832001f49Smrg 12932001f49Smrgstatic struct eglut_window * 13032001f49Smrg_eglutCreateWindow(const char *title, int x, int y, int w, int h) 13132001f49Smrg{ 13232001f49Smrg struct eglut_window *win; 13332001f49Smrg EGLint context_attribs[4]; 13432001f49Smrg EGLint api, i; 13532001f49Smrg 13632001f49Smrg win = calloc(1, sizeof(*win)); 13732001f49Smrg if (!win) 13832001f49Smrg _eglutFatal("failed to allocate window"); 13932001f49Smrg 14032001f49Smrg win->config = _eglutChooseConfig(); 14132001f49Smrg 14232001f49Smrg i = 0; 14332001f49Smrg context_attribs[i] = EGL_NONE; 14432001f49Smrg 14532001f49Smrg /* multiple APIs? */ 14632001f49Smrg 14732001f49Smrg api = EGL_OPENGL_ES_API; 14832001f49Smrg if (_eglut->api_mask & EGLUT_OPENGL_BIT) { 14932001f49Smrg api = EGL_OPENGL_API; 15032001f49Smrg } 15132001f49Smrg else if (_eglut->api_mask & EGLUT_OPENVG_BIT) { 15232001f49Smrg api = EGL_OPENVG_API; 15332001f49Smrg } 15432001f49Smrg else if (_eglut->api_mask & EGLUT_OPENGL_ES2_BIT) { 15532001f49Smrg context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION; 15632001f49Smrg context_attribs[i++] = 2; 15732001f49Smrg } 15832001f49Smrg 15932001f49Smrg context_attribs[i] = EGL_NONE; 16032001f49Smrg 16132001f49Smrg eglBindAPI(api); 16232001f49Smrg win->context = eglCreateContext(_eglut->dpy, 16332001f49Smrg win->config, EGL_NO_CONTEXT, context_attribs); 16432001f49Smrg if (!win->context) 16532001f49Smrg _eglutFatal("failed to create context"); 16632001f49Smrg 16732001f49Smrg _eglutNativeInitWindow(win, title, x, y, w, h); 16832001f49Smrg switch (_eglut->surface_type) { 16932001f49Smrg case EGL_WINDOW_BIT: 17032001f49Smrg win->surface = eglCreateWindowSurface(_eglut->dpy, 17132001f49Smrg win->config, win->native.u.window, NULL); 17232001f49Smrg break; 17332001f49Smrg case EGL_PIXMAP_BIT: 17432001f49Smrg win->surface = eglCreatePixmapSurface(_eglut->dpy, 17532001f49Smrg win->config, win->native.u.pixmap, NULL); 17632001f49Smrg break; 17732001f49Smrg case EGL_PBUFFER_BIT: 17832001f49Smrg case EGL_SCREEN_BIT_MESA: 17932001f49Smrg win->surface = win->native.u.surface; 18032001f49Smrg break; 18132001f49Smrg default: 18232001f49Smrg break; 18332001f49Smrg } 18432001f49Smrg if (win->surface == EGL_NO_SURFACE) 18532001f49Smrg _eglutFatal("failed to create surface"); 18632001f49Smrg 18732001f49Smrg return win; 18832001f49Smrg} 18932001f49Smrg 19032001f49Smrgvoid 19132001f49SmrgeglutInitAPIMask(int mask) 19232001f49Smrg{ 19332001f49Smrg _eglut->api_mask = mask; 19432001f49Smrg} 19532001f49Smrg 19632001f49Smrgvoid 19732001f49SmrgeglutInitWindowSize(int width, int height) 19832001f49Smrg{ 19932001f49Smrg _eglut->window_width = width; 20032001f49Smrg _eglut->window_height = height; 20132001f49Smrg} 20232001f49Smrg 20332001f49Smrgvoid 20432001f49SmrgeglutInit(int argc, char **argv) 20532001f49Smrg{ 20632001f49Smrg int i; 20732001f49Smrg 20832001f49Smrg for (i = 1; i < argc; i++) { 20932001f49Smrg if (strcmp(argv[i], "-display") == 0) 21032001f49Smrg _eglut->display_name = argv[++i]; 21132001f49Smrg else if (strcmp(argv[i], "-info") == 0) { 21232001f49Smrg _eglut->verbose = 1; 21332001f49Smrg } 21432001f49Smrg } 21532001f49Smrg 21632001f49Smrg _eglutNativeInitDisplay(); 21732001f49Smrg _eglut->dpy = eglGetDisplay(_eglut->native_dpy); 21832001f49Smrg 21932001f49Smrg if (!eglInitialize(_eglut->dpy, &_eglut->major, &_eglut->minor)) 22032001f49Smrg _eglutFatal("failed to initialize EGL display"); 22132001f49Smrg 22232001f49Smrg _eglut->init_time = _eglutNow(); 22332001f49Smrg 22432001f49Smrg printf("EGL_VERSION = %s\n", eglQueryString(_eglut->dpy, EGL_VERSION)); 22532001f49Smrg if (_eglut->verbose) { 22632001f49Smrg printf("EGL_VENDOR = %s\n", eglQueryString(_eglut->dpy, EGL_VENDOR)); 22732001f49Smrg printf("EGL_EXTENSIONS = %s\n", 22832001f49Smrg eglQueryString(_eglut->dpy, EGL_EXTENSIONS)); 22932001f49Smrg printf("EGL_CLIENT_APIS = %s\n", 23032001f49Smrg eglQueryString(_eglut->dpy, EGL_CLIENT_APIS)); 23132001f49Smrg } 23232001f49Smrg} 23332001f49Smrg 23432001f49Smrgint 23532001f49SmrgeglutGet(int state) 23632001f49Smrg{ 23732001f49Smrg int val; 23832001f49Smrg 23932001f49Smrg switch (state) { 24032001f49Smrg case EGLUT_ELAPSED_TIME: 24132001f49Smrg val = _eglutNow() - _eglut->init_time; 24232001f49Smrg break; 24332001f49Smrg default: 24432001f49Smrg val = -1; 24532001f49Smrg break; 24632001f49Smrg } 24732001f49Smrg 24832001f49Smrg return val; 24932001f49Smrg} 25032001f49Smrg 25132001f49Smrgvoid 25232001f49SmrgeglutIdleFunc(EGLUTidleCB func) 25332001f49Smrg{ 25432001f49Smrg _eglut->idle_cb = func; 25532001f49Smrg} 25632001f49Smrg 25732001f49Smrgvoid 25832001f49SmrgeglutPostRedisplay(void) 25932001f49Smrg{ 26032001f49Smrg _eglut->redisplay = 1; 26132001f49Smrg} 26232001f49Smrg 26332001f49Smrgvoid 26432001f49SmrgeglutMainLoop(void) 26532001f49Smrg{ 26632001f49Smrg struct eglut_window *win = _eglut->current; 26732001f49Smrg 26832001f49Smrg if (!win) 26932001f49Smrg _eglutFatal("no window is created\n"); 27032001f49Smrg 27132001f49Smrg if (win->reshape_cb) 27232001f49Smrg win->reshape_cb(win->native.width, win->native.height); 27332001f49Smrg 27432001f49Smrg _eglutNativeEventLoop(); 27532001f49Smrg} 27632001f49Smrg 27732001f49Smrgstatic void 27832001f49Smrg_eglutFini(void) 27932001f49Smrg{ 28032001f49Smrg eglTerminate(_eglut->dpy); 28132001f49Smrg _eglutNativeFiniDisplay(); 28232001f49Smrg} 28332001f49Smrg 28432001f49Smrgvoid 28532001f49SmrgeglutDestroyWindow(int win) 28632001f49Smrg{ 28732001f49Smrg struct eglut_window *window = _eglut->current; 28832001f49Smrg 28932001f49Smrg if (window->index != win) 29032001f49Smrg return; 29132001f49Smrg 29232001f49Smrg /* XXX it causes some bug in st/egl KMS backend */ 29332001f49Smrg if ( _eglut->surface_type != EGL_SCREEN_BIT_MESA) 29432001f49Smrg eglMakeCurrent(_eglut->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 29532001f49Smrg 29632001f49Smrg _eglutDestroyWindow(_eglut->current); 29732001f49Smrg} 29832001f49Smrg 29932001f49Smrgstatic void 30032001f49Smrg_eglutDefaultKeyboard(unsigned char key) 30132001f49Smrg{ 30232001f49Smrg if (key == 27) { 30332001f49Smrg if (_eglut->current) 30432001f49Smrg eglutDestroyWindow(_eglut->current->index); 30532001f49Smrg _eglutFini(); 30632001f49Smrg 30732001f49Smrg exit(0); 30832001f49Smrg } 30932001f49Smrg} 31032001f49Smrg 31132001f49Smrgint 31232001f49SmrgeglutCreateWindow(const char *title) 31332001f49Smrg{ 31432001f49Smrg struct eglut_window *win; 31532001f49Smrg 31632001f49Smrg win = _eglutCreateWindow(title, 0, 0, 31732001f49Smrg _eglut->window_width, _eglut->window_height); 31832001f49Smrg 31932001f49Smrg win->index = _eglut->num_windows++; 32032001f49Smrg win->reshape_cb = NULL; 32132001f49Smrg win->display_cb = NULL; 32232001f49Smrg win->keyboard_cb = _eglutDefaultKeyboard; 32332001f49Smrg win->special_cb = NULL; 32432001f49Smrg 32532001f49Smrg if (!eglMakeCurrent(_eglut->dpy, win->surface, win->surface, win->context)) 32632001f49Smrg _eglutFatal("failed to make window current"); 32732001f49Smrg _eglut->current = win; 32832001f49Smrg 32932001f49Smrg return win->index; 33032001f49Smrg} 33132001f49Smrg 33232001f49Smrgint 33332001f49SmrgeglutGetWindowWidth(void) 33432001f49Smrg{ 33532001f49Smrg struct eglut_window *win = _eglut->current; 33632001f49Smrg return win->native.width; 33732001f49Smrg} 33832001f49Smrg 33932001f49Smrgint 34032001f49SmrgeglutGetWindowHeight(void) 34132001f49Smrg{ 34232001f49Smrg struct eglut_window *win = _eglut->current; 34332001f49Smrg return win->native.height; 34432001f49Smrg} 34532001f49Smrg 34632001f49Smrgvoid 34732001f49SmrgeglutDisplayFunc(EGLUTdisplayCB func) 34832001f49Smrg{ 34932001f49Smrg struct eglut_window *win = _eglut->current; 35032001f49Smrg win->display_cb = func; 35132001f49Smrg 35232001f49Smrg} 35332001f49Smrg 35432001f49Smrgvoid 35532001f49SmrgeglutReshapeFunc(EGLUTreshapeCB func) 35632001f49Smrg{ 35732001f49Smrg struct eglut_window *win = _eglut->current; 35832001f49Smrg win->reshape_cb = func; 35932001f49Smrg} 36032001f49Smrg 36132001f49Smrgvoid 36232001f49SmrgeglutKeyboardFunc(EGLUTkeyboardCB func) 36332001f49Smrg{ 36432001f49Smrg struct eglut_window *win = _eglut->current; 36532001f49Smrg win->keyboard_cb = func; 36632001f49Smrg} 36732001f49Smrg 36832001f49Smrgvoid 36932001f49SmrgeglutSpecialFunc(EGLUTspecialCB func) 37032001f49Smrg{ 37132001f49Smrg struct eglut_window *win = _eglut->current; 37232001f49Smrg win->special_cb = func; 37332001f49Smrg} 374