1 #include <stdlib.h>
2 #include <string.h>
3 #include <SDL.h>
4 #include "gl_init.h"
5 #include "asc.h"
6 #include "elconfig.h"
7 #include "errors.h"
8 #include "hud.h"
9 #include "init.h"
10 #include "interface.h"
11 #include "paste.h"
12 #include "textures.h"
13 #include "translate.h"
14 #include "sky.h"
15 #include "shader/shader.h"
16 #ifdef FSAA
17 #include "fsaa/fsaa.h"
18 #endif /* FSAA */
19
20 int window_width = 640;
21 int window_height = 480;
22 static float window_highdpi_scale_width = 1.0f;
23 static float window_highdpi_scale_height = 1.0f;
24
25 SDL_Window *el_gl_window = NULL;
26 static SDL_GLContext el_gl_context = NULL;
27 static SDL_Surface *icon_bmp = NULL;
28 static SDL_version el_gl_linked;
29 static int log_next_window_resize = 0;
30
31 int bpp = 0;
32 int have_stencil = 1;
33 int video_mode = 0;
34 int video_user_width = 640;
35 int video_user_height = 480;
36 int full_screen = 0;
37
38 int use_compiled_vertex_array = 0;
39 int use_vertex_buffers = 0;
40 int use_frame_buffer = 0;
41 int use_mipmaps = 0;
42 int use_draw_range_elements = 1;
43 float anisotropic_filter = 1.0f;
44 int disable_gamma_adjust = 0;
45 float gamma_var = 1.00f;
46 float perspective = 0.15f;
47 float near_plane = 0.1f; // don't cut off anything
48 float far_plane = 100.0; // LOD helper. Cull distant objects. Lower value == higher framerates.
49 float far_reflection_plane = 100.0; // LOD helper. Cull distant reflected objects. Lower value == higher framerates.
50 int gl_extensions_loaded = 0;
51
get_window_size(int mode,int * width,int * height)52 static void get_window_size(int mode, int *width, int *height)
53 {
54 /* Video mode 0 is user defined size (via video_user_width and video_user_height)
55 * Video mode 1 and above are defined in the video_modes array where mode 1 is at position 0
56 * Therefore we heve to adjust the index by one
57 */
58 int index = mode - 1;
59
60 /* Safe fallback
61 * If the user select an invalid mode (like a wrong number in the config file) fallback
62 * to safe 640x480 mode
63 */
64 if (index < 0 || index >= video_modes_count)
65 index = 0;
66
67 *width = (mode == 0) ?video_user_width :video_modes[index].width;
68 *height = (mode == 0) ?video_user_height :video_modes[index].height;
69 }
70
load_window_icon(void)71 static void load_window_icon(void)
72 {
73 char *icon_name = "icon.bmp";
74 size_t str_len = strlen(datadir) + strlen(icon_name) + 1;
75 char *str_buf = malloc(str_len);
76 safe_strncpy(str_buf, datadir, str_len);
77 safe_strcat(str_buf, icon_name, str_len);
78 icon_bmp = SDL_LoadBMP(str_buf);
79 if (icon_bmp == NULL)
80 LOG_ERROR("Failed to load window icon: %s\n",str_buf);
81 else
82 SDL_SetWindowIcon(el_gl_window, icon_bmp);
83 free(str_buf);
84 }
85
init_video(void)86 void init_video(void)
87 {
88 int target_width = 0, target_height = 0;
89 int rgb_size[3];
90 Uint32 flags;
91
92 if (!full_screen)
93 get_window_size(video_mode, &target_width, &target_height);
94
95 if (SDL_Init(SDL_INIT_VIDEO) < 0)
96 {
97 LOG_ERROR("%s: %s\n", no_sdl_str, SDL_GetError());
98 fprintf(stderr, "%s: %s\n", no_sdl_str, SDL_GetError());
99 SDL_Quit();
100 FATAL_ERROR_WINDOW("Failed to initialise SDL, going to exit.");
101 exit(1);
102 }
103
104 SDL_GetVersion(&el_gl_linked);
105
106 /* Detect the display depth */
107 if (!bpp)
108 {
109 SDL_DisplayMode current;
110 SDL_GetCurrentDisplayMode(0, ¤t);
111 if ( SDL_BITSPERPIXEL(current.format) <= 8 )
112 bpp = 8;
113 else if ( SDL_BITSPERPIXEL(current.format) <= 16 )
114 bpp = 16;
115 else
116 bpp = 32;
117 }
118
119 // adjust the video mode depending on the BITSPERPIXEL available
120 if (video_mode == 0)
121 {
122 // do nothing user defined
123 }
124 else if (bpp == 16)
125 {
126 if (!(video_mode%2))
127 video_mode -= 1;
128 }
129 else
130 {
131 if (video_mode%2)
132 video_mode += 1;
133 }
134
135 /* Initialize the display */
136 switch (bpp) {
137 case 8:
138 rgb_size[0] = 2;
139 rgb_size[1] = 3;
140 rgb_size[2] = 3;
141 break;
142 case 15:
143 case 16:
144 rgb_size[0] = 5;
145 rgb_size[1] = 5;
146 rgb_size[2] = 5;
147 break;
148 default:
149 rgb_size[0] = 8;
150 rgb_size[1] = 8;
151 rgb_size[2] = 8;
152 break;
153 }
154
155 // Mac OS X will always use 8-8-8-8 ARGB for 32-bit screens and 5-5-5 RGB for 16-bit screens
156 #ifndef OSX
157 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] );
158 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] );
159 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] );
160 #endif
161
162 SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 0 );
163 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
164 SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8);
165 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
166
167 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI;
168 if(full_screen)
169 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
170
171 #ifdef FSAA
172 if (fsaa > 1)
173 {
174 char str[400];
175 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
176 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fsaa);
177 glDisable(GL_MULTISAMPLE);
178
179 el_gl_window = SDL_CreateWindow("Eternal Lands", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, target_width, target_height, flags);
180 if (el_gl_window == NULL)
181 {
182 safe_snprintf(str, sizeof(str), "Can't use fsaa mode x%d, disabling it.", fsaa);
183 LOG_TO_CONSOLE(c_yellow1, str);
184 LOG_WARNING("%s\n", str);
185 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
186 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
187 fsaa = 0;
188 }
189 }
190 #endif /* FSAA */
191
192 //try to find a stencil buffer
193 if (el_gl_window == NULL)
194 {
195 el_gl_window = SDL_CreateWindow("Eternal Lands", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, target_width, target_height, flags);
196 if (el_gl_window == NULL)
197 {
198 LOG_TO_CONSOLE(c_red1,no_hardware_stencil_str);
199 LOG_ERROR("%s\n",no_hardware_stencil_str);
200 if(bpp!=32)
201 {
202 LOG_TO_CONSOLE(c_grey1,suggest_24_or_32_bit);
203 LOG_ERROR("%s\n",suggest_24_or_32_bit);
204 }
205 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16);
206 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,0);
207 el_gl_window = SDL_CreateWindow("Eternal Lands", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, target_width, target_height, flags);
208 if (el_gl_window == NULL)
209 {
210 LOG_ERROR("%s: %s\n", fail_opengl_mode, SDL_GetError());
211 SDL_Quit();
212 FATAL_ERROR_WINDOW("Failed to create game window, going to exit.");
213 exit(1);
214 }
215 have_stencil=0;
216 }
217 }
218
219 el_gl_context = SDL_GL_CreateContext(el_gl_window);
220 if (el_gl_context == NULL)
221 {
222 LOG_ERROR("%s: %s\n", "SDL_GL_CreateContext() Failed", SDL_GetError());
223 SDL_Quit();
224 FATAL_ERROR_WINDOW("Failed to create game GL context, going to exit.");
225 exit(1);
226 }
227
228 // check we have a working GL context, we will only fail later if we do not.
229 {
230 const GLubyte* test_string = glGetString(GL_VENDOR);
231 if (test_string == NULL)
232 {
233 const char* error_str = "glGetString(GL_VENDOR) failed, going to exit.";
234 DO_CHECK_GL_ERRORS();
235 LOG_ERROR("%s: %s\n", error_str, SDL_GetError());
236 SDL_Quit();
237 FATAL_ERROR_WINDOW(error_str);
238 exit(1);
239 }
240 }
241
242 // set the minimum size for the window, this is too small perhaps but a config option
243 SDL_SetWindowMinimumSize(el_gl_window, 640, 480);
244
245 // read events for a few milliseconds, this will catch window size changes made by the window manger
246 {
247 SDL_Event event;
248 Uint32 start_wait = SDL_GetTicks();
249 while((SDL_GetTicks() < (start_wait + 100)))
250 {
251 SDL_PollEvent(&event);
252 SDL_Delay(1);
253 }
254 }
255
256 // get the windos size, these variables are used globaly
257 update_window_size_and_scale();
258 // even though no windows have been created, their starting position need to be adjusted
259 if (!full_screen)
260 move_windows_proportionally((float)window_width / (float)target_width, (float)window_height / (float)target_height);
261
262 // enable V-SYNC, choosing active as a preference
263 if (SDL_GL_SetSwapInterval(-1) < 0)
264 SDL_GL_SetSwapInterval(1);
265
266 // set the hint that clicks that focus the window, pass through for action too
267 #if SDL_VERSION_ATLEAST(2, 0, 5)
268 if (SDL_VERSIONNUM(el_gl_linked.major, el_gl_linked.minor, el_gl_linked.patch) >= 2005)
269 SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
270 #endif
271
272 // set the gamma of we are controlling it
273 if (!disable_gamma_adjust)
274 SDL_SetWindowBrightness(el_gl_window, gamma_var);
275
276 // set the initial window title, though it will change once we are logged in
277 SDL_SetWindowTitle( el_gl_window, win_principal );
278
279 glEnable(GL_DEPTH_TEST);
280 glDepthFunc(GL_LESS);
281 //glDepthFunc(GL_LEQUAL);
282 glEnable(GL_TEXTURE_2D);
283 glShadeModel(GL_SMOOTH);
284 glFrontFace(GL_CCW);
285 glCullFace(GL_BACK);
286 glEnable(GL_NORMALIZE);
287 glClearStencil(0);
288
289 #ifdef ANTI_ALIAS
290 if (anti_alias) {
291 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
292 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
293 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
294 glEnable(GL_POINT_SMOOTH);
295 glEnable(GL_LINE_SMOOTH);
296 glEnable(GL_POLYGON_SMOOTH);
297 } else {
298 glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
299 glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
300 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
301 glDisable(GL_POINT_SMOOTH);
302 glDisable(GL_LINE_SMOOTH);
303 glDisable(GL_POLYGON_SMOOTH);
304 }
305 #endif
306
307 last_texture = -1; //no active texture
308 video_mode_set = 1; //now you may set the video mode using the %<foo> in-game
309
310 #if !defined OSX && !defined WINDOWS
311 init_x11_copy_paste();
312 #endif
313
314 load_window_icon();
315
316 check_options();
317
318 DO_CHECK_GL_ERRORS();
319 }
320
321 #ifdef GL_EXTENSION_CHECK
evaluate_extension(void)322 static void evaluate_extension(void)
323 {
324 char str[1024];
325 int has_arb_texture_env_add;
326 int has_arb_texture_env_crossbar;
327 int has_arb_texture_rectangle;
328 int has_arb_fragment_shader_shadow;
329 int has_ati_fragment_shader;
330 int has_ati_texture_env_combine3;
331 int has_nv_texture_env_combine4;
332 int has_nv_texture_shader;
333 int has_nv_texture_shader2;
334 int options;
335 char* extensions;
336
337 extensions = (char*)glGetString(GL_EXTENSIONS);
338
339 has_arb_texture_env_add = strstr(extensions, "GL_ARB_texture_env_add") > 0;
340 has_arb_texture_env_crossbar = strstr(extensions, "GL_ARB_texture_env_crossbar") > 0;
341 has_arb_texture_rectangle = strstr(extensions, "GL_ARB_texture_rectangle") > 0;
342 has_arb_fragment_shader_shadow = strstr(extensions, "GL_ARB_fragment_program_shadow") > 0;
343 has_ati_fragment_shader = strstr(extensions, "GL_ATI_fragment_shader") > 0;
344 has_ati_texture_env_combine3 = strstr(extensions, "GL_ATI_texture_env_combine3") > 0;
345 has_nv_texture_env_combine4 = strstr(extensions, "GL_NV_texture_env_combine4") > 0;
346 has_nv_texture_shader = strstr(extensions, "GL_NV_texture_shader") > 0;
347 has_nv_texture_shader2 = strstr(extensions, "GL_NV_texture_shader2") > 0;
348
349 options = (get_texture_units() >= 2) && has_arb_texture_env_add &&
350 have_extension(arb_texture_env_combine) && have_extension(arb_vertex_program) &&
351 have_extension(arb_texture_compression) && have_extension(arb_vertex_buffer_object) &&
352 have_extension(ext_texture_compression_s3tc);
353
354 if (!options)
355 {
356 safe_snprintf(str,sizeof(str),"%s%s%s","Your graphic card/driver don't support the minimum",
357 " requirements for the next EL release. Please upgrade your driver.",
358 " If this don't help, you need a better graphic card.");
359 LOG_TO_CONSOLE(c_red1, str);
360 LOG_ERROR("%s\n",str);
361 return;
362 }
363
364 if (!have_extension(arb_vertex_shader) || (have_extension(arb_fragment_program) &&
365 !have_extension(arb_fragment_shader)) || (has_ati_fragment_shader &&
366 !have_extension(arb_fragment_program) && !have_extension(arb_fragment_shader)))
367 {
368 safe_snprintf(str,sizeof(str),"Please update your graphic card driver!");
369 LOG_TO_CONSOLE(c_yellow1, str);
370 LOG_WARNING("%s\n",str);
371 }
372
373 options = ((has_ati_texture_env_combine3 && has_arb_texture_env_crossbar) ||
374 has_nv_texture_env_combine4) && (get_texture_units() >= 4) &&
375 have_extension(ext_draw_range_elements) && have_extension(arb_shadow) &&
376 have_extension(arb_point_parameters) && have_extension(arb_point_sprite);
377
378 if (!options)
379 {
380 safe_snprintf(str,sizeof(str),"%s%s%s","Your graphic card supports the absolute minimum",
381 " requirements for the next EL release, but don't expect that you can use",
382 " all features.");
383 LOG_TO_CONSOLE(c_yellow1, str);
384 LOG_DEBUG("%s\n",str);
385
386 }
387 else
388 {
389 options = (has_ati_fragment_shader || (has_nv_texture_shader &&
390 has_nv_texture_shader2)) && have_extension(arb_occlusion_query) &&
391 has_arb_texture_rectangle && have_extension(ext_framebuffer_object);
392 if (!options)
393 {
394 safe_snprintf(str,sizeof(str),"%s%s","Your graphic card supports the default ",
395 "requirements for the next EL release.");
396 LOG_TO_CONSOLE(c_green2, str);
397 LOG_DEBUG("%s\n",str);
398 }
399 else
400 {
401 if (have_extension(arb_fragment_shader) &&
402 have_extension(arb_shader_objects) &&
403 have_extension(arb_vertex_shader) &&
404 have_extension(arb_shading_language_100))
405 {
406 safe_snprintf(str,sizeof(str),"%s%s","Your graphic card supports all ",
407 "features EL will use in the future.");
408 LOG_TO_CONSOLE(c_blue2, str);
409 LOG_DEBUG("%s\n",str);
410 }
411 else
412 {
413 safe_snprintf(str,sizeof(str),"%s%s","Your graphic card supports more than the",
414 " default requirements for the next EL release.");
415 LOG_TO_CONSOLE(c_blue2, str);
416 LOG_DEBUG("%s\n",str);
417 }
418 }
419 }
420 }
421 #endif //GL_EXTENSION_CHECK
422
init_gl_extensions(void)423 void init_gl_extensions(void)
424 {
425 char str[1024];
426
427 init_opengl_extensions();
428
429 /* GL_ARB_multitexture */
430 if (have_extension(arb_multitexture))
431 {
432 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_multitexture");
433 LOG_TO_CONSOLE(c_green2, str);
434 LOG_DEBUG("%s\n",str);
435 }
436 else
437 {
438 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_multitexture");
439 LOG_TO_CONSOLE(c_red1, str);
440 LOG_DEBUG("%s\n",str);
441 }
442 /* GL_ARB_multitexture */
443
444 /* GL_ARB_texture_env_combine */
445 if (have_extension(arb_texture_env_combine))
446 {
447 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_texture_env_combine");
448 LOG_TO_CONSOLE(c_green2, str);
449 LOG_DEBUG("%s\n",str);
450 }
451 else
452 {
453 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_texture_env_combine");
454 LOG_TO_CONSOLE(c_red1, str);
455 LOG_DEBUG("%s\n",str);
456 }
457 /* GL_ARB_texture_env_combine */
458
459 /* GL_EXT_compiled_vertex_array */
460 if (have_extension(ext_compiled_vertex_array))
461 {
462 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_compiled_vertex_array");
463 LOG_TO_CONSOLE(c_green2, str);
464 LOG_DEBUG("%s\n",str);
465 }
466 else
467 {
468 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_compiled_vertex_array");
469 LOG_TO_CONSOLE(c_red1, str);
470 LOG_DEBUG("%s\n",str);
471 }
472 /* GL_EXT_compiled_vertex_array */
473
474 /* GL_ARB_point_sprite */
475 if (have_extension(arb_point_sprite))
476 {
477 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_point_sprite");
478 LOG_TO_CONSOLE(c_green2, str);
479 LOG_DEBUG("%s\n",str);
480 }
481 else
482 {
483 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_point_sprite");
484 LOG_TO_CONSOLE(c_red1, str);
485 LOG_DEBUG("%s\n",str);
486 }
487 /* GL_ARB_point_sprite */
488
489 /* GL_ARB_texture_compression */
490 if (have_extension(arb_texture_compression))
491 {
492 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_texture_compression");
493 LOG_TO_CONSOLE(c_green2, str);
494 LOG_DEBUG("%s\n",str);
495 }
496 else
497 {
498 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_texture_compression");
499 LOG_TO_CONSOLE(c_red1, str);
500 LOG_DEBUG("%s\n",str);
501 }
502 /* GL_ARB_texture_compression */
503
504 /* GL_EXT_texture_compression_s3tc */
505 if (have_extension(ext_texture_compression_s3tc))
506 {
507 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_texture_compression_s3tc");
508 LOG_TO_CONSOLE(c_green2, str);
509 LOG_DEBUG("%s\n",str);
510 }
511 else
512 {
513 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_texture_compression_s3tc");
514 LOG_TO_CONSOLE(c_red1, str);
515 LOG_DEBUG("%s\n",str);
516 }
517 /* GL_EXT_texture_compression_s3tc */
518
519 /* GL_SGIS_generate_mipmap */
520 if (have_extension(sgis_generate_mipmap))
521 {
522 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_SGIS_generate_mipmap");
523 LOG_TO_CONSOLE(c_green2, str);
524 LOG_DEBUG("%s\n",str);
525 }
526 else
527 {
528 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_SGIS_generate_mipmap");
529 LOG_TO_CONSOLE(c_red1, str);
530 LOG_DEBUG("%s\n",str);
531 }
532 /* GL_SGIS_generate_mipmap */
533
534 /* GL_ARB_shadow */
535 if (have_extension(arb_shadow))
536 {
537 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_shadow");
538 LOG_TO_CONSOLE(c_green2, str);
539 LOG_DEBUG("%s\n",str);
540 }
541 else
542 {
543 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_shadow");
544 LOG_TO_CONSOLE(c_red1, str);
545 LOG_DEBUG("%s\n",str);
546 }
547 /* GL_ARB_shadow */
548
549 /* GL_ARB_vertex_buffer_object */
550 if (have_extension(arb_vertex_buffer_object))
551 {
552 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_vertex_buffer_object");
553 LOG_TO_CONSOLE(c_green2, str);
554 LOG_DEBUG("%s\n",str);
555 }
556 else
557 {
558 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_vertex_buffer_object");
559 LOG_TO_CONSOLE(c_red1, str);
560 LOG_DEBUG("%s\n",str);
561 }
562 /* GL_ARB_vertex_buffer_object */
563
564 /* GL_EXT_framebuffer_object */
565 if (have_extension(ext_framebuffer_object))
566 {
567 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_framebuffer_object");
568 LOG_TO_CONSOLE(c_green2, str);
569 LOG_DEBUG("%s\n",str);
570 }
571 else
572 {
573 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_framebuffer_object");
574 LOG_TO_CONSOLE(c_red1, str);
575 LOG_DEBUG("%s\n",str);
576 }
577 /* GL_EXT_framebuffer_object */
578
579 /* GL_EXT_draw_range_elements */
580 if (have_extension(ext_draw_range_elements))
581 {
582 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_draw_range_elements");
583 LOG_TO_CONSOLE(c_green2, str);
584 LOG_DEBUG("%s\n",str);
585 }
586 else
587 {
588 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_draw_range_elements");
589 LOG_TO_CONSOLE(c_red1, str);
590 LOG_DEBUG("%s\n",str);
591 }
592 /* GL_EXT_draw_range_elements */
593
594 /* GL_ARB_texture_non_power_of_two */
595 if (have_extension(arb_texture_non_power_of_two))
596 {
597 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_texture_non_power_of_two");
598 LOG_TO_CONSOLE(c_green2, str);
599 LOG_DEBUG("%s\n",str);
600 }
601 else
602 {
603 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_texture_non_power_of_two");
604 LOG_TO_CONSOLE(c_red1, str);
605 LOG_DEBUG("%s\n",str);
606 }
607 /* GL_ARB_texture_non_power_of_two */
608
609 /* GL_ARB_fragment_program */
610 if (have_extension(arb_fragment_program))
611 {
612 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_fragment_program");
613 LOG_TO_CONSOLE(c_green2, str);
614 LOG_DEBUG("%s\n",str);
615 }
616 else
617 {
618 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_fragment_program");
619 LOG_TO_CONSOLE(c_red1, str);
620 LOG_DEBUG("%s\n",str);
621 }
622 /* GL_ARB_fragment_program */
623
624 /* GL_ARB_vertex_program */
625 if (have_extension(arb_vertex_program))
626 {
627 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_vertex_program");
628 LOG_TO_CONSOLE(c_green2, str);
629 LOG_DEBUG("%s\n",str);
630 }
631 else
632 {
633 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_vertex_program");
634 LOG_TO_CONSOLE(c_red1, str);
635 LOG_DEBUG("%s\n",str);
636 }
637 /* GL_ARB_vertex_program */
638
639 /* GL_ARB_fragment_shader */
640 if (have_extension(arb_fragment_shader))
641 {
642 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_fragment_shader");
643 LOG_TO_CONSOLE(c_green2, str);
644 LOG_DEBUG("%s\n",str);
645 }
646 else
647 {
648 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_fragment_shader");
649 LOG_TO_CONSOLE(c_red1, str);
650 LOG_DEBUG("%s\n",str);
651 }
652 /* GL_ARB_fragment_shader */
653
654 /* GL_ARB_vertex_shader */
655 if (have_extension(arb_vertex_shader))
656 {
657 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_vertex_shader");
658 LOG_TO_CONSOLE(c_green2, str);
659 LOG_DEBUG("%s\n",str);
660 }
661 else
662 {
663 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_vertex_shader");
664 LOG_TO_CONSOLE(c_red1, str);
665 LOG_DEBUG("%s\n",str);
666 }
667 /* GL_ARB_vertex_shader */
668
669 /* GL_ARB_shader_objects */
670 if (have_extension(arb_shader_objects))
671 {
672 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_shader_objects");
673 LOG_TO_CONSOLE(c_green2, str);
674 LOG_DEBUG("%s\n",str);
675 }
676 else
677 {
678 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_shader_objects");
679 LOG_TO_CONSOLE(c_red1, str);
680 LOG_DEBUG("%s\n",str);
681 }
682 /* GL_ARB_shader_objects */
683
684 /* GL_ARB_shading_language_100 */
685 if (have_extension(arb_shading_language_100))
686 {
687 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ARB_shading_language_100");
688 LOG_TO_CONSOLE(c_green2, str);
689 LOG_DEBUG("%s\n",str);
690 }
691 else
692 {
693 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_shading_language_100");
694 LOG_TO_CONSOLE(c_red1, str);
695 LOG_DEBUG("%s\n",str);
696 }
697 /* GL_ARB_shading_language_100 */
698
699 /* GL_ARB_texture_mirrored_repeat */
700 if (have_extension(arb_texture_mirrored_repeat))
701 {
702 safe_snprintf(str, sizeof(str), gl_ext_found_not_used, "GL_ARB_texture_mirrored_repeat");
703 LOG_TO_CONSOLE(c_green2, str);
704 LOG_DEBUG("%s\n",str);
705 }
706 else
707 {
708 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_texture_mirrored_repeat");
709 LOG_TO_CONSOLE(c_red1, str);
710 LOG_DEBUG("%s\n",str);
711 }
712 /* GL_ARB_texture_mirrored_repeat */
713
714 /* GL_ARB_texture_rectangle */
715 if (have_extension(arb_texture_rectangle))
716 {
717 safe_snprintf(str, sizeof(str), gl_ext_found_not_used, "GL_ARB_texture_rectangle");
718 LOG_TO_CONSOLE(c_green2, str);
719 LOG_DEBUG("%s\n",str);
720 }
721 else
722 {
723 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ARB_texture_rectangle");
724 LOG_TO_CONSOLE(c_red1, str);
725 LOG_DEBUG("%s\n",str);
726 }
727 /* GL_ARB_texture_rectangle */
728
729 /* GL_EXT_fog_coord */
730 if (have_extension(ext_fog_coord))
731 {
732 safe_snprintf(str, sizeof(str), gl_ext_found_not_used, "GL_EXT_fog_coord");
733 LOG_TO_CONSOLE(c_green2, str);
734 LOG_DEBUG("%s\n",str);
735 }
736 else
737 {
738 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_fog_coord");
739 LOG_TO_CONSOLE(c_red1, str);
740 LOG_DEBUG("%s\n",str);
741 }
742 /* GL_EXT_fog_coord */
743
744 /* GL_ATI_texture_compression_3dc */
745 if (have_extension(ati_texture_compression_3dc))
746 {
747 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_ATI_texture_compression_3dc");
748 LOG_TO_CONSOLE(c_green2, str);
749 LOG_DEBUG("%s\n",str);
750 }
751 else
752 {
753 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_ATI_texture_compression_3dc");
754 LOG_TO_CONSOLE(c_red1, str);
755 LOG_DEBUG("%s\n",str);
756 }
757 /* GL_ATI_texture_compression_3dc */
758
759 /* GL_EXT_texture_compression_latc */
760 if (have_extension(ext_texture_compression_latc))
761 {
762 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_texture_compression_latc");
763 LOG_TO_CONSOLE(c_green2, str);
764 LOG_DEBUG("%s\n",str);
765 }
766 else
767 {
768 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_texture_compression_latc");
769 LOG_TO_CONSOLE(c_red1, str);
770 LOG_DEBUG("%s\n",str);
771 }
772 /* GL_EXT_texture_compression_latc */
773
774 /* GL_EXT_texture_filter_anisotropic */
775 if (have_extension(ext_texture_filter_anisotropic))
776 {
777 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic_filter);
778 safe_snprintf(str, sizeof(str), gl_ext_found, "GL_EXT_texture_filter_anisotropic");
779 LOG_TO_CONSOLE(c_green2, str);
780 LOG_DEBUG("%s\n",str);
781 }
782 else
783 {
784 anisotropic_filter = 1.0f;
785 safe_snprintf(str, sizeof(str), gl_ext_not_found, "GL_EXT_texture_filter_anisotropic");
786 LOG_TO_CONSOLE(c_red1, str);
787 LOG_DEBUG("%s\n",str);
788 }
789 /* GL_EXT_texture_filter_anisotropic */
790
791 #if 0
792 // Disabled because of bad drivers
793 if (have_extension(ext_framebuffer_object))
794 {
795 check_fbo_formats();
796 }
797 #endif
798 init_shaders();
799
800 #ifdef GL_EXTENSION_CHECK
801 evaluate_extension();
802 #endif //GL_EXTENSION_CHECK
803
804 gl_extensions_loaded = 1;
805
806 CHECK_GL_ERRORS();
807 }
808
resize_root_window(void)809 void resize_root_window(void)
810 {
811 float window_ratio;
812 //float hud_x_adjust=0;
813 //float hud_y_adjust=0;
814
815 if (window_height==0)window_height=1; // Prevent A Divide By Zero
816
817 //glViewport(0, hud_y, window_width-hud_x, window_height); // Reset The Current Viewport
818 //glViewport(0, 0, window_width-hud_x, -(window_height-hud_y)); // Reset The Current Viewport
819
820 glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
821 glLoadIdentity(); // Reset The Projection Matrix
822
823 window_ratio=(GLfloat)(window_width-hud_x)/(GLfloat)(window_height-hud_y);
824
825 //hud_y_adjust=(2.0/window_height)*hud_y;
826 //hud_x_adjust=(2.0/window_width)*hud_x;
827 //Setup matrix for the sky. If we don't do this the sky looks unhinged when perspective changes.
828 glLoadIdentity();
829 glFrustum(-perspective*window_ratio*near_plane,
830 perspective*window_ratio*near_plane,
831 -perspective*near_plane,
832 perspective*near_plane,
833 near_plane, 1000.0);
834 glGetDoublev(GL_PROJECTION_MATRIX, skybox_view);
835 glLoadIdentity(); // Reset The Projection Matrix
836
837 //new zoom
838 if (isometric)
839 {
840 glOrtho( -1.0*zoom_level*window_ratio, 1.0*zoom_level*window_ratio, -1.0*zoom_level, 1.0*zoom_level, -near_plane*zoom_level, 60.0 );
841 }
842 else
843 {
844 glFrustum(-perspective*window_ratio*near_plane,
845 perspective*window_ratio*near_plane,
846 -perspective*near_plane,
847 perspective*near_plane,
848 near_plane, far_plane);
849 if (!first_person)
850 {
851 glTranslatef(0.0, 0.0, zoom_level*camera_distance);
852 glTranslatef(0.0, 0.0, -zoom_level/perspective);
853 }
854 }
855
856 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
857 glLoadIdentity(); // Reset The Modelview Matrix
858 last_texture=-1; //no active texture
859 }
860
switch_video(int mode,int full_screen)861 int switch_video(int mode, int full_screen)
862 {
863 video_mode = mode;
864 if (full_screen)
865 SDL_SetWindowFullscreen(el_gl_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
866 else
867 {
868 int target_width, target_height;
869 get_window_size(mode, &target_width, &target_height);
870 set_client_window_size(target_width, target_height);
871 }
872 return 1;
873 }
874
875 // Set the window size as specified without changing the window mode.
set_client_window_size(int width,int height)876 void set_client_window_size(int width, int height)
877 {
878 // limit the window size to the actual available space
879 #if SDL_VERSION_ATLEAST(2, 0, 5)
880 {
881 SDL_Rect rect;
882 int display_index = SDL_GetWindowDisplayIndex(el_gl_window);
883 int top, left, bottom, right;
884 SDL_GetWindowBordersSize(el_gl_window, &top, &left, &bottom, &right);
885 SDL_GetDisplayUsableBounds(display_index, &rect);
886 width = (width > (rect.w - left - right)) ?rect.w - left - right :width;
887 height = (height > (rect.h - top - bottom)) ?rect.h - top - bottom :height;
888 }
889 #endif
890
891 log_next_window_resize = 1;
892 SDL_RestoreWindow(el_gl_window);
893 SDL_SetWindowFullscreen(el_gl_window, 0);
894 SDL_SetWindowSize(el_gl_window, width, height);
895 }
896
897 // Get a single value for highhdpi scaling.
get_highdpi_scale(void)898 float get_highdpi_scale(void)
899 {
900 return (window_highdpi_scale_width > window_highdpi_scale_height) ?window_highdpi_scale_width :window_highdpi_scale_height;
901 }
902
903 // Use the calulated values to scale mouse values.
highdpi_scale(int * width,int * height)904 void highdpi_scale(int *width, int *height)
905 {
906 *width = (int)((0.5 - (*width < 0)) + (float)*width * window_highdpi_scale_width);
907 *height = (int)((0.5 - (*height < 0)) + (float)*height * window_highdpi_scale_height);
908 }
909
910 // For high DPI displays, SDL_GetWindowSize() reports different values to SDL_GL_GetDrawableSize()
911 // You need the SDL_GL_GetDrawableSize() to enable use of the full window.
912 // You need to ration of SDL_GL_GetDrawableSize()/SDL_GetWindowSize() to scale the mouse location.
update_window_size_and_scale(void)913 void update_window_size_and_scale(void)
914 {
915 float old_width = window_highdpi_scale_width, old_height = window_highdpi_scale_height;
916 int non_dpi_w, non_dpi_h;
917 SDL_GetWindowSize(el_gl_window, &non_dpi_w, &non_dpi_h);
918 SDL_GL_GetDrawableSize(el_gl_window, &window_width, &window_height);
919 window_highdpi_scale_width = (float)window_width / (float)non_dpi_w;
920 window_highdpi_scale_height = (float)window_height / (float)non_dpi_h;
921 if ((old_width != window_highdpi_scale_width) || (old_height != window_highdpi_scale_height))
922 update_highdpi_auto_scaling();
923 if (log_next_window_resize)
924 {
925 char modestr[100];
926 char str[100];
927 safe_snprintf(modestr, sizeof(modestr), "%dx%d", window_width, window_height);
928 safe_snprintf(str, sizeof(str), window_size_adjusted_str, modestr);
929 LOG_TO_CONSOLE(c_yellow1, str);
930 LOG_DEBUG("%s",str);
931 log_next_window_resize = 0;
932 }
933 }
934
toggle_full_screen(void)935 void toggle_full_screen(void)
936 {
937 full_screen=!full_screen;
938 switch_video(video_mode, full_screen);
939 }
940
print_gl_errors(const char * file,int line)941 int print_gl_errors(const char *file, int line)
942 {
943 GLenum glErr, anyErr=GL_NO_ERROR;
944
945 while ((glErr=glGetError()) != GL_NO_ERROR )
946 {
947 anyErr=glErr;
948 log_error(file, line, "OpenGL %s", gluErrorString(glErr));
949 }
950 return anyErr;
951 }
952
gl_window_cleanup(void)953 void gl_window_cleanup(void)
954 {
955 if (el_gl_window != NULL)
956 {
957 SDL_DestroyWindow(el_gl_window);
958 el_gl_window = NULL;
959 }
960 if (icon_bmp != NULL)
961 {
962 SDL_FreeSurface(icon_bmp);
963 icon_bmp = NULL;
964 }
965 }
966