| /* |
| * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org> |
| * |
| * 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 <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| #include <sys/time.h> |
| |
| #define EGL_EGLEXT_PROTOTYPES |
| |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| |
| #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); |
| } |