/* * Copyright (C) 2009 Chia-I Wu * * Based on eglgears by * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #define EGL_EGLEXT_PROTOTYPES #include #include #include "winsys.h" #define MAX_MODES 100 static struct { EGLBoolean verbose; EGLDisplay dpy; EGLConfig conf; EGLScreenMESA screen; EGLModeMESA mode; EGLint width, height; EGLContext ctx; EGLSurface surf; } screen; static EGLBoolean init_screen(void) { EGLModeMESA modes[MAX_MODES]; EGLint num_screens, num_modes; EGLint width, height, best_mode; EGLint i; if (!eglGetScreensMESA(screen.dpy, &screen.screen, 1, &num_screens) || !num_screens) { printf("eglGetScreensMESA failed\n"); return EGL_FALSE; } if (!eglGetModesMESA(screen.dpy, screen.screen, modes, MAX_MODES, &num_modes) || !num_modes) { printf("eglGetModesMESA failed!\n"); return EGL_FALSE; } printf("Found %d modes:\n", num_modes); best_mode = 0; width = 0; height = 0; for (i = 0; i < num_modes; i++) { EGLint w, h; eglGetModeAttribMESA(screen.dpy, modes[i], EGL_WIDTH, &w); eglGetModeAttribMESA(screen.dpy, modes[i], EGL_HEIGHT, &h); printf("%3d: %d x %d\n", i, w, h); if (w > width && h > height) { width = w; height = h; best_mode = i; } } screen.mode = modes[best_mode]; screen.width = width; screen.height = height; return EGL_TRUE; } static EGLBoolean init_display(void) { EGLint maj, min; const char *exts; const EGLint attribs[] = { EGL_SURFACE_TYPE, 0x0, /* should be EGL_SCREEN_BIT_MESA */ EGL_RENDERABLE_TYPE, 0x0, /* should be EGL_OPENGL_ES_BIT */ EGL_NONE }; EGLint num_configs; screen.dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!screen.dpy) { printf("eglGetDisplay failed\n"); return EGL_FALSE; } if (!eglInitialize(screen.dpy, &maj, &min)) { printf("eglInitialize failed\n"); return EGL_FALSE; } printf("EGL_VERSION = %s\n", eglQueryString(screen.dpy, EGL_VERSION)); printf("EGL_VENDOR = %s\n", eglQueryString(screen.dpy, EGL_VENDOR)); exts = eglQueryString(screen.dpy, EGL_EXTENSIONS); assert(exts); if (!strstr(exts, "EGL_MESA_screen_surface")) { printf("EGL_MESA_screen_surface is not supported\n"); return EGL_FALSE; } if (!eglChooseConfig(screen.dpy, attribs, &screen.conf, 1, &num_configs) || !num_configs) { printf("eglChooseConfig failed\n"); return EGL_FALSE; } return EGL_TRUE; } EGLBoolean winsysInitScreen(void) { EGLint surf_attribs[20]; EGLint i; EGLBoolean ok; if (!init_display()) goto fail; if (!init_screen()) goto fail; /* create context */ screen.ctx = eglCreateContext(screen.dpy, screen.conf, EGL_NO_CONTEXT, NULL); if (screen.ctx == EGL_NO_CONTEXT) { printf("eglCreateContext failed\n"); goto fail; } i = 0; surf_attribs[i++] = EGL_WIDTH; surf_attribs[i++] = screen.width; surf_attribs[i++] = EGL_HEIGHT; surf_attribs[i++] = screen.height; surf_attribs[i++] = EGL_NONE; /* create surface */ printf("Using screen size: %d x %d\n", screen.width, screen.height); screen.surf = eglCreateScreenSurfaceMESA(screen.dpy, screen.conf, surf_attribs); if (screen.surf == EGL_NO_SURFACE) { printf("eglCreateScreenSurfaceMESA failed\n"); goto fail; } ok = eglMakeCurrent(screen.dpy, screen.surf, screen.surf, screen.ctx); if (!ok) { printf("eglMakeCurrent failed\n"); goto fail; } ok = eglShowScreenSurfaceMESA(screen.dpy, screen.screen, screen.surf, screen.mode); if (!ok) { printf("eglShowScreenSurfaceMESA failed\n"); goto fail; } return EGL_TRUE; fail: winsysFiniScreen(); return EGL_FALSE; } EGLBoolean winsysQueryScreenSize(EGLint *width, EGLint *height) { if (!screen.dpy) return EGL_FALSE; if (width) *width = screen.width; if (height) *height = screen.height; return EGL_TRUE; } void winsysFiniScreen(void) { if (screen.dpy) { eglMakeCurrent(screen.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (screen.surf != EGL_NO_SURFACE) eglDestroySurface(screen.dpy, screen.surf); if (screen.ctx != EGL_NO_CONTEXT) eglDestroyContext(screen.dpy, screen.ctx); eglTerminate(screen.dpy); memset(&screen, 0, sizeof(screen)); } } void winsysSwapBuffers(void) { eglSwapBuffers(screen.dpy, screen.surf); } /* return current time (in seconds) */ double winsysNow(void) { struct timeval tv; gettimeofday(&tv, NULL); return (double) tv.tv_sec + tv.tv_usec / 1000000.0; } void winsysRun(double seconds, void (*draw_frame)(void *data), void *data) { double begin, end, last_frame, duration; EGLint num_frames = 0; begin = winsysNow(); end = begin + seconds; last_frame = begin; while (last_frame < end) { draw_frame(data); winsysSwapBuffers(); last_frame = winsysNow(); num_frames++; } duration = last_frame - begin; printf("%d frames in %3.1f seconds = %6.3f FPS\n", num_frames, duration, (double) num_frames / duration); }