]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/gropengl.cpp
clean up fullscreen code; fill/plug in gr_toggle_fullscreen
[taylor/freespace2.git] / src / graphics / gropengl.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "pstypes.h"
10 #include "osregistry.h"
11 #include "gropengl.h"
12 #include "gropengl1.h"
13 #include "gropenglinternal.h"
14 #include "2d.h"
15 #include "bmpman.h"
16 #include "grinternal.h"
17 #include "cmdline.h"
18 #include "mouse.h"
19 #include "osapi.h"
20
21
22 bool OGL_inited = false;
23 int GL_version = 0;
24
25 SDL_Window *GL_window = NULL;
26 SDL_GLContext GL_context;
27
28 static int FSAA = 0;
29
30 int GL_viewport_x = 0;
31 int GL_viewport_y = 0;
32 int GL_viewport_w = 640;
33 int GL_viewport_h = 480;
34 float GL_viewport_scale_w = 1.0f;
35 float GL_viewport_scale_h = 1.0f;
36 int GL_min_texture_width = 0;
37 int GL_max_texture_width = 0;
38 int GL_min_texture_height = 0;
39 int GL_max_texture_height = 0;
40
41 rb_t *render_buffer = NULL;
42 static size_t render_buffer_size = 0;
43
44
45 void opengl_alloc_render_buffer(unsigned int nelems)
46 {
47         if (nelems < 0) {
48                 nelems = 1;
49         }
50
51         if ( render_buffer && (nelems <= render_buffer_size) ) {
52                 return;
53         }
54
55         if (render_buffer) {
56                 free(render_buffer);
57         }
58
59         render_buffer = (rb_t*) malloc(sizeof(rb_t) * nelems);
60         render_buffer_size = nelems;
61 }
62
63 void opengl_free_render_buffer()
64 {
65         if (render_buffer) {
66                 free(render_buffer);
67                 render_buffer = NULL;
68                 render_buffer_size = 0;
69         }
70 }
71
72 static void opengl_set_variables()
73 {
74         GL_min_texture_height = 16;
75         GL_min_texture_width = 16;
76
77         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GL_max_texture_width);
78         GL_max_texture_height = GL_max_texture_width;
79
80         // no texture is larger than 1024, so maybe don't use sections
81         if (GL_max_texture_width >= 1024) {
82                 gr_screen.use_sections = 0;
83         }
84 }
85
86 void gr_opengl_set_viewport(int width, int height)
87 {
88         int w, h, x, y;
89
90         float ratio = gr_screen.max_w / i2fl(gr_screen.max_h);
91
92         w = width;
93         h = i2fl((width / ratio) + 0.5f);
94
95         if (h > height) {
96                 h = height;
97                 w = i2fl((height * ratio) + 0.5f);
98         }
99
100         x = (width - w) / 2;
101         y = (height - h) / 2;
102
103         GL_viewport_x = x;
104         GL_viewport_y = y;
105         GL_viewport_w = w;
106         GL_viewport_h = h;
107         GL_viewport_scale_w = w / i2fl(gr_screen.max_w);
108         GL_viewport_scale_h = h / i2fl(gr_screen.max_h);
109
110         glViewport(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h);
111
112         glMatrixMode(GL_PROJECTION);
113         glLoadIdentity();
114         glOrtho(0, GL_viewport_w, GL_viewport_h, 0, 0.0, 1.0);
115         glMatrixMode(GL_MODELVIEW);
116         glLoadIdentity();
117         glScalef(GL_viewport_scale_w, GL_viewport_scale_h, 1.0f);
118 }
119
120 void gr_opengl_force_windowed()
121 {
122         SDL_SetWindowFullscreen(GL_window, 0);
123 }
124
125 void gr_opengl_force_fullscreen()
126 {
127         SDL_SetWindowFullscreen(GL_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
128 }
129
130 void gr_opengl_toggle_fullscreen()
131 {
132         Uint32 flags = SDL_GetWindowFlags(GL_window);
133
134         if ( (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP ) {
135                 gr_opengl_force_windowed();
136         } else {
137                 gr_opengl_force_fullscreen();
138         }
139 }
140
141 void gr_opengl_set_color_fast(color *dst)
142 {
143         if ( dst->screen_sig != gr_screen.signature )   {
144                 if ( dst->is_alphacolor )       {
145                         gr_opengl_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
146                 } else {
147                         gr_opengl_init_color( dst, dst->red, dst->green, dst->blue );
148                 }
149         }
150         gr_screen.current_color = *dst;
151 }
152
153 void gr_opengl_get_color( int * r, int * g, int * b )
154 {
155         if (r) *r = gr_screen.current_color.red;
156         if (g) *g = gr_screen.current_color.green;
157         if (b) *b = gr_screen.current_color.blue;
158 }
159
160 void gr_opengl_init_color(color *c, int r, int g, int b)
161 {
162         c->screen_sig = gr_screen.signature;
163         c->red = (unsigned char)r;
164         c->green = (unsigned char)g;
165         c->blue = (unsigned char)b;
166         c->alpha = 255;
167         c->ac_type = AC_TYPE_NONE;
168         c->alphacolor = -1;
169         c->is_alphacolor = 0;
170         c->magic = 0xAC01;
171 }
172
173 void gr_opengl_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
174 {
175         if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
176         if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
177         if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
178         if ( alpha < 0 ) alpha = 0; else if ( alpha > 255 ) alpha = 255;
179
180         gr_opengl_init_color( clr, r, g, b );
181
182         clr->alpha = (unsigned char)alpha;
183         clr->ac_type = (ubyte)type;
184         clr->alphacolor = -1;
185         clr->is_alphacolor = 1;
186 }
187
188 void gr_opengl_set_color( int r, int g, int b )
189 {
190         SDL_assert((r >= 0) && (r < 256));
191         SDL_assert((g >= 0) && (g < 256));
192         SDL_assert((b >= 0) && (b < 256));
193
194         gr_opengl_init_color( &gr_screen.current_color, r, g, b );
195 }
196
197 void gr_opengl_set_clear_color(int r, int g, int b)
198 {
199         gr_opengl_init_color(&gr_screen.current_clear_color, r, g, b);
200 }
201
202 void gr_opengl_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy)
203 {
204         gr_screen.current_alpha = alpha;
205         gr_screen.current_alphablend_mode = alphablend_mode;
206         gr_screen.current_bitblt_mode = bitblt_mode;
207         gr_screen.current_bitmap = bitmap_num;
208
209         gr_screen.current_bitmap_sx = sx;
210         gr_screen.current_bitmap_sy = sy;
211 }
212
213 void gr_opengl_create_shader(shader * shade, float r, float g, float b, float c )
214 {
215         shade->screen_sig = gr_screen.signature;
216         shade->r = r;
217         shade->g = g;
218         shade->b = b;
219         shade->c = c;
220 }
221
222 void gr_opengl_set_shader( shader * shade )
223 {
224         if ( shade )    {
225                 if (shade->screen_sig != gr_screen.signature)   {
226                         gr_create_shader( shade, shade->r, shade->g, shade->b, shade->c );
227                 }
228                 gr_screen.current_shader = *shade;
229         } else {
230                 gr_create_shader( &gr_screen.current_shader, 0.0f, 0.0f, 0.0f, 0.0f );
231         }
232 }
233
234 int gr_opengl_zbuffer_get()
235 {
236         if ( !Gr_global_zbuffering ) {
237                 return GR_ZBUFF_NONE;
238         }
239
240         return Gr_zbuffering_mode;
241 }
242
243 int gr_opengl_zbuffer_set(int mode)
244 {
245         int tmp = Gr_zbuffering_mode;
246
247         Gr_zbuffering_mode = mode;
248
249         if (Gr_zbuffering_mode == GR_ZBUFF_NONE) {
250                 Gr_zbuffering = 0;
251         } else {
252                 Gr_zbuffering = 1;
253         }
254
255         return tmp;
256 }
257
258 void gr_opengl_cleanup()
259 {
260         opengl1_cleanup();
261
262         opengl_free_render_buffer();
263 }
264
265 void gr_opengl_init()
266 {
267         if ( OGL_inited )       {
268                 gr_opengl_cleanup();
269                 OGL_inited = false;
270         }
271
272         mprintf(( "Initializing OpenGL graphics device...\n" ));
273
274         OGL_inited = true;
275
276         if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
277                 Error(LOCATION, "Couldn't init SDL: %s", SDL_GetError());
278         }
279
280         int a = 1, r = 5, g = 5, b = 5, bpp = 16, db = 1;
281
282         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, r);
283         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, g);
284         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, b);
285         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, a);
286         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, bpp);
287         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, db);
288
289         FSAA = os_config_read_uint(NULL, "FSAA", 0);
290
291         if (FSAA) {
292             SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
293             SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, FSAA);
294         }
295
296         GL_window = SDL_CreateWindow(Osreg_title, SDL_WINDOWPOS_CENTERED,
297                                                 SDL_WINDOWPOS_CENTERED,
298                                                 gr_screen.max_w, gr_screen.max_h, SDL_WINDOW_OPENGL);
299
300         if ( !GL_window ) {
301                 Error(LOCATION, "Couldn't create window: %s\n", SDL_GetError());
302         }
303
304         GL_context = SDL_GL_CreateContext(GL_window);
305
306         const char *gl_version = (const char*)glGetString(GL_VERSION);
307         int v_major = 0, v_minor = 0;
308
309         sscanf(gl_version, "%d.%d", &v_major, &v_minor);
310
311         GL_version = (v_major * 10) + v_minor;
312
313         // version check, require 1.2+ for sake of simplicity
314         if (GL_version < 12) {
315                 Error(LOCATION, "Minimum OpenGL version is 1.2!");
316         }
317
318         mprintf(("  Vendor   : %s\n", glGetString(GL_VENDOR)));
319         mprintf(("  Renderer : %s\n", glGetString(GL_RENDERER)));
320         mprintf(("  Version  : %s\n", gl_version));
321
322         mprintf(("  Attributes requested: ARGB %d%d%d%d, BPP %d, DB %d, AA %d\n", a, r, g, b, bpp, db, FSAA));
323
324         SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
325         SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
326         SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
327         SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a);
328         SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &bpp);
329         SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &db);
330         SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &FSAA);
331
332         mprintf(("  Attributes received : ARGB %d%d%d%d, BPP %d, DB %d, AA %d\n", a, r, g, b, bpp, db, FSAA));
333
334
335         SDL_DisableScreenSaver();
336         SDL_ShowCursor(0);
337
338         // initial viewport setup
339         gr_opengl_set_viewport(gr_screen.max_w, gr_screen.max_h);
340
341         // set up generic variables before further init() calls
342         opengl_set_variables();
343
344         // main GL init
345         opengl1_init();
346
347         // maybe go fullscreen - should be done *after* main GL init
348         int fullscreen = os_config_read_uint(NULL, "Fullscreen", 1);
349         if ( !Cmdline_window && (fullscreen || Cmdline_fullscreen) ) {
350                 SDL_SetWindowFullscreen(GL_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
351                 // poll for window events
352                 os_poll();
353         }
354
355         mprintf(("\n"));
356
357
358         switch (bpp) {
359                 case 15:
360                 case 16:
361                         gr_screen.bits_per_pixel = 16;
362                         gr_screen.bytes_per_pixel = 2;
363
364                         // screen values
365                         Gr_red.bits = 5;
366                         Gr_red.shift = 10;
367                         Gr_red.scale = 8;
368                         Gr_red.mask = 0x7C00;
369
370                         Gr_green.bits = 5;
371                         Gr_green.shift = 5;
372                         Gr_green.scale = 8;
373                         Gr_green.mask = 0x3E0;
374
375                         Gr_blue.bits = 5;
376                         Gr_blue.shift = 0;
377                         Gr_blue.scale = 8;
378                         Gr_blue.mask = 0x1F;
379
380                         Gr_alpha.bits = 1;
381                         Gr_alpha.shift = 15;
382                         Gr_alpha.scale = 255;
383                         Gr_alpha.mask = 0x8000;
384
385                         break;
386
387                 case 24:
388                 case 32:
389                         gr_screen.bits_per_pixel = 32;
390                         gr_screen.bytes_per_pixel = 4;
391
392                         // screen values
393                         Gr_red.bits = 8;
394                         Gr_red.shift = 16;
395                         Gr_red.scale = 1;
396                         Gr_red.mask = 0xff0000;
397
398                         Gr_green.bits = 8;
399                         Gr_green.shift = 8;
400                         Gr_green.scale = 1;
401                         Gr_green.mask = 0xff00;
402
403                         Gr_blue.bits = 8;
404                         Gr_blue.shift = 0;
405                         Gr_blue.scale = 1;
406                         Gr_blue.mask = 0xff;
407
408                         Gr_alpha.bits = 8;
409                         Gr_alpha.shift = 24;
410                         Gr_alpha.scale = 1;
411                         Gr_alpha.mask = 0xff000000;
412
413                         break;
414
415                 default:
416                         Int3(); // Illegal bpp
417                         break;
418         }
419
420         // DDOI - set these so no one else does!
421         // texture values, always 1555 - 16-bit
422         Gr_t_red.mask = 0x7C00;
423         Gr_t_red.shift = 10;
424         Gr_t_red.scale = 8;
425
426         Gr_t_green.mask = 0x3E0;
427         Gr_t_green.shift = 5;
428         Gr_t_green.scale = 8;
429
430         Gr_t_blue.mask = 0x1F;
431         Gr_t_blue.shift = 0;
432         Gr_t_blue.scale = 8;
433
434         Gr_t_alpha.mask = 0x8000;
435         Gr_t_alpha.scale = 255;
436         Gr_t_alpha.shift = 15;
437
438         // alpha-texture values
439         Gr_ta_red.mask = 0x0f00;
440         Gr_ta_red.shift = 8;
441         Gr_ta_red.scale = 16;
442
443         Gr_ta_green.mask = 0x00f0;
444         Gr_ta_green.shift = 4;
445         Gr_ta_green.scale = 16;
446
447         Gr_ta_blue.mask = 0x000f;
448         Gr_ta_blue.shift = 0;
449         Gr_ta_blue.scale = 16;
450
451         Gr_ta_alpha.mask = 0xf000;
452         Gr_ta_alpha.shift = 12;
453         Gr_ta_alpha.scale = 16;
454
455         // default to screen
456         Gr_current_red = &Gr_red;
457         Gr_current_blue = &Gr_blue;
458         Gr_current_green = &Gr_green;
459         Gr_current_alpha = &Gr_alpha;
460
461         Mouse_hidden++;
462         gr_reset_clip();
463         gr_clear();
464         gr_flip();
465         Mouse_hidden--;
466 }