texenvprogram: fix for ARB_draw_buffers.
[mesa.git] / progs / es1 / screen / winsys.c
1 /*
2 * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
3 *
4 * Based on eglgears by
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <sys/time.h>
30
31 #define EGL_EGLEXT_PROTOTYPES
32
33 #include <EGL/egl.h>
34 #include <EGL/eglext.h>
35
36 #include "winsys.h"
37
38 #define MAX_MODES 100
39
40 static struct {
41 EGLBoolean verbose;
42
43 EGLDisplay dpy;
44 EGLConfig conf;
45
46 EGLScreenMESA screen;
47 EGLModeMESA mode;
48 EGLint width, height;
49
50 EGLContext ctx;
51 EGLSurface surf;
52 } screen;
53
54
55 static EGLBoolean
56 init_screen(void)
57 {
58 EGLModeMESA modes[MAX_MODES];
59 EGLint num_screens, num_modes;
60 EGLint width, height, best_mode;
61 EGLint i;
62
63 if (!eglGetScreensMESA(screen.dpy, &screen.screen, 1, &num_screens) ||
64 !num_screens) {
65 printf("eglGetScreensMESA failed\n");
66 return EGL_FALSE;
67 }
68
69 if (!eglGetModesMESA(screen.dpy, screen.screen, modes, MAX_MODES,
70 &num_modes) ||
71 !num_modes) {
72 printf("eglGetModesMESA failed!\n");
73 return EGL_FALSE;
74 }
75
76 printf("Found %d modes:\n", num_modes);
77
78 best_mode = 0;
79 width = 0;
80 height = 0;
81 for (i = 0; i < num_modes; i++) {
82 EGLint w, h;
83 eglGetModeAttribMESA(screen.dpy, modes[i], EGL_WIDTH, &w);
84 eglGetModeAttribMESA(screen.dpy, modes[i], EGL_HEIGHT, &h);
85 printf("%3d: %d x %d\n", i, w, h);
86 if (w > width && h > height) {
87 width = w;
88 height = h;
89 best_mode = i;
90 }
91 }
92
93 screen.mode = modes[best_mode];
94 screen.width = width;
95 screen.height = height;
96
97 return EGL_TRUE;
98 }
99
100
101 static EGLBoolean
102 init_display(void)
103 {
104 EGLint maj, min;
105 const char *exts;
106 const EGLint attribs[] = {
107 EGL_SURFACE_TYPE, 0x0, /* should be EGL_SCREEN_BIT_MESA */
108 EGL_RENDERABLE_TYPE, 0x0, /* should be EGL_OPENGL_ES_BIT */
109 EGL_NONE
110 };
111 EGLint num_configs;
112
113 screen.dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
114 if (!screen.dpy) {
115 printf("eglGetDisplay failed\n");
116 return EGL_FALSE;
117 }
118
119 if (!eglInitialize(screen.dpy, &maj, &min)) {
120 printf("eglInitialize failed\n");
121 return EGL_FALSE;
122 }
123
124 printf("EGL_VERSION = %s\n", eglQueryString(screen.dpy, EGL_VERSION));
125 printf("EGL_VENDOR = %s\n", eglQueryString(screen.dpy, EGL_VENDOR));
126
127 exts = eglQueryString(screen.dpy, EGL_EXTENSIONS);
128 assert(exts);
129
130 if (!strstr(exts, "EGL_MESA_screen_surface")) {
131 printf("EGL_MESA_screen_surface is not supported\n");
132 return EGL_FALSE;
133 }
134
135 if (!eglChooseConfig(screen.dpy, attribs, &screen.conf, 1,
136 &num_configs) ||
137 !num_configs) {
138 printf("eglChooseConfig failed\n");
139 return EGL_FALSE;
140 }
141
142 return EGL_TRUE;
143 }
144
145
146 EGLBoolean
147 winsysInitScreen(void)
148 {
149 EGLint surf_attribs[20];
150 EGLint i;
151 EGLBoolean ok;
152
153 if (!init_display())
154 goto fail;
155 if (!init_screen())
156 goto fail;
157
158 /* create context */
159 screen.ctx = eglCreateContext(screen.dpy, screen.conf,
160 EGL_NO_CONTEXT, NULL);
161 if (screen.ctx == EGL_NO_CONTEXT) {
162 printf("eglCreateContext failed\n");
163 goto fail;
164 }
165
166 i = 0;
167 surf_attribs[i++] = EGL_WIDTH;
168 surf_attribs[i++] = screen.width;
169 surf_attribs[i++] = EGL_HEIGHT;
170 surf_attribs[i++] = screen.height;
171 surf_attribs[i++] = EGL_NONE;
172
173 /* create surface */
174 printf("Using screen size: %d x %d\n", screen.width, screen.height);
175 screen.surf = eglCreateScreenSurfaceMESA(screen.dpy, screen.conf,
176 surf_attribs);
177 if (screen.surf == EGL_NO_SURFACE) {
178 printf("eglCreateScreenSurfaceMESA failed\n");
179 goto fail;
180 }
181
182 ok = eglMakeCurrent(screen.dpy, screen.surf, screen.surf, screen.ctx);
183 if (!ok) {
184 printf("eglMakeCurrent failed\n");
185 goto fail;
186 }
187
188 ok = eglShowScreenSurfaceMESA(screen.dpy, screen.screen,
189 screen.surf, screen.mode);
190 if (!ok) {
191 printf("eglShowScreenSurfaceMESA failed\n");
192 goto fail;
193 }
194
195 return EGL_TRUE;
196
197 fail:
198 winsysFiniScreen();
199 return EGL_FALSE;
200 }
201
202
203 EGLBoolean
204 winsysQueryScreenSize(EGLint *width, EGLint *height)
205 {
206 if (!screen.dpy)
207 return EGL_FALSE;
208
209 if (width)
210 *width = screen.width;
211 if (height)
212 *height = screen.height;
213
214 return EGL_TRUE;
215 }
216
217
218 void
219 winsysFiniScreen(void)
220 {
221 if (screen.dpy) {
222 eglMakeCurrent(screen.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
223 EGL_NO_CONTEXT);
224 if (screen.surf != EGL_NO_SURFACE)
225 eglDestroySurface(screen.dpy, screen.surf);
226 if (screen.ctx != EGL_NO_CONTEXT)
227 eglDestroyContext(screen.dpy, screen.ctx);
228 eglTerminate(screen.dpy);
229
230 memset(&screen, 0, sizeof(screen));
231 }
232 }
233
234
235 void
236 winsysSwapBuffers(void)
237 {
238 eglSwapBuffers(screen.dpy, screen.surf);
239 }
240
241
242 /* return current time (in seconds) */
243 double
244 winsysNow(void)
245 {
246 struct timeval tv;
247 gettimeofday(&tv, NULL);
248 return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
249 }
250
251
252 void
253 winsysRun(double seconds, void (*draw_frame)(void *data), void *data)
254 {
255 double begin, end, last_frame, duration;
256 EGLint num_frames = 0;
257
258 begin = winsysNow();
259 end = begin + seconds;
260
261 last_frame = begin;
262 while (last_frame < end) {
263 draw_frame(data);
264 winsysSwapBuffers();
265 last_frame = winsysNow();
266 num_frames++;
267 }
268
269 duration = last_frame - begin;
270 printf("%d frames in %3.1f seconds = %6.3f FPS\n",
271 num_frames, duration, (double) num_frames / duration);
272 }