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