2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
22 /*---------------------------------------------------------------------------*/
24 static SDL_GLES_Context *context;
27 int video_init(const char *title, const char *icon)
29 SDL_QuitSubSystem(SDL_INIT_VIDEO);
31 if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
33 fprintf(stderr, "%s\n", SDL_GetError());
37 /* This has to happen before mode setting... */
42 if (SDL_GLES_Init(SDL_GLES_VERSION_1_1) != 0)
44 fprintf(stderr, "SDL_GLES_Init failed\n");
49 /* Initialize the video. */
51 if (!video_mode(config_get_d(CONFIG_FULLSCREEN),
52 config_get_d(CONFIG_WIDTH),
53 config_get_d(CONFIG_HEIGHT)))
55 fprintf(stderr, "%s\n", SDL_GetError());
59 /* ...and this has to happen after it. */
63 SDL_WM_SetCaption(title, title);
68 /*---------------------------------------------------------------------------*/
70 int video_mode(int f, int w, int h)
72 int stereo = config_get_d(CONFIG_STEREO) ? 1 : 0;
73 int stencil = config_get_d(CONFIG_REFLECTION) ? 1 : 0;
74 int buffers = config_get_d(CONFIG_MULTISAMPLE) ? 1 : 0;
75 int samples = config_get_d(CONFIG_MULTISAMPLE);
76 int vsync = config_get_d(CONFIG_VSYNC) ? 1 : 0;
78 SDL_GL_SetAttribute(SDL_GL_STEREO, stereo);
79 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil);
80 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers);
81 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
82 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync);
84 /* Require 16-bit double buffer with 16-bit depth buffer. */
86 #ifndef __MAEMO__ /* SDL_GLES already takes care of these */
87 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
88 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
89 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
90 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
91 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
94 /* Try to set the currently specified mode. */
95 if (SDL_SetVideoMode(w, h, 0,
101 (f ? SDL_FULLSCREEN : 0)))
103 config_set_d(CONFIG_FULLSCREEN, f);
104 config_set_d(CONFIG_WIDTH, w);
105 config_set_d(CONFIG_HEIGHT, h);
108 SDL_ShowCursor(SDL_DISABLE);
109 context = SDL_GLES_CreateContext();
112 fprintf(stderr, "SDL_GLES_CreateContext failed\n");
113 fprintf(stderr, "%s\n", SDL_GetError());
117 if (SDL_GLES_MakeCurrent(context) != 0)
119 fprintf(stderr, "SDL_GLES_MakeCurrent failed\n");
120 fprintf(stderr, "%s\n", SDL_GetError());
128 glViewport(0, 0, w, h);
129 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
131 glEnable(GL_NORMALIZE);
132 glEnable(GL_CULL_FACE);
133 glEnable(GL_DEPTH_TEST);
134 glEnable(GL_TEXTURE_2D);
135 glEnable(GL_LIGHTING);
139 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,
140 GL_SEPARATE_SPECULAR_COLOR);
143 glPixelStorei(GL_PACK_ALIGNMENT, 1);
144 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
146 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
147 glDepthFunc(GL_LEQUAL);
149 /* If GL supports multisample, and SDL got a multisample buffer... */
151 if (glext_check("ARB_multisample"))
153 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
154 if (buffers) glEnable(GL_MULTISAMPLE);
157 /* Attempt manual swap control if SDL's is broken. */
159 if (vsync && SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &vsync) == -1)
165 /* If the mode failed, try it without stereo. */
169 config_set_d(CONFIG_STEREO, 0);
170 return video_mode(f, w, h);
173 /* If the mode failed, try decreasing the level of multisampling. */
177 config_set_d(CONFIG_MULTISAMPLE, samples / 2);
178 return video_mode(f, w, h);
181 /* If that mode failed, try it without reflections. */
185 config_set_d(CONFIG_REFLECTION, 0);
186 return video_mode(f, w, h);
189 /* If THAT mode failed, punt. */
194 /*---------------------------------------------------------------------------*/
199 static int ticks = 0;
200 static int frames = 0;
207 void video_swap(void)
211 SDL_GL_SwapBuffers();
213 /* Accumulate time passed and frames rendered. */
215 dt = (int) SDL_GetTicks() - last;
221 /* Average over 250ms. */
225 /* Round the frames-per-second value to the nearest integer. */
227 double k = 1000.0 * frames / ticks;
231 /* Compute frame time and frames-per-second stats. */
233 fps = (int) ((c - k < k - f) ? c : f);
234 ms = (float) ticks / (float) frames;
236 /* Reset the counters for the next update. */
241 /* Output statistics if configured. */
243 if (config_get_d(CONFIG_STATS))
244 fprintf(stdout, "%4d %8.4f\n", fps, ms);
248 /*---------------------------------------------------------------------------*/
250 static int grabbed = 0;
252 void video_set_grab(int w)
256 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
258 SDL_WarpMouse(config_get_d(CONFIG_WIDTH) / 2,
259 config_get_d(CONFIG_HEIGHT) / 2);
261 SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
264 SDL_WM_GrabInput(SDL_GRAB_ON);
265 SDL_ShowCursor(SDL_DISABLE);
270 void video_clr_grab(void)
272 SDL_WM_GrabInput(SDL_GRAB_OFF);
273 SDL_ShowCursor(SDL_ENABLE);
277 int video_get_grab(void)
282 /*---------------------------------------------------------------------------*/
284 void video_push_persp(float fov, float n, float f)
288 GLfloat r = fov / 2 * V_PI / 180;
290 GLfloat c = cos(r) / s;
292 GLfloat a = ((GLfloat) config_get_d(CONFIG_WIDTH) /
293 (GLfloat) config_get_d(CONFIG_HEIGHT));
295 glMatrixMode(GL_PROJECTION);
310 m[2][2] = -(f + n) / (f - n);
314 m[3][2] = -2.0f * n * f / (f - n);
317 glMultMatrixf(&m[0][0]);
319 glMatrixMode(GL_MODELVIEW);
322 void video_push_ortho(void)
324 GLfloat w = (GLfloat) config_get_d(CONFIG_WIDTH);
325 GLfloat h = (GLfloat) config_get_d(CONFIG_HEIGHT);
327 glMatrixMode(GL_PROJECTION);
331 glOrtho_(0.0, w, 0.0, h, -1.0, +1.0);
333 glMatrixMode(GL_MODELVIEW);
336 void video_pop_matrix(void)
338 glMatrixMode(GL_PROJECTION);
342 glMatrixMode(GL_MODELVIEW);
345 void video_clear(void)
347 if (config_get_d(CONFIG_REFLECTION))
348 glClear(GL_DEPTH_BUFFER_BIT |
349 GL_STENCIL_BUFFER_BIT);
351 glClear(GL_DEPTH_BUFFER_BIT);
354 /*---------------------------------------------------------------------------*/