1
2
3
4
5
6 #include "globalincs/pstypes.h"
7 #include "cmdline/cmdline.h"
8 #include "osapi/osapi.h"
9 #include "graphics/2d.h"
10 #include "render/3d.h"
11 #include "bmpman/bmpman.h"
12 #include "math/floating.h"
13 #include "palman/palman.h"
14 #include "globalincs/systemvars.h"
15 #include "graphics/grinternal.h"
16 #include "graphics/gropengl.h"
17 #include "graphics/line.h"
18 #include "nebula/neb.h"
19 #include "io/mouse.h"
20 #include "osapi/osregistry.h"
21 #include "cfile/cfile.h"
22 #include "io/timer.h"
23 #include "ddsutils/ddsutils.h"
24 #include "model/model.h"
25 #include "debugconsole/timerbar.h"
26 #include "graphics/gropenglbmpman.h"
27 #include "graphics/gropengllight.h"
28 #include "graphics/gropengltexture.h"
29 #include "graphics/gropenglextension.h"
30 #include "graphics/gropengltnl.h"
31 #include "graphics/gropenglbmpman.h"
32 #include "graphics/gropengldraw.h"
33 #include "graphics/gropenglshader.h"
34 #include "graphics/gropenglstate.h"
35 #include "graphics/gropenglpostprocessing.h"
36
37
38 #if defined(_WIN32)
39 #include <windows.h>
40 #include <windowsx.h>
41 #include <direct.h>
42 #elif defined(__APPLE__)
43 #include "OpenGL.h"
44 #else
45 typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
46 #endif
47
48
49 #if defined(_WIN32) && !defined(__GNUC__)
50 #pragma comment (lib, "opengl32")
51 #pragma comment (lib, "glu32")
52 #endif
53
54 // minimum GL version we can reliably support is 1.2
55 static const int MIN_REQUIRED_GL_VERSION = 12;
56
57 int GL_version = 0;
58
59 bool GL_initted = 0;
60
61 //0==no fog
62 //1==linear
63 //2==fog coord EXT
64 //3==NV Radial
65 int OGL_fogmode = 0;
66
67 #ifdef _WIN32
68 static HDC GL_device_context = NULL;
69 static HGLRC GL_render_context = NULL;
70 static PIXELFORMATDESCRIPTOR GL_pfd;
71 #endif
72
73 static ushort *GL_original_gamma_ramp = NULL;
74
75 int Use_VBOs = 0;
76 int Use_PBOs = 0;
77 int Use_GLSL = 0;
78
79 static int GL_dump_frames = 0;
80 static ubyte *GL_dump_buffer = NULL;
81 static int GL_dump_frame_number = 0;
82 static int GL_dump_frame_count = 0;
83 static int GL_dump_frame_count_max = 0;
84 static int GL_dump_frame_size = 0;
85
86 static ubyte *GL_saved_screen = NULL;
87 static ubyte *GL_saved_mouse_data = NULL;
88 static int GL_saved_screen_id = -1;
89 static GLuint GL_cursor_pbo = 0;
90 static GLuint GL_screen_pbo = 0;
91
92 static int GL_mouse_saved = 0;
93 static int GL_mouse_saved_x1 = 0;
94 static int GL_mouse_saved_y1 = 0;
95 static int GL_mouse_saved_x2 = 0;
96 static int GL_mouse_saved_y2 = 0;
97
98 void opengl_save_mouse_area(int x, int y, int w, int h);
99
100 extern const char *Osreg_title;
101
102 extern GLfloat GL_anisotropy;
103
104 extern float FreeSpace_gamma;
105 void gr_opengl_set_gamma(float gamma);
106
107 extern float FreeSpace_gamma;
108 void gr_opengl_set_gamma(float gamma);
109
110 static int GL_fullscreen = 0;
111 static int GL_windowed = 0;
112 static int GL_minimized = 0;
113
114 static GLenum GL_read_format = GL_BGRA;
115
116
opengl_go_fullscreen()117 void opengl_go_fullscreen()
118 {
119 if (Cmdline_fullscreen_window || Cmdline_window || GL_fullscreen || Fred_running)
120 return;
121
122 #ifdef _WIN32
123 DEVMODE dm;
124 RECT cursor_clip;
125 HWND wnd = (HWND)os_get_window();
126
127 Assert( wnd );
128
129 os_suspend();
130
131 memset((void*)&dm, 0, sizeof(DEVMODE));
132
133 dm.dmSize = sizeof(DEVMODE);
134 dm.dmPelsHeight = gr_screen.max_h;
135 dm.dmPelsWidth = gr_screen.max_w;
136 dm.dmBitsPerPel = gr_screen.bits_per_pixel;
137 dm.dmDisplayFrequency = os_config_read_uint( NULL, NOX("OGL_RefreshRate"), 0 );
138 dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
139
140 if (dm.dmDisplayFrequency)
141 dm.dmFields |= DM_DISPLAYFREQUENCY;
142
143 if ( (ChangeDisplaySettings(&dm, CDS_FULLSCREEN)) != DISP_CHANGE_SUCCESSFUL ) {
144 if (dm.dmDisplayFrequency) {
145 // failed to switch with freq change so try without it just in case
146 dm.dmDisplayFrequency = 0;
147 dm.dmFields &= ~DM_DISPLAYFREQUENCY;
148
149 if ( (ChangeDisplaySettings(&dm, CDS_FULLSCREEN)) != DISP_CHANGE_SUCCESSFUL ) {
150 Warning( LOCATION, "Unable to go fullscreen on second attempt!" );
151 }
152 } else {
153 Warning( LOCATION, "Unable to go fullscreen!" );
154 }
155 }
156
157 ShowWindow( wnd, SW_SHOWNORMAL );
158 UpdateWindow( wnd );
159
160 SetForegroundWindow( wnd );
161 SetActiveWindow( wnd );
162 SetFocus( wnd );
163
164 GetWindowRect((HWND)os_get_window(), &cursor_clip);
165 ClipCursor(&cursor_clip);
166 ShowCursor(FALSE);
167
168 os_resume();
169 #else
170 if ( (os_config_read_uint(NULL, NOX("Fullscreen"), 1) == 1) && !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) ) {
171 os_suspend();
172 // SDL_WM_ToggleFullScreen( SDL_GetVideoSurface() );
173 if ( (SDL_SetVideoMode(gr_screen.max_w, gr_screen.max_h, 0, SDL_OPENGL | SDL_FULLSCREEN)) == NULL ) {
174 mprintf(("Couldn't go fullscreen!\n"));
175 if ( (SDL_SetVideoMode(gr_screen.max_w, gr_screen.max_h, 0, SDL_OPENGL)) == NULL ) {
176 mprintf(("Couldn't drop back to windowed mode either!\n"));
177 exit(1);
178 }
179 }
180 os_resume();
181 }
182 #endif
183
184 gr_opengl_set_gamma(FreeSpace_gamma);
185
186 GL_fullscreen = 1;
187 GL_minimized = 0;
188 GL_windowed = 0;
189 }
190
opengl_go_windowed()191 void opengl_go_windowed()
192 {
193 if ( ( !Cmdline_fullscreen_window && !Cmdline_window ) /*|| GL_windowed*/ || Fred_running )
194 return;
195
196 #ifdef _WIN32
197 HWND wnd = (HWND)os_get_window();
198 Assert( wnd );
199
200 // if we are already in a windowed state, then just make sure that we are sane and bail
201 if (GL_windowed) {
202 SetForegroundWindow( wnd );
203 SetActiveWindow( wnd );
204 SetFocus( wnd );
205
206 ClipCursor(NULL);
207 ShowCursor(FALSE);
208 return;
209 }
210
211 os_suspend();
212
213 ShowWindow( wnd, SW_SHOWNORMAL );
214 UpdateWindow( wnd );
215
216 SetForegroundWindow( wnd );
217 SetActiveWindow( wnd );
218 SetFocus( wnd );
219
220 ClipCursor(NULL);
221 ShowCursor(FALSE);
222
223 os_resume();
224
225 #else
226 if (SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) {
227 os_suspend();
228
229 // SDL_WM_ToggleFullScreen( SDL_GetVideoSurface() );
230 if ( (SDL_SetVideoMode(gr_screen.max_w, gr_screen.max_h, 0, SDL_OPENGL)) == NULL ) {
231 Warning( LOCATION, "Unable to enter windowed mode!" );
232 }
233
234 os_resume();
235 }
236 #endif
237
238 GL_windowed = 1;
239 GL_minimized = 0;
240 GL_fullscreen = 0;
241 }
242
opengl_minimize()243 void opengl_minimize()
244 {
245 // don't attempt to minimize if we are already in a window, or already minimized, or when playing a movie
246 if (GL_minimized /*|| GL_windowed || Cmdline_window*/ || Fred_running)
247 return;
248
249 #ifdef _WIN32
250 HWND wnd = (HWND)os_get_window();
251 Assert( wnd );
252
253 // if we are a window then just show the cursor and bail
254 if ( Cmdline_fullscreen_window || Cmdline_window || GL_windowed) {
255 ClipCursor(NULL);
256 ShowCursor(TRUE);
257 return;
258 }
259
260 os_suspend();
261
262 // restore original gamma settings
263 if (GL_original_gamma_ramp != NULL) {
264 SetDeviceGammaRamp( GL_device_context, GL_original_gamma_ramp );
265 }
266
267 ShowWindow(wnd, SW_MINIMIZE);
268 ChangeDisplaySettings(NULL, 0);
269
270 ClipCursor(NULL);
271 ShowCursor(TRUE);
272
273 os_resume();
274 #else
275 // lets not minimize if we are in windowed mode
276 if ( !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) )
277 return;
278
279 os_suspend();
280
281 if (GL_original_gamma_ramp != NULL) {
282 SDL_SetGammaRamp( GL_original_gamma_ramp, (GL_original_gamma_ramp+256), (GL_original_gamma_ramp+512) );
283 }
284
285 SDL_WM_IconifyWindow();
286 os_resume();
287 #endif
288
289 GL_minimized = 1;
290 GL_windowed = 0;
291 GL_fullscreen = 0;
292 }
293
gr_opengl_activate(int active)294 void gr_opengl_activate(int active)
295 {
296 if (active) {
297 if (Cmdline_fullscreen_window||Cmdline_window)
298 opengl_go_windowed();
299 else
300 opengl_go_fullscreen();
301
302 #ifdef SCP_UNIX
303 // Check again and if we didn't go fullscreen turn on grabbing if possible
304 if(!Cmdline_no_grab && !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN)) {
305 SDL_WM_GrabInput(SDL_GRAB_ON);
306 }
307 #endif
308 } else {
309 opengl_minimize();
310
311 #ifdef SCP_UNIX
312 // let go of mouse/keyboard
313 if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON)
314 SDL_WM_GrabInput(SDL_GRAB_OFF);
315 #endif
316 }
317 }
318
gr_opengl_clear()319 void gr_opengl_clear()
320 {
321 glClearColor(gr_screen.current_clear_color.red / 255.0f,
322 gr_screen.current_clear_color.green / 255.0f,
323 gr_screen.current_clear_color.blue / 255.0f, gr_screen.current_clear_color.alpha / 255.0f);
324
325 glClear ( GL_COLOR_BUFFER_BIT );
326 }
327
gr_opengl_flip()328 void gr_opengl_flip()
329 {
330 if ( !GL_initted )
331 return;
332
333 gr_reset_clip();
334
335 mouse_eval_deltas();
336
337 GL_mouse_saved = 0;
338
339 if ( mouse_is_visible() ) {
340 int mx, my;
341
342 gr_reset_clip();
343 mouse_get_pos( &mx, &my );
344
345 // opengl_save_mouse_area(mx, my, Gr_cursor_size, Gr_cursor_size);
346
347 if (Gr_cursor != -1 && bm_is_valid(Gr_cursor)) {
348 gr_set_bitmap(Gr_cursor);
349 gr_bitmap( mx, my, GR_RESIZE_NONE);
350 }
351 }
352
353 #ifdef _WIN32
354 SwapBuffers(GL_device_context);
355 #else
356 SDL_GL_SwapBuffers();
357 #endif
358
359 opengl_tcache_frame();
360
361 #ifndef NDEBUG
362 int ic = opengl_check_for_errors();
363
364 if (ic) {
365 mprintf(("!!DEBUG!! OpenGL Errors this frame: %i\n", ic));
366 }
367 #endif
368 }
369
gr_opengl_set_clip(int x,int y,int w,int h,int resize_mode)370 void gr_opengl_set_clip(int x, int y, int w, int h, int resize_mode)
371 {
372 // check for sanity of parameters
373 if (x < 0) {
374 x = 0;
375 }
376
377 if (y < 0) {
378 y = 0;
379 }
380
381 int to_resize = (resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)));
382
383 int max_w = ((to_resize) ? gr_screen.max_w_unscaled : gr_screen.max_w);
384 int max_h = ((to_resize) ? gr_screen.max_h_unscaled : gr_screen.max_h);
385
386 if (x >= max_w) {
387 x = max_w - 1;
388 }
389
390 if (y >= max_h) {
391 y = max_h - 1;
392 }
393
394 if (x + w > max_w) {
395 w = max_w - x;
396 }
397
398 if (y + h > max_h) {
399 h = max_h - y;
400 }
401
402 if (w > max_w) {
403 w = max_w;
404 }
405
406 if (h > max_h) {
407 h = max_h;
408 }
409
410 gr_screen.offset_x_unscaled = x;
411 gr_screen.offset_y_unscaled = y;
412 gr_screen.clip_left_unscaled = 0;
413 gr_screen.clip_right_unscaled = w-1;
414 gr_screen.clip_top_unscaled = 0;
415 gr_screen.clip_bottom_unscaled = h-1;
416 gr_screen.clip_width_unscaled = w;
417 gr_screen.clip_height_unscaled = h;
418
419 if (to_resize) {
420 gr_resize_screen_pos(&x, &y, &w, &h, resize_mode);
421 } else {
422 gr_unsize_screen_pos( &gr_screen.offset_x_unscaled, &gr_screen.offset_y_unscaled );
423 gr_unsize_screen_pos( &gr_screen.clip_right_unscaled, &gr_screen.clip_bottom_unscaled );
424 gr_unsize_screen_pos( &gr_screen.clip_width_unscaled, &gr_screen.clip_height_unscaled );
425 }
426
427 gr_screen.offset_x = x;
428 gr_screen.offset_y = y;
429 gr_screen.clip_left = 0;
430 gr_screen.clip_right = w-1;
431 gr_screen.clip_top = 0;
432 gr_screen.clip_bottom = h-1;
433 gr_screen.clip_width = w;
434 gr_screen.clip_height = h;
435
436 gr_screen.clip_aspect = i2fl(w) / i2fl(h);
437 gr_screen.clip_center_x = (gr_screen.clip_left + gr_screen.clip_right) * 0.5f;
438 gr_screen.clip_center_y = (gr_screen.clip_top + gr_screen.clip_bottom) * 0.5f;
439
440 // just return early if we aren't actually going to need the scissor test
441 if ( (x == 0) && (y == 0) && (w == max_w) && (h == max_h) ) {
442 GL_state.ScissorTest(GL_FALSE);
443 return;
444 }
445
446 GL_state.ScissorTest(GL_TRUE);
447 if(GL_rendering_to_texture) {
448 glScissor(x, y, w, h);
449 } else {
450 glScissor(x, gr_screen.max_h-y-h, w, h);
451 }
452 }
453
gr_opengl_reset_clip()454 void gr_opengl_reset_clip()
455 {
456 gr_screen.offset_x = gr_screen.offset_x_unscaled = 0;
457 gr_screen.offset_y = gr_screen.offset_y_unscaled = 0;
458 gr_screen.clip_left = gr_screen.clip_left_unscaled = 0;
459 gr_screen.clip_top = gr_screen.clip_top_unscaled = 0;
460 gr_screen.clip_right = gr_screen.clip_right_unscaled = gr_screen.max_w - 1;
461 gr_screen.clip_bottom = gr_screen.clip_bottom_unscaled = gr_screen.max_h - 1;
462 gr_screen.clip_width = gr_screen.clip_width_unscaled = gr_screen.max_w;
463 gr_screen.clip_height = gr_screen.clip_height_unscaled = gr_screen.max_h;
464
465 if (gr_screen.custom_size) {
466 gr_unsize_screen_pos( &gr_screen.clip_right_unscaled, &gr_screen.clip_bottom_unscaled );
467 gr_unsize_screen_pos( &gr_screen.clip_width_unscaled, &gr_screen.clip_height_unscaled );
468 }
469
470 gr_screen.clip_aspect = i2fl(gr_screen.clip_width) / i2fl(gr_screen.clip_height);
471 gr_screen.clip_center_x = (gr_screen.clip_left + gr_screen.clip_right) * 0.5f;
472 gr_screen.clip_center_y = (gr_screen.clip_top + gr_screen.clip_bottom) * 0.5f;
473
474 GL_state.ScissorTest(GL_FALSE);
475 }
476
gr_opengl_set_palette(ubyte * new_palette,int is_alphacolor)477 void gr_opengl_set_palette(ubyte *new_palette, int is_alphacolor)
478 {
479 }
480
gr_opengl_print_screen(const char * filename)481 void gr_opengl_print_screen(const char *filename)
482 {
483 char tmp[MAX_PATH_LEN];
484 ubyte tga_hdr[18];
485 int i;
486 ushort width, height;
487 GLubyte *pixels = NULL;
488 GLuint pbo = 0;
489
490 // save to a "screenshots" directory and tack on the filename
491 #ifdef SCP_UNIX
492 snprintf( tmp, MAX_PATH_LEN-1, "%s/%s/screenshots/%s.tga", detect_home(), Osreg_user_dir, filename);
493 _mkdir( tmp );
494 #else
495 _getcwd( tmp, MAX_PATH_LEN-1 );
496 strcat_s( tmp, "\\screenshots\\" );
497 _mkdir( tmp );
498
499 strcat_s( tmp, filename );
500 strcat_s( tmp, ".tga" );
501 #endif
502
503 FILE *fout = fopen(tmp, "wb");
504
505 if (fout == NULL) {
506 return;
507 }
508
509 // glReadBuffer(GL_FRONT);
510
511 // now for the data
512 if (Use_PBOs) {
513 Assert( !pbo );
514 vglGenBuffersARB(1, &pbo);
515
516 if ( !pbo ) {
517 if (fout != NULL)
518 fclose(fout);
519
520 return;
521 }
522
523 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo);
524 vglBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, (gr_screen.max_w * gr_screen.max_h * 4), NULL, GL_STATIC_READ);
525
526 glReadBuffer(GL_FRONT);
527 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
528
529 // map the image data so that we can save it to file
530 pixels = (GLubyte*) vglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
531 } else {
532 pixels = (GLubyte*) vm_malloc_q(gr_screen.max_w * gr_screen.max_h * 4);
533
534 if (pixels == NULL) {
535 if (fout != NULL) {
536 fclose(fout);
537 }
538
539 return;
540 }
541
542 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
543 glFlush();
544 }
545
546 // Write the TGA header
547 width = INTEL_SHORT((ushort)gr_screen.max_w);
548 height = INTEL_SHORT((ushort)gr_screen.max_h);
549
550 memset( tga_hdr, 0, sizeof(tga_hdr) );
551
552 tga_hdr[2] = 2; // ImageType 2 = 24bpp, uncompressed
553 memcpy( tga_hdr + 12, &width, sizeof(ushort) ); // Width
554 memcpy( tga_hdr + 14, &height, sizeof(ushort) ); // Height
555 tga_hdr[16] = 24; // PixelDepth
556
557 fwrite( tga_hdr, sizeof(tga_hdr), 1, fout );
558
559 // now for the data, we convert it from 32-bit to 24-bit
560 for (i = 0; i < (gr_screen.max_w * gr_screen.max_h * 4); i += 4) {
561 #if BYTE_ORDER == BIG_ENDIAN
562 int pix, *pix_tmp;
563
564 pix_tmp = (int*)(pixels + i);
565 pix = INTEL_INT(*pix_tmp);
566
567 fwrite( &pix, 1, 3, fout );
568 #else
569 fwrite( pixels + i, 1, 3, fout );
570 #endif
571 }
572
573 if (pbo) {
574 vglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
575 pixels = NULL;
576 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
577 vglDeleteBuffersARB(1, &pbo);
578 }
579
580 // done!
581 fclose(fout);
582
583 if (pixels != NULL) {
584 vm_free(pixels);
585 }
586 }
587
gr_opengl_cleanup(int minimize)588 void gr_opengl_cleanup(int minimize)
589 {
590 if ( !GL_initted ) {
591 return;
592 }
593
594 if ( !Fred_running ) {
595 gr_reset_clip();
596 gr_clear();
597 gr_flip();
598 gr_clear();
599 gr_flip();
600 gr_clear();
601 }
602
603 GL_initted = false;
604
605 opengl_tcache_flush();
606
607 #ifdef _WIN32
608 HWND wnd = (HWND)os_get_window();
609
610 if (GL_render_context) {
611 if ( !wglMakeCurrent(NULL, NULL) ) {
612 MessageBox(wnd, "SHUTDOWN ERROR", "error", MB_OK);
613 }
614
615 if ( !wglDeleteContext(GL_render_context) ) {
616 MessageBox(wnd, "Unable to delete rendering context", "error", MB_OK);
617 }
618
619 GL_render_context = NULL;
620 }
621 #endif
622
623 opengl_minimize();
624
625 if (minimize) {
626 #ifdef _WIN32
627 if ( !Cmdline_fullscreen_window && !Cmdline_window ) {
628 ChangeDisplaySettings(NULL, 0);
629 }
630 #endif
631 }
632 }
633
gr_opengl_fog_set(int fog_mode,int r,int g,int b,float fog_near,float fog_far)634 void gr_opengl_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
635 {
636 // mprintf(("gr_opengl_fog_set(%d,%d,%d,%d,%f,%f)\n",fog_mode,r,g,b,fog_near,fog_far));
637
638 Assert((r >= 0) && (r < 256));
639 Assert((g >= 0) && (g < 256));
640 Assert((b >= 0) && (b < 256));
641
642 if (fog_mode == GR_FOGMODE_NONE) {
643 if ( GL_state.Fog() ) {
644 GL_state.Fog(GL_FALSE);
645 }
646
647 gr_screen.current_fog_mode = fog_mode;
648
649 return;
650 }
651
652 if (gr_screen.current_fog_mode != fog_mode) {
653 if (OGL_fogmode == 3) {
654 glFogf(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
655 glFogf(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH);
656 }
657 // Um.. this is not the correct way to fog in software, probably doesn't matter though
658 else if ( (OGL_fogmode == 2) && Cmdline_nohtl ) {
659 glFogf(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
660 fog_near *= fog_near; // it's faster this way
661 fog_far *= fog_far;
662 } else {
663 glFogf(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH);
664 }
665
666 GL_state.Fog(GL_TRUE);
667 glFogf(GL_FOG_MODE, GL_LINEAR);
668 glFogf(GL_FOG_START, fog_near);
669 glFogf(GL_FOG_END, fog_far);
670
671 gr_screen.current_fog_mode = fog_mode;
672 }
673
674 if ( (gr_screen.current_fog_color.red != r) ||
675 (gr_screen.current_fog_color.green != g) ||
676 (gr_screen.current_fog_color.blue != b) )
677 {
678 GLfloat fc[4];
679
680 gr_init_color( &gr_screen.current_fog_color, r, g, b );
681
682 fc[0] = (float)r/255.0f;
683 fc[1] = (float)g/255.0f;
684 fc[2] = (float)b/255.0f;
685 fc[3] = 1.0f;
686
687 glFogfv(GL_FOG_COLOR, fc);
688 }
689
690 }
691
gr_opengl_set_cull(int cull)692 int gr_opengl_set_cull(int cull)
693 {
694 GLboolean enabled = GL_FALSE;
695
696 if (cull) {
697 enabled = GL_state.CullFace(GL_TRUE);
698 GL_state.FrontFaceValue(GL_CCW);
699 GL_state.CullFaceValue(GL_BACK);
700 } else {
701 enabled = GL_state.CullFace(GL_FALSE);
702 }
703
704 return (enabled) ? 1 : 0;
705 }
706
gr_opengl_set_clear_color(int r,int g,int b)707 void gr_opengl_set_clear_color(int r, int g, int b)
708 {
709 gr_init_color(&gr_screen.current_clear_color, r, g, b);
710 }
711
gr_opengl_set_color_buffer(int mode)712 int gr_opengl_set_color_buffer(int mode)
713 {
714 GLboolean enabled = GL_FALSE;
715
716 if ( mode ) {
717 enabled = GL_state.ColorMask(GL_TRUE);
718 } else {
719 enabled = GL_state.ColorMask(GL_FALSE);
720 }
721
722 GL_state.SetAlphaBlendMode(ALPHA_BLEND_ALPHA_BLEND_ALPHA);
723
724 return (enabled) ? 1 : 0;
725 }
726
gr_opengl_zbuffer_get()727 int gr_opengl_zbuffer_get()
728 {
729 if ( !gr_global_zbuffering ) {
730 return GR_ZBUFF_NONE;
731 }
732
733 return gr_zbuffering_mode;
734 }
735
gr_opengl_zbuffer_set(int mode)736 int gr_opengl_zbuffer_set(int mode)
737 {
738 int tmp = gr_zbuffering_mode;
739
740 gr_zbuffering_mode = mode;
741
742 if (gr_zbuffering_mode == GR_ZBUFF_NONE) {
743 gr_zbuffering = 0;
744 GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
745 } else if ( gr_zbuffering_mode == GR_ZBUFF_READ ) {
746 gr_zbuffering = 1;
747 GL_state.SetZbufferType(ZBUFFER_TYPE_READ);
748 } else {
749 gr_zbuffering = 1;
750 GL_state.SetZbufferType(ZBUFFER_TYPE_FULL);
751 }
752
753 return tmp;
754 }
755
gr_opengl_zbuffer_clear(int mode)756 void gr_opengl_zbuffer_clear(int mode)
757 {
758 if (mode) {
759 gr_zbuffering = 1;
760 gr_zbuffering_mode = GR_ZBUFF_FULL;
761 gr_global_zbuffering = 1;
762
763 GL_state.SetTextureSource(TEXTURE_SOURCE_NONE);
764 GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
765 GL_state.SetZbufferType(ZBUFFER_TYPE_FULL);
766
767 glClear(GL_DEPTH_BUFFER_BIT);
768 } else {
769 gr_zbuffering = 0;
770 gr_zbuffering_mode = GR_ZBUFF_NONE;
771 gr_global_zbuffering = 0;
772
773 GL_state.DepthTest(GL_FALSE);
774 }
775 }
776
gr_opengl_stencil_set(int mode)777 int gr_opengl_stencil_set(int mode)
778 {
779 int tmp = gr_stencil_mode;
780
781 gr_stencil_mode = mode;
782
783 if ( mode == GR_STENCIL_READ ) {
784 GL_state.StencilTest(1);
785 GL_state.SetStencilType(STENCIL_TYPE_READ);
786 } else if ( mode == GR_STENCIL_WRITE ) {
787 GL_state.StencilTest(1);
788 GL_state.SetStencilType(STENCIL_TYPE_WRITE);
789 } else {
790 GL_state.StencilTest(0);
791 GL_state.SetStencilType(STENCIL_TYPE_NONE);
792 }
793
794 return tmp;
795 }
796
gr_opengl_stencil_clear()797 void gr_opengl_stencil_clear()
798 {
799 glClear(GL_STENCIL_BUFFER_BIT);
800 }
801
gr_opengl_alpha_mask_set(int mode,float alpha)802 int gr_opengl_alpha_mask_set(int mode, float alpha)
803 {
804 int tmp = gr_alpha_test;
805
806 gr_alpha_test = mode;
807
808 if ( mode ) {
809 GL_state.AlphaTest(GL_TRUE);
810 GL_state.AlphaFunc(GL_GREATER, alpha);
811 } else {
812 GL_state.AlphaTest(GL_FALSE);
813 GL_state.AlphaFunc(GL_ALWAYS, 1.0f);
814 }
815
816 return tmp;
817 }
818
819 // I feel dirty...
opengl_make_gamma_ramp(float gamma,ushort * ramp)820 static void opengl_make_gamma_ramp(float gamma, ushort *ramp)
821 {
822 ushort x, y;
823 ushort base_ramp[256];
824
825 Assert( ramp != NULL );
826
827 // generate the base ramp values first off
828
829 // if no gamma set then just do this quickly
830 if (gamma <= 0.0f) {
831 memset( ramp, 0, 3 * 256 * sizeof(ushort) );
832 return;
833 }
834 // identity gamma, avoid all of the math
835 else if ( (gamma == 1.0f) || (GL_original_gamma_ramp == NULL) ) {
836 if (GL_original_gamma_ramp != NULL) {
837 memcpy( ramp, GL_original_gamma_ramp, 3 * 256 * sizeof(ushort) );
838 }
839 // set identity if no original ramp
840 else {
841 for (x = 0; x < 256; x++) {
842 ramp[x] = (x << 8) | x;
843 ramp[x + 256] = (x << 8) | x;
844 ramp[x + 512] = (x << 8) | x;
845 }
846 }
847
848 return;
849 }
850 // for everything else we need to actually figure it up
851 else {
852 double g = 1.0 / (double)gamma;
853 double val;
854
855 Assert( GL_original_gamma_ramp != NULL );
856
857 for (x = 0; x < 256; x++) {
858 val = (pow(x/255.0, g) * 65535.0 + 0.5);
859 CLAMP( val, 0, 65535 );
860
861 base_ramp[x] = (ushort)val;
862 }
863
864 for (y = 0; y < 3; y++) {
865 for (x = 0; x < 256; x++) {
866 val = (base_ramp[x] * 2) - GL_original_gamma_ramp[x + y * 256];
867 CLAMP( val, 0, 65535 );
868
869 ramp[x + y * 256] = (ushort)val;
870 }
871 }
872 }
873 }
874
gr_opengl_set_gamma(float gamma)875 void gr_opengl_set_gamma(float gamma)
876 {
877 ushort *gamma_ramp = NULL;
878
879 Gr_gamma = gamma;
880 Gr_gamma_int = int (Gr_gamma*10);
881
882 // new way - but not while running FRED
883 if (!Fred_running && !Cmdline_no_set_gamma) {
884 gamma_ramp = (ushort*) vm_malloc_q( 3 * 256 * sizeof(ushort) );
885
886 if (gamma_ramp == NULL) {
887 Int3();
888 return;
889 }
890
891 memset( gamma_ramp, 0, 3 * 256 * sizeof(ushort) );
892
893 // Create the Gamma lookup table
894 opengl_make_gamma_ramp(gamma, gamma_ramp);
895
896 #ifdef _WIN32
897 SetDeviceGammaRamp( GL_device_context, gamma_ramp );
898 #else
899 SDL_SetGammaRamp( gamma_ramp, (gamma_ramp+256), (gamma_ramp+512) );
900 #endif
901
902 vm_free(gamma_ramp);
903 }
904 }
905
gr_opengl_get_region(int front,int w,int h,ubyte * data)906 void gr_opengl_get_region(int front, int w, int h, ubyte *data)
907 {
908
909 // if (front) {
910 // glReadBuffer(GL_FRONT);
911 // } else {
912 glReadBuffer(GL_BACK);
913 // }
914
915 GL_state.SetTextureSource(TEXTURE_SOURCE_NO_FILTERING);
916 GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
917 GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
918
919 if (gr_screen.bits_per_pixel == 16) {
920 glReadPixels(0, gr_screen.max_h-h, w, h, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, data);
921 } else if (gr_screen.bits_per_pixel == 32) {
922 glReadPixels(0, gr_screen.max_h-h, w, h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
923 }
924
925
926 }
927
opengl_save_mouse_area(int x,int y,int w,int h)928 void opengl_save_mouse_area(int x, int y, int w, int h)
929 {
930 int cursor_size;
931
932 GL_CHECK_FOR_ERRORS("start of save_mouse_area()");
933
934 // lazy - taylor
935 cursor_size = (Gr_cursor_size * Gr_cursor_size);
936
937 // no reason to be bigger than the cursor, should never be smaller
938 if (w != Gr_cursor_size)
939 w = Gr_cursor_size;
940 if (h != Gr_cursor_size)
941 h = Gr_cursor_size;
942
943 GL_mouse_saved_x1 = x;
944 GL_mouse_saved_y1 = y;
945 GL_mouse_saved_x2 = x+w-1;
946 GL_mouse_saved_y2 = y+h-1;
947
948 CLAMP(GL_mouse_saved_x1, gr_screen.clip_left, gr_screen.clip_right );
949 CLAMP(GL_mouse_saved_x2, gr_screen.clip_left, gr_screen.clip_right );
950 CLAMP(GL_mouse_saved_y1, gr_screen.clip_top, gr_screen.clip_bottom );
951 CLAMP(GL_mouse_saved_y2, gr_screen.clip_top, gr_screen.clip_bottom );
952
953 GL_state.SetTextureSource(TEXTURE_SOURCE_NO_FILTERING);
954 GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
955 GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
956
957 if ( Use_PBOs ) {
958 // since this is used a lot, and is pretty small in size, we just create it once and leave it until exit
959 if (!GL_cursor_pbo) {
960 vglGenBuffersARB(1, &GL_cursor_pbo);
961 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_cursor_pbo);
962 vglBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, cursor_size * 4, NULL, GL_STATIC_READ);
963 }
964
965 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_cursor_pbo);
966 glReadBuffer(GL_BACK);
967 glReadPixels(x, gr_screen.max_h-y-1-h, w, h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
968 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
969 } else {
970 // this should really only have to be malloc'd once
971 if (GL_saved_mouse_data == NULL)
972 GL_saved_mouse_data = (ubyte*)vm_malloc_q(cursor_size * 4);
973
974 if (GL_saved_mouse_data == NULL)
975 return;
976
977 glReadBuffer(GL_BACK);
978 glReadPixels(x, gr_screen.max_h-y-1-h, w, h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, GL_saved_mouse_data);
979 }
980
981 GL_CHECK_FOR_ERRORS("end of save_mouse_area()");
982
983 GL_mouse_saved = 1;
984 }
985
gr_opengl_save_screen()986 int gr_opengl_save_screen()
987 {
988 int i;
989 ubyte *sptr = NULL, *dptr = NULL;
990 ubyte *opengl_screen_tmp = NULL;
991 int width_times_pixel, mouse_times_pixel;
992
993 gr_opengl_reset_clip();
994
995 if (GL_saved_screen || GL_screen_pbo) {
996 // already have a screen saved so just bail...
997 return -1;
998 }
999
1000 GL_saved_screen = (ubyte*)vm_malloc_q( gr_screen.max_w * gr_screen.max_h * 4 );
1001
1002 if (!GL_saved_screen) {
1003 mprintf(( "Couldn't get memory for saved screen!\n" ));
1004 return -1;
1005 }
1006
1007 GLboolean save_state = GL_state.DepthTest(GL_FALSE);
1008 glReadBuffer(GL_FRONT_LEFT);
1009
1010 if ( Use_PBOs ) {
1011 GLubyte *pixels = NULL;
1012
1013 vglGenBuffersARB(1, &GL_screen_pbo);
1014
1015 if (!GL_screen_pbo) {
1016 if (GL_saved_screen) {
1017 vm_free(GL_saved_screen);
1018 GL_saved_screen = NULL;
1019 }
1020
1021 return -1;
1022 }
1023
1024 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_screen_pbo);
1025 vglBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, gr_screen.max_w * gr_screen.max_h * 4, NULL, GL_STATIC_READ);
1026
1027 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1028
1029 pixels = (GLubyte*)vglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1030
1031 width_times_pixel = (gr_screen.max_w * 4);
1032 mouse_times_pixel = (Gr_cursor_size * 4);
1033
1034 sptr = (ubyte *)pixels;
1035 dptr = (ubyte *)&GL_saved_screen[gr_screen.max_w * gr_screen.max_h * 4];
1036
1037 for (i = 0; i < gr_screen.max_h; i++) {
1038 dptr -= width_times_pixel;
1039 memcpy(dptr, sptr, width_times_pixel);
1040 sptr += width_times_pixel;
1041 }
1042
1043 vglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1044 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1045
1046 if (GL_mouse_saved && GL_cursor_pbo) {
1047 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_cursor_pbo);
1048
1049 pixels = (GLubyte*)vglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1050
1051 sptr = (ubyte *)pixels;
1052 dptr = (ubyte *)&GL_saved_screen[(GL_mouse_saved_x1 + GL_mouse_saved_y2 * gr_screen.max_w) * 4];
1053
1054 for (i = 0; i < Gr_cursor_size; i++) {
1055 memcpy(dptr, sptr, mouse_times_pixel);
1056 sptr += mouse_times_pixel;
1057 dptr -= width_times_pixel;
1058 }
1059
1060 vglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1061 vglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1062 }
1063
1064 vglDeleteBuffersARB(1, &GL_screen_pbo);
1065 GL_screen_pbo = 0;
1066
1067 GL_saved_screen_id = bm_create(32, gr_screen.max_w, gr_screen.max_h, GL_saved_screen, 0);
1068 } else {
1069 opengl_screen_tmp = (ubyte*)vm_malloc_q( gr_screen.max_w * gr_screen.max_h * 4 );
1070
1071 if (!opengl_screen_tmp) {
1072 if (GL_saved_screen) {
1073 vm_free(GL_saved_screen);
1074 GL_saved_screen = NULL;
1075 }
1076
1077 mprintf(( "Couldn't get memory for temporary saved screen!\n" ));
1078 GL_state.DepthTest(save_state);
1079 return -1;
1080 }
1081
1082 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_read_format, GL_UNSIGNED_INT_8_8_8_8_REV, opengl_screen_tmp);
1083
1084 sptr = (ubyte *)&opengl_screen_tmp[gr_screen.max_w * gr_screen.max_h * 4];
1085 dptr = (ubyte *)GL_saved_screen;
1086
1087 width_times_pixel = (gr_screen.max_w * 4);
1088 mouse_times_pixel = (Gr_cursor_size * 4);
1089
1090 for (i = 0; i < gr_screen.max_h; i++) {
1091 sptr -= width_times_pixel;
1092 memcpy(dptr, sptr, width_times_pixel);
1093 dptr += width_times_pixel;
1094 }
1095
1096 vm_free(opengl_screen_tmp);
1097
1098 if (GL_mouse_saved && GL_saved_mouse_data) {
1099 sptr = (ubyte *)GL_saved_mouse_data;
1100 dptr = (ubyte *)&GL_saved_screen[(GL_mouse_saved_x1 + GL_mouse_saved_y2 * gr_screen.max_w) * 4];
1101
1102 for (i = 0; i < Gr_cursor_size; i++) {
1103 memcpy(dptr, sptr, mouse_times_pixel);
1104 sptr += mouse_times_pixel;
1105 dptr -= width_times_pixel;
1106 }
1107 }
1108
1109 GL_saved_screen_id = bm_create(32, gr_screen.max_w, gr_screen.max_h, GL_saved_screen, 0);
1110 }
1111
1112 GL_state.DepthTest(save_state);
1113
1114 return GL_saved_screen_id;
1115 }
1116
gr_opengl_restore_screen(int bmp_id)1117 void gr_opengl_restore_screen(int bmp_id)
1118 {
1119 gr_reset_clip();
1120
1121 if ( !GL_saved_screen ) {
1122 gr_clear();
1123 return;
1124 }
1125
1126 Assert( (bmp_id < 0) || (bmp_id == GL_saved_screen_id) );
1127
1128 if (GL_saved_screen_id < 0)
1129 return;
1130
1131 gr_set_bitmap(GL_saved_screen_id);
1132 gr_bitmap(0, 0, GR_RESIZE_NONE); // don't scale here since we already have real screen size
1133 }
1134
gr_opengl_free_screen(int bmp_id)1135 void gr_opengl_free_screen(int bmp_id)
1136 {
1137 if (!GL_saved_screen)
1138 return;
1139
1140 vm_free(GL_saved_screen);
1141 GL_saved_screen = NULL;
1142
1143 Assert( (bmp_id < 0) || (bmp_id == GL_saved_screen_id) );
1144
1145 if (GL_saved_screen_id < 0)
1146 return;
1147
1148 bm_release(GL_saved_screen_id);
1149 GL_saved_screen_id = -1;
1150 }
1151
opengl_flush_frame_dump()1152 static void opengl_flush_frame_dump()
1153 {
1154 char filename[MAX_FILENAME_LEN];
1155
1156 Assert( GL_dump_buffer != NULL);
1157
1158 for (int i = 0; i < GL_dump_frame_count; i++) {
1159 sprintf(filename, NOX("frm%04d.tga"), GL_dump_frame_number );
1160 GL_dump_frame_number++;
1161
1162 CFILE *f = cfopen(filename, "wb", CFILE_NORMAL, CF_TYPE_DATA);
1163
1164 // Write the TGA header
1165 cfwrite_ubyte( 0, f ); // IDLength;
1166 cfwrite_ubyte( 0, f ); // ColorMapType;
1167 cfwrite_ubyte( 2, f ); // ImageType; // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
1168 cfwrite_ushort( 0, f ); // CMapStart;
1169 cfwrite_ushort( 0, f ); // CMapLength;
1170 cfwrite_ubyte( 0, f ); // CMapDepth;
1171 cfwrite_ushort( 0, f ); // XOffset;
1172 cfwrite_ushort( 0, f ); // YOffset;
1173 cfwrite_ushort( (ushort)gr_screen.max_w, f ); // Width;
1174 cfwrite_ushort( (ushort)gr_screen.max_h, f ); // Height;
1175 cfwrite_ubyte( 24, f ); //PixelDepth;
1176 cfwrite_ubyte( 0, f ); //ImageDesc;
1177
1178 glReadBuffer(GL_FRONT);
1179 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_BGR_EXT, GL_UNSIGNED_BYTE, GL_dump_buffer);
1180
1181 // save the data out
1182 cfwrite( GL_dump_buffer, GL_dump_frame_size, 1, f );
1183
1184 cfclose(f);
1185
1186 }
1187
1188 GL_dump_frame_count = 0;
1189 }
1190
gr_opengl_dump_frame_start(int first_frame,int frames_between_dumps)1191 void gr_opengl_dump_frame_start(int first_frame, int frames_between_dumps)
1192 {
1193 if ( GL_dump_frames ) {
1194 Int3(); // We're already dumping frames. See John.
1195 return;
1196 }
1197
1198 GL_dump_frames = 1;
1199 GL_dump_frame_number = first_frame;
1200 GL_dump_frame_count = 0;
1201 GL_dump_frame_count_max = frames_between_dumps; // only works if it's 1
1202 GL_dump_frame_size = gr_screen.max_w * gr_screen.max_h * 3;
1203
1204 if ( !GL_dump_buffer ) {
1205 int size = GL_dump_frame_count_max * GL_dump_frame_size;
1206
1207 GL_dump_buffer = (ubyte *)vm_malloc(size);
1208
1209 if ( !GL_dump_buffer ) {
1210 Error(LOCATION, "Unable to malloc %d bytes for dump buffer", size );
1211 }
1212 }
1213 }
1214
gr_opengl_dump_frame_stop()1215 void gr_opengl_dump_frame_stop()
1216 {
1217 if ( !GL_dump_frames ) {
1218 Int3(); // We're not dumping frames. See John.
1219 return;
1220 }
1221
1222 // dump any remaining frames
1223 opengl_flush_frame_dump();
1224
1225 GL_dump_frames = 0;
1226
1227 if ( GL_dump_buffer ) {
1228 vm_free(GL_dump_buffer);
1229 GL_dump_buffer = NULL;
1230 }
1231 }
1232
gr_opengl_dump_frame()1233 void gr_opengl_dump_frame()
1234 {
1235 GL_dump_frame_count++;
1236
1237 if ( GL_dump_frame_count == GL_dump_frame_count_max ) {
1238 opengl_flush_frame_dump();
1239 }
1240 }
1241
1242 //fill mode, solid/wire frame
gr_opengl_set_fill_mode(int mode)1243 void gr_opengl_set_fill_mode(int mode)
1244 {
1245 if (mode == GR_FILL_MODE_SOLID) {
1246 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1247 return;
1248 }
1249
1250 if (mode == GR_FILL_MODE_WIRE) {
1251 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1252 return;
1253 }
1254
1255 // default setting
1256 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1257 }
1258
gr_opengl_zbias(int bias)1259 void gr_opengl_zbias(int bias)
1260 {
1261 if (bias) {
1262 GL_state.PolygonOffsetFill(GL_TRUE);
1263 glPolygonOffset(0.0, -i2fl(bias));
1264 } else {
1265 GL_state.PolygonOffsetFill(GL_FALSE);
1266 }
1267 }
1268
gr_opengl_push_texture_matrix(int unit)1269 void gr_opengl_push_texture_matrix(int unit)
1270 {
1271 GLint current_matrix;
1272
1273 if (unit > GL_supported_texture_units)
1274 return;
1275
1276 glGetIntegerv(GL_MATRIX_MODE, ¤t_matrix);
1277 vglActiveTextureARB(GL_TEXTURE0_ARB+unit);
1278
1279 glMatrixMode(GL_TEXTURE);
1280 glPushMatrix();
1281
1282 glMatrixMode(current_matrix);
1283 }
1284
gr_opengl_pop_texture_matrix(int unit)1285 void gr_opengl_pop_texture_matrix(int unit)
1286 {
1287 GLint current_matrix;
1288
1289 if (unit > GL_supported_texture_units)
1290 return;
1291
1292 glGetIntegerv(GL_MATRIX_MODE, ¤t_matrix);
1293 vglActiveTextureARB(GL_TEXTURE0_ARB+unit);
1294
1295 glMatrixMode(GL_TEXTURE);
1296 glPopMatrix();
1297
1298 glMatrixMode(current_matrix);
1299 }
1300
gr_opengl_translate_texture_matrix(int unit,vec3d * shift)1301 void gr_opengl_translate_texture_matrix(int unit, vec3d *shift)
1302 {
1303 GLint current_matrix;
1304
1305 if (unit > GL_supported_texture_units) {
1306 /*tex_shift=*shift;*/
1307 return;
1308 }
1309
1310 glGetIntegerv(GL_MATRIX_MODE, ¤t_matrix);
1311 vglActiveTextureARB(GL_TEXTURE0_ARB+unit);
1312
1313 glMatrixMode(GL_TEXTURE);
1314 glTranslated(shift->xyz.x, shift->xyz.y, shift->xyz.z);
1315
1316 glMatrixMode(current_matrix);
1317
1318 // tex_shift=vmd_zero_vector;
1319 }
1320
gr_opengl_setup_background_fog(bool set)1321 void gr_opengl_setup_background_fog(bool set)
1322 {
1323 if (Cmdline_nohtl) {
1324 return;
1325 }
1326 }
1327
gr_opengl_set_line_width(float width)1328 void gr_opengl_set_line_width(float width)
1329 {
1330 glLineWidth(width);
1331 }
1332
1333 // Returns the human readable error string if there is an error or NULL if not
opengl_error_string()1334 const char *opengl_error_string()
1335 {
1336 GLenum error = GL_NO_ERROR;
1337
1338 error = glGetError();
1339
1340 if ( error != GL_NO_ERROR ) {
1341 return (const char *)gluErrorString(error);
1342 }
1343
1344 return NULL;
1345 }
1346
opengl_check_for_errors(char * err_at)1347 int opengl_check_for_errors(char *err_at)
1348 {
1349 #ifdef NDEBUG
1350 return 0;
1351 #endif
1352 const char *error_str = NULL;
1353 int num_errors = 0;
1354
1355 error_str = opengl_error_string();
1356
1357 if (error_str) {
1358 if (err_at != NULL) {
1359 nprintf(("OpenGL", "OpenGL Error from %s: %s\n", err_at, error_str));
1360 } else {
1361 nprintf(("OpenGL", "OpenGL Error: %s\n", error_str));
1362 }
1363
1364 num_errors++;
1365 }
1366
1367 return num_errors;
1368 }
1369
opengl_set_vsync(int status)1370 void opengl_set_vsync(int status)
1371 {
1372 if ( (status < 0) || (status > 1) ) {
1373 Int3();
1374 return;
1375 }
1376
1377 #if defined(__APPLE__)
1378 // GLInt on 10.6 is an actual int now, instead of a long
1379 // This will need further testing once Snow Leopard 10.6 goes RTM
1380 CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, (GLint*)&status);
1381 #elif defined(_WIN32)
1382 vwglSwapIntervalEXT(status);
1383 #else
1384 // NOTE: this may not work well with the closed NVIDIA drivers since those use the
1385 // special "__GL_SYNC_TO_VBLANK" environment variable to manage sync
1386 vglXSwapIntervalSGI(status);
1387 #endif
1388
1389 GL_CHECK_FOR_ERRORS("end of set_vsync()");
1390 }
1391
opengl_setup_viewport()1392 void opengl_setup_viewport()
1393 {
1394 glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
1395
1396 glMatrixMode(GL_PROJECTION);
1397 glLoadIdentity();
1398
1399 // the top and bottom positions are reversed on purpose, but RTT needs them the other way
1400 if (GL_rendering_to_texture) {
1401 glOrtho(0, gr_screen.max_w, 0, gr_screen.max_h, -1.0, 1.0);
1402 } else {
1403 glOrtho(0, gr_screen.max_w, gr_screen.max_h, 0, -1.0, 1.0);
1404 }
1405
1406 glMatrixMode(GL_MODELVIEW);
1407 glLoadIdentity();
1408 }
1409
1410 // NOTE: This should only ever be called through os_cleanup(), or when switching video APIs
gr_opengl_shutdown()1411 void gr_opengl_shutdown()
1412 {
1413 if (GL_cursor_pbo) {
1414 vglDeleteBuffersARB(1, &GL_cursor_pbo);
1415 GL_cursor_pbo = 0;
1416 }
1417
1418 if (GL_saved_mouse_data != NULL) {
1419 vm_free(GL_saved_mouse_data);
1420 GL_saved_mouse_data = NULL;
1421 }
1422
1423 opengl_tcache_shutdown();
1424 opengl_light_shutdown();
1425 opengl_tnl_shutdown();
1426 opengl_scene_texture_shutdown();
1427 opengl_post_process_shutdown();
1428 opengl_shader_shutdown();
1429
1430 GL_initted = false;
1431
1432 #ifdef _WIN32
1433 // restore original gamma settings
1434 if (GL_original_gamma_ramp != NULL) {
1435 SetDeviceGammaRamp( GL_device_context, GL_original_gamma_ramp );
1436 }
1437
1438 // swap out our window mode and un-jail the cursor
1439 ShowWindow((HWND)os_get_window(), SW_HIDE);
1440 ClipCursor(NULL);
1441 ChangeDisplaySettings( NULL, 0 );
1442 #else
1443 if (GL_original_gamma_ramp != NULL) {
1444 SDL_SetGammaRamp( GL_original_gamma_ramp, (GL_original_gamma_ramp+256), (GL_original_gamma_ramp+512) );
1445 }
1446 #endif
1447
1448 if (GL_original_gamma_ramp != NULL) {
1449 vm_free(GL_original_gamma_ramp);
1450 GL_original_gamma_ramp = NULL;
1451 }
1452
1453 #ifdef _WIN32
1454 wglMakeCurrent(NULL, NULL);
1455
1456 if (GL_render_context) {
1457 wglDeleteContext(GL_render_context);
1458 GL_render_context = NULL;
1459 }
1460
1461 GL_device_context = NULL;
1462 #endif
1463 }
1464
1465 // NOTE: This should only ever be called through atexit()!!!
opengl_close()1466 void opengl_close()
1467 {
1468 // if ( !GL_initted )
1469 // return;
1470 }
1471
opengl_init_display_device()1472 int opengl_init_display_device()
1473 {
1474 int bpp = gr_screen.bits_per_pixel;
1475
1476 if ( (bpp != 16) && (bpp != 32) ) {
1477 Int3();
1478 return 1;
1479 }
1480
1481
1482 // screen format
1483 switch (bpp) {
1484 case 16: {
1485 Gr_red.bits = 5;
1486 Gr_red.shift = 11;
1487 Gr_red.scale = 8;
1488 Gr_red.mask = 0xF800;
1489
1490 Gr_green.bits = 6;
1491 Gr_green.shift = 5;
1492 Gr_green.scale = 4;
1493 Gr_green.mask = 0x7E0;
1494
1495 Gr_blue.bits = 5;
1496 Gr_blue.shift = 0;
1497 Gr_blue.scale = 8;
1498 Gr_blue.mask = 0x1F;
1499
1500 break;
1501 }
1502
1503 case 32: {
1504 Gr_red.bits = 8;
1505 Gr_red.shift = 16;
1506 Gr_red.scale = 1;
1507 Gr_red.mask = 0xff0000;
1508
1509 Gr_green.bits = 8;
1510 Gr_green.shift = 8;
1511 Gr_green.scale = 1;
1512 Gr_green.mask = 0x00ff00;
1513
1514 Gr_blue.bits = 8;
1515 Gr_blue.shift = 0;
1516 Gr_blue.scale = 1;
1517 Gr_blue.mask = 0x0000ff;
1518
1519 Gr_alpha.bits = 8;
1520 Gr_alpha.shift = 24;
1521 Gr_alpha.mask = 0xff000000;
1522 Gr_alpha.scale = 1;
1523
1524 break;
1525 }
1526 }
1527
1528 // texture format
1529 Gr_t_red.bits = 5;
1530 Gr_t_red.mask = 0x7c00;
1531 Gr_t_red.shift = 10;
1532 Gr_t_red.scale = 8;
1533
1534 Gr_t_green.bits = 5;
1535 Gr_t_green.mask = 0x03e0;
1536 Gr_t_green.shift = 5;
1537 Gr_t_green.scale = 8;
1538
1539 Gr_t_blue.bits = 5;
1540 Gr_t_blue.mask = 0x001f;
1541 Gr_t_blue.shift = 0;
1542 Gr_t_blue.scale = 8;
1543
1544 Gr_t_alpha.bits = 1;
1545 Gr_t_alpha.mask = 0x8000;
1546 Gr_t_alpha.scale = 255;
1547 Gr_t_alpha.shift = 15;
1548
1549 // alpha-texture format
1550 Gr_ta_red.bits = 4;
1551 Gr_ta_red.mask = 0x0f00;
1552 Gr_ta_red.shift = 8;
1553 Gr_ta_red.scale = 17;
1554
1555 Gr_ta_green.bits = 4;
1556 Gr_ta_green.mask = 0x00f0;
1557 Gr_ta_green.shift = 4;
1558 Gr_ta_green.scale = 17;
1559
1560 Gr_ta_blue.bits = 4;
1561 Gr_ta_blue.mask = 0x000f;
1562 Gr_ta_blue.shift = 0;
1563 Gr_ta_blue.scale = 17;
1564
1565 Gr_ta_alpha.bits = 4;
1566 Gr_ta_alpha.mask = 0xf000;
1567 Gr_ta_alpha.shift = 12;
1568 Gr_ta_alpha.scale = 17;
1569
1570 // allocate storage for original gamma settings
1571 if ( !Cmdline_no_set_gamma && (GL_original_gamma_ramp == NULL) ) {
1572 GL_original_gamma_ramp = (ushort*) vm_malloc_q( 3 * 256 * sizeof(ushort) );
1573
1574 if (GL_original_gamma_ramp == NULL) {
1575 mprintf((" Unable to allocate memory for gamma ramp! Disabling...\n"));
1576 Cmdline_no_set_gamma = 1;
1577 } else {
1578 // assume identity ramp by default, to be overwritten by true ramp later
1579 for (ushort x = 0; x < 256; x++) {
1580 GL_original_gamma_ramp[x] = GL_original_gamma_ramp[x + 256] = GL_original_gamma_ramp[x + 512] = (x << 8) | x;
1581 }
1582 }
1583 }
1584
1585
1586 // now init the display device
1587 #ifdef _WIN32
1588 int PixelFormat;
1589 HWND wnd = 0;
1590 PIXELFORMATDESCRIPTOR pfd_test;
1591
1592 mprintf((" Initializing WGL...\n"));
1593
1594 memset(&GL_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
1595 memset(&pfd_test, 0, sizeof(PIXELFORMATDESCRIPTOR));
1596
1597 GL_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
1598 GL_pfd.nVersion = 1;
1599 GL_pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
1600 GL_pfd.iPixelType = PFD_TYPE_RGBA;
1601 GL_pfd.cColorBits = (ubyte)bpp;
1602 GL_pfd.cRedBits = (ubyte)Gr_red.bits;
1603 GL_pfd.cGreenBits = (ubyte)Gr_green.bits;
1604 GL_pfd.cBlueBits = (ubyte)Gr_blue.bits;
1605 GL_pfd.cAlphaBits = (bpp == 32) ? (ubyte)Gr_alpha.bits : 0;
1606 GL_pfd.cDepthBits = (bpp == 32) ? 24 : 16;
1607 GL_pfd.cStencilBits = (bpp == 32) ? 8 : 1;
1608
1609 wnd = (HWND)os_get_window();
1610
1611 Assert( wnd != NULL );
1612
1613 extern uint os_get_dc();
1614 GL_device_context = (HDC)os_get_dc();
1615
1616 if ( !GL_device_context ) {
1617 MessageBox(wnd, "Unable to get device context for OpenGL W32!", "error", MB_ICONERROR | MB_OK);
1618 return 1;
1619 }
1620
1621 PixelFormat = ChoosePixelFormat(GL_device_context, &GL_pfd);
1622
1623 if ( !PixelFormat ) {
1624 MessageBox(wnd, "Unable to choose pixel format for OpenGL W32!","error", MB_ICONERROR | MB_OK);
1625 return 1;
1626 } else {
1627 DescribePixelFormat(GL_device_context, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd_test);
1628
1629 // make sure that we are hardware accelerated and not using the generic implementation
1630 if ( !Fred_running && (pfd_test.dwFlags & PFD_GENERIC_FORMAT) && !(pfd_test.dwFlags & PFD_GENERIC_ACCELERATED) ) {
1631 Assert( bpp == 32 );
1632
1633 // if we failed at 32-bit then we are probably a 16-bit desktop, so try and init a 16-bit visual instead
1634 GL_pfd.cAlphaBits = 0;
1635 GL_pfd.cDepthBits = 16;
1636 GL_pfd.cStencilBits = 1;
1637 // NOTE: the bit values for colors should get updated automatically by ChoosePixelFormat()
1638
1639 PixelFormat = ChoosePixelFormat(GL_device_context, &GL_pfd);
1640
1641 if (!PixelFormat) {
1642 MessageBox(wnd, "Unable to choose pixel format for OpenGL W32!","error", MB_ICONERROR | MB_OK);
1643 return 1;
1644 }
1645
1646 // double-check that we are correct now
1647 DescribePixelFormat(GL_device_context, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd_test);
1648
1649 if ( (pfd_test.dwFlags & PFD_GENERIC_FORMAT) && !(pfd_test.dwFlags & PFD_GENERIC_ACCELERATED) ) {
1650 MessageBox(wnd, "Unable to get proper pixel format for OpenGL W32!", "Error", MB_ICONERROR | MB_OK);
1651 return 1;
1652 }
1653 }
1654 }
1655
1656 if ( !SetPixelFormat(GL_device_context, PixelFormat, &GL_pfd) ) {
1657 MessageBox(wnd, "Unable to set pixel format for OpenGL W32!", "error", MB_ICONERROR | MB_OK);
1658 return 1;
1659 }
1660
1661 GL_render_context = wglCreateContext(GL_device_context);
1662 if ( !GL_render_context ) {
1663 MessageBox(wnd, "Unable to create rendering context for OpenGL W32!", "error", MB_ICONERROR | MB_OK);
1664 return 1;
1665 }
1666
1667 if ( !wglMakeCurrent(GL_device_context, GL_render_context) ) {
1668 MessageBox(wnd, "Unable to make current thread for OpenGL W32!", "error", MB_ICONERROR | MB_OK);
1669 return 1;
1670 }
1671
1672 mprintf((" Requested WGL Video values = R: %d, G: %d, B: %d, depth: %d, stencil: %d, double-buffer: %d\n", Gr_red.bits, Gr_green.bits, Gr_blue.bits, GL_pfd.cDepthBits, GL_pfd.cStencilBits, (GL_pfd.dwFlags & PFD_DOUBLEBUFFER) > 0));
1673
1674 // now report back as to what we ended up getting
1675
1676 DescribePixelFormat(GL_device_context, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &GL_pfd);
1677
1678 int r = GL_pfd.cRedBits;
1679 int g = GL_pfd.cGreenBits;
1680 int b = GL_pfd.cBlueBits;
1681 int depth = GL_pfd.cDepthBits;
1682 int stencil = GL_pfd.cStencilBits;
1683 int db = ((GL_pfd.dwFlags & PFD_DOUBLEBUFFER) > 0);
1684
1685 mprintf((" Actual WGL Video values = R: %d, G: %d, B: %d, depth: %d, stencil: %d, double-buffer: %d\n", r, g, b, depth, stencil, db));
1686
1687 // get the default gamma ramp so that we can restore it on close
1688 if (GL_original_gamma_ramp != NULL) {
1689 GetDeviceGammaRamp( GL_device_context, GL_original_gamma_ramp );
1690 }
1691
1692 #else
1693
1694 int flags = SDL_OPENGL;
1695 int r = 0, g = 0, b = 0, depth = 0, stencil = 1, db = 1;
1696
1697 mprintf((" Initializing SDL...\n"));
1698
1699 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
1700 fprintf (stderr, "Couldn't init SDL: %s", SDL_GetError());
1701 return 1;
1702 }
1703
1704 // grab mouse/key unless told otherwise, ignore when we are going fullscreen
1705 if ( (Cmdline_fullscreen_window|| Cmdline_window || os_config_read_uint(NULL, "Fullscreen", 1) == 0) && !Cmdline_no_grab ) {
1706 SDL_WM_GrabInput(SDL_GRAB_ON);
1707 }
1708
1709 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, Gr_red.bits);
1710 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, Gr_green.bits);
1711 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, Gr_blue.bits);
1712 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bpp == 32) ? 24 : 16);
1713 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, (bpp == 32) ? 8 : 1);
1714 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, db);
1715
1716 int fsaa_samples = os_config_read_uint(NULL, "OGL_AntiAliasSamples", 0);
1717
1718 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa_samples == 0) ? 0 : 1);
1719 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fsaa_samples);
1720
1721 // Slight hack to make Mesa advertise S3TC support without libtxc_dxtn
1722 setenv("force_s3tc_enable", "true", 1);
1723
1724 mprintf((" Requested SDL Video values = R: %d, G: %d, B: %d, depth: %d, stencil: %d, double-buffer: %d, FSAA: %d\n", Gr_red.bits, Gr_green.bits, Gr_blue.bits, (bpp == 32) ? 24 : 16, (bpp == 32) ? 8 : 1, db, fsaa_samples));
1725
1726 if (SDL_SetVideoMode(gr_screen.max_w, gr_screen.max_h, bpp, flags) == NULL) {
1727 fprintf (stderr, "Couldn't set video mode: %s", SDL_GetError());
1728 return 1;
1729 }
1730
1731 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
1732 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
1733 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
1734 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
1735 SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &db);
1736 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil);
1737 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fsaa_samples);
1738
1739 mprintf((" Actual SDL Video values = R: %d, G: %d, B: %d, depth: %d, stencil: %d, double-buffer: %d, FSAA: %d\n", r, g, b, depth, stencil, db, fsaa_samples));
1740
1741 SDL_ShowCursor(0);
1742
1743 /* might as well put this here */
1744 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1745
1746 if (GL_original_gamma_ramp != NULL) {
1747 SDL_GetGammaRamp( GL_original_gamma_ramp, (GL_original_gamma_ramp+256), (GL_original_gamma_ramp+512) );
1748 }
1749 #endif
1750
1751 return 0;
1752 }
1753
1754
opengl_setup_function_pointers()1755 void opengl_setup_function_pointers()
1756 {
1757 // *****************************************************************************
1758 // NOTE: All function pointers here should have a Cmdline_nohtl check at the top
1759 // if they shouldn't be run in non-HTL mode, Don't keep separate entries.
1760
1761 gr_screen.gf_flip = gr_opengl_flip;
1762 gr_screen.gf_set_clip = gr_opengl_set_clip;
1763 gr_screen.gf_reset_clip = gr_opengl_reset_clip;
1764
1765 gr_screen.gf_clear = gr_opengl_clear;
1766 // gr_screen.gf_bitmap = gr_opengl_bitmap;
1767 gr_screen.gf_bitmap_ex = gr_opengl_bitmap_ex;
1768 gr_screen.gf_aabitmap = gr_opengl_aabitmap;
1769 gr_screen.gf_aabitmap_ex = gr_opengl_aabitmap_ex;
1770
1771 // gr_screen.gf_rect = gr_opengl_rect;
1772 // gr_screen.gf_shade = gr_opengl_shade;
1773 gr_screen.gf_string = gr_opengl_string;
1774 gr_screen.gf_circle = gr_opengl_circle;
1775 gr_screen.gf_unfilled_circle = gr_opengl_unfilled_circle;
1776 gr_screen.gf_arc = gr_opengl_arc;
1777 gr_screen.gf_curve = gr_opengl_curve;
1778
1779 gr_screen.gf_line = gr_opengl_line;
1780 gr_screen.gf_aaline = gr_opengl_aaline;
1781 gr_screen.gf_pixel = gr_opengl_pixel;
1782 gr_screen.gf_scaler = gr_opengl_scaler;
1783 gr_screen.gf_tmapper = gr_opengl_tmapper;
1784 gr_screen.gf_render = gr_opengl_render;
1785 gr_screen.gf_render_effect = gr_opengl_render_effect;
1786
1787 gr_screen.gf_gradient = gr_opengl_gradient;
1788
1789 gr_screen.gf_set_palette = gr_opengl_set_palette;
1790 gr_screen.gf_print_screen = gr_opengl_print_screen;
1791
1792 gr_screen.gf_fade_in = gr_opengl_fade_in;
1793 gr_screen.gf_fade_out = gr_opengl_fade_out;
1794 gr_screen.gf_flash = gr_opengl_flash;
1795 gr_screen.gf_flash_alpha = gr_opengl_flash_alpha;
1796
1797 gr_screen.gf_zbuffer_get = gr_opengl_zbuffer_get;
1798 gr_screen.gf_zbuffer_set = gr_opengl_zbuffer_set;
1799 gr_screen.gf_zbuffer_clear = gr_opengl_zbuffer_clear;
1800
1801 gr_screen.gf_stencil_set = gr_opengl_stencil_set;
1802 gr_screen.gf_stencil_clear = gr_opengl_stencil_clear;
1803
1804 gr_screen.gf_alpha_mask_set = gr_opengl_alpha_mask_set;
1805
1806 gr_screen.gf_save_screen = gr_opengl_save_screen;
1807 gr_screen.gf_restore_screen = gr_opengl_restore_screen;
1808 gr_screen.gf_free_screen = gr_opengl_free_screen;
1809
1810 gr_screen.gf_dump_frame_start = gr_opengl_dump_frame_start;
1811 gr_screen.gf_dump_frame_stop = gr_opengl_dump_frame_stop;
1812 gr_screen.gf_dump_frame = gr_opengl_dump_frame;
1813
1814 gr_screen.gf_set_gamma = gr_opengl_set_gamma;
1815
1816 gr_screen.gf_fog_set = gr_opengl_fog_set;
1817
1818 // UnknownPlayer : Don't recognize this - MAY NEED DEBUGGING
1819 gr_screen.gf_get_region = gr_opengl_get_region;
1820
1821 // now for the bitmap functions
1822 gr_screen.gf_bm_free_data = gr_opengl_bm_free_data;
1823 gr_screen.gf_bm_create = gr_opengl_bm_create;
1824 gr_screen.gf_bm_init = gr_opengl_bm_init;
1825 gr_screen.gf_bm_load = gr_opengl_bm_load;
1826 gr_screen.gf_bm_page_in_start = gr_opengl_bm_page_in_start;
1827 gr_screen.gf_bm_lock = gr_opengl_bm_lock;
1828 gr_screen.gf_bm_make_render_target = gr_opengl_bm_make_render_target;
1829 gr_screen.gf_bm_set_render_target = gr_opengl_bm_set_render_target;
1830
1831 gr_screen.gf_set_cull = gr_opengl_set_cull;
1832 gr_screen.gf_set_color_buffer = gr_opengl_set_color_buffer;
1833
1834 gr_screen.gf_cross_fade = gr_opengl_cross_fade;
1835
1836 gr_screen.gf_tcache_set = gr_opengl_tcache_set;
1837
1838 gr_screen.gf_set_clear_color = gr_opengl_set_clear_color;
1839
1840 gr_screen.gf_preload = gr_opengl_preload;
1841
1842 gr_screen.gf_push_texture_matrix = gr_opengl_push_texture_matrix;
1843 gr_screen.gf_pop_texture_matrix = gr_opengl_pop_texture_matrix;
1844 gr_screen.gf_translate_texture_matrix = gr_opengl_translate_texture_matrix;
1845
1846 gr_screen.gf_set_texture_addressing = gr_opengl_set_texture_addressing;
1847 gr_screen.gf_zbias = gr_opengl_zbias;
1848 gr_screen.gf_set_fill_mode = gr_opengl_set_fill_mode;
1849 gr_screen.gf_set_texture_panning = gr_opengl_set_texture_panning;
1850
1851 gr_screen.gf_create_buffer = gr_opengl_create_buffer;
1852 gr_screen.gf_config_buffer = gr_opengl_config_buffer;
1853 gr_screen.gf_pack_buffer = gr_opengl_pack_buffer;
1854 gr_screen.gf_destroy_buffer = gr_opengl_destroy_buffer;
1855 gr_screen.gf_render_buffer = gr_opengl_render_buffer;
1856 gr_screen.gf_set_buffer = gr_opengl_set_buffer;
1857
1858 gr_screen.gf_create_stream_buffer = gr_opengl_create_stream_buffer;
1859 gr_screen.gf_update_stream_buffer = gr_opengl_update_stream_buffer;
1860 gr_screen.gf_render_stream_buffer = gr_opengl_render_stream_buffer;
1861 gr_screen.gf_render_stream_buffer_start = gr_opengl_render_stream_buffer_start;
1862 gr_screen.gf_render_stream_buffer_end = gr_opengl_render_stream_buffer_end;
1863
1864 gr_screen.gf_start_instance_matrix = gr_opengl_start_instance_matrix;
1865 gr_screen.gf_end_instance_matrix = gr_opengl_end_instance_matrix;
1866 gr_screen.gf_start_angles_instance_matrix = gr_opengl_start_instance_angles;
1867
1868 gr_screen.gf_make_light = gr_opengl_make_light;
1869 gr_screen.gf_modify_light = gr_opengl_modify_light;
1870 gr_screen.gf_destroy_light = gr_opengl_destroy_light;
1871 gr_screen.gf_set_light = gr_opengl_set_light;
1872 gr_screen.gf_reset_lighting = gr_opengl_reset_lighting;
1873 gr_screen.gf_set_ambient_light = gr_opengl_set_ambient_light;
1874
1875 gr_screen.gf_post_process_set_effect = gr_opengl_post_process_set_effect;
1876 gr_screen.gf_post_process_set_defaults = gr_opengl_post_process_set_defaults;
1877
1878 gr_screen.gf_post_process_begin = gr_opengl_post_process_begin;
1879 gr_screen.gf_post_process_end = gr_opengl_post_process_end;
1880 gr_screen.gf_post_process_save_zbuffer = gr_opengl_post_process_save_zbuffer;
1881
1882 gr_screen.gf_scene_texture_begin = gr_opengl_scene_texture_begin;
1883 gr_screen.gf_scene_texture_end = gr_opengl_scene_texture_end;
1884
1885 gr_screen.gf_start_clip_plane = gr_opengl_start_clip_plane;
1886 gr_screen.gf_end_clip_plane = gr_opengl_end_clip_plane;
1887
1888 gr_screen.gf_lighting = gr_opengl_set_lighting;
1889
1890 gr_screen.gf_set_proj_matrix = gr_opengl_set_projection_matrix;
1891 gr_screen.gf_end_proj_matrix = gr_opengl_end_projection_matrix;
1892
1893 gr_screen.gf_set_view_matrix = gr_opengl_set_view_matrix;
1894 gr_screen.gf_end_view_matrix = gr_opengl_end_view_matrix;
1895
1896 gr_screen.gf_push_scale_matrix = gr_opengl_push_scale_matrix;
1897 gr_screen.gf_pop_scale_matrix = gr_opengl_pop_scale_matrix;
1898 gr_screen.gf_center_alpha = gr_opengl_center_alpha;
1899
1900 gr_screen.gf_setup_background_fog = gr_opengl_setup_background_fog;
1901
1902 gr_screen.gf_start_state_block = gr_opengl_start_state_block;
1903 gr_screen.gf_end_state_block = gr_opengl_end_state_block;
1904 gr_screen.gf_set_state_block = gr_opengl_set_state_block;
1905
1906 gr_screen.gf_draw_line_list = gr_opengl_draw_line_list;
1907
1908 gr_screen.gf_set_line_width = gr_opengl_set_line_width;
1909
1910 gr_screen.gf_line_htl = gr_opengl_line_htl;
1911 gr_screen.gf_sphere_htl = gr_opengl_sphere_htl;
1912
1913 gr_screen.gf_maybe_create_shader = gr_opengl_maybe_create_shader;
1914
1915 gr_screen.gf_flush_data_states = gr_opengl_flush_data_states;
1916
1917 gr_screen.gf_set_team_color = gr_opengl_set_team_color;
1918 gr_screen.gf_disable_team_color = gr_opengl_disable_team_color;
1919
1920 gr_screen.gf_update_texture = gr_opengl_update_texture;
1921 // NOTE: All function pointers here should have a Cmdline_nohtl check at the top
1922 // if they shouldn't be run in non-HTL mode, Don't keep separate entries.
1923 // *****************************************************************************
1924 }
1925
1926
gr_opengl_init()1927 bool gr_opengl_init()
1928 {
1929 char *ver;
1930 int major = 0, minor = 0;
1931
1932 if ( !GL_initted )
1933 atexit(opengl_close);
1934
1935 if (GL_initted) {
1936 gr_opengl_cleanup();
1937 GL_initted = false;
1938 }
1939
1940 mprintf(( "Initializing OpenGL graphics device at %ix%i with %i-bit color...\n", gr_screen.max_w, gr_screen.max_h, gr_screen.bits_per_pixel ));
1941
1942 if ( opengl_init_display_device() ) {
1943 Error(LOCATION, "Unable to initialize display device!\n");
1944 }
1945
1946 // version check
1947 ver = (char *)glGetString(GL_VERSION);
1948 sscanf(ver, "%d.%d", &major, &minor);
1949
1950 GL_version = (major * 10) + minor;
1951
1952 if (GL_version < MIN_REQUIRED_GL_VERSION) {
1953 Error(LOCATION, "Current GL Version of %d.%d is less than the required version of %d.%d.\nSwitch video modes or update your drivers.", major, minor, (MIN_REQUIRED_GL_VERSION / 10), (MIN_REQUIRED_GL_VERSION % 10));
1954 }
1955
1956 GL_initted = true;
1957
1958 // this MUST be done before any other gr_opengl_* or opengl_* funcion calls!!
1959 opengl_setup_function_pointers();
1960
1961 mprintf(( " OpenGL Vendor : %s\n", glGetString(GL_VENDOR) ));
1962 mprintf(( " OpenGL Renderer : %s\n", glGetString(GL_RENDERER) ));
1963 mprintf(( " OpenGL Version : %s\n", ver ));
1964 mprintf(( "\n" ));
1965
1966 if (Cmdline_fullscreen_window || Cmdline_window) {
1967 opengl_go_windowed();
1968 } else {
1969 opengl_go_fullscreen();
1970 }
1971
1972 // initialize the extensions and make sure we aren't missing something that we need
1973 opengl_extensions_init();
1974
1975 // setup the lighting stuff that will get used later
1976 opengl_light_init();
1977
1978 // init state system (must come AFTER light is set up)
1979 GL_state.init();
1980
1981 GLint max_texture_units = GL_supported_texture_units;
1982
1983 if (Use_GLSL) {
1984 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &max_texture_units);
1985 }
1986
1987 GL_state.Texture.init(max_texture_units);
1988 GL_state.Array.init(max_texture_units);
1989
1990 opengl_set_texture_target();
1991 GL_state.Texture.SetActiveUnit(0);
1992 GL_state.Texture.SetTarget(GL_TEXTURE_2D);
1993 GL_state.Texture.Enable();
1994
1995 // ready the texture system
1996 opengl_tcache_init();
1997
1998 extern void opengl_tnl_init();
1999 opengl_tnl_init();
2000
2001 // setup default shaders, and shader related items
2002 opengl_shader_init();
2003
2004 // post processing effects, after shaders are initialized
2005 opengl_setup_scene_textures();
2006 opengl_post_process_init();
2007
2008 // must be called after extensions are setup
2009 opengl_set_vsync( !Cmdline_no_vsync );
2010
2011
2012 opengl_setup_viewport();
2013
2014 glClear(GL_DEPTH_BUFFER_BIT);
2015 glClear(GL_STENCIL_BUFFER_BIT);
2016
2017 glShadeModel(GL_SMOOTH);
2018
2019 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2020 glHint(GL_FOG_HINT, GL_NICEST);
2021
2022 glDepthRange(0.0, 1.0);
2023
2024 glPixelStorei(GL_PACK_ALIGNMENT, 1);
2025 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2026
2027 glFlush();
2028
2029 Gr_current_red = &Gr_red;
2030 Gr_current_blue = &Gr_blue;
2031 Gr_current_green = &Gr_green;
2032 Gr_current_alpha = &Gr_alpha;
2033
2034 Mouse_hidden++;
2035 gr_opengl_reset_clip();
2036 gr_opengl_clear();
2037 gr_opengl_flip();
2038 gr_opengl_clear();
2039 gr_opengl_flip();
2040 gr_opengl_clear();
2041 Mouse_hidden--;
2042
2043
2044 glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GL_max_elements_vertices);
2045 glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &GL_max_elements_indices);
2046
2047 mprintf(( " Max texture units: %i (%i)\n", GL_supported_texture_units, max_texture_units ));
2048 mprintf(( " Max elements vertices: %i\n", GL_max_elements_vertices ));
2049 mprintf(( " Max elements indices: %i\n", GL_max_elements_indices ));
2050 mprintf(( " Max texture size: %ix%i\n", GL_max_texture_width, GL_max_texture_height ));
2051
2052 if ( Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) ) {
2053 mprintf(( " Max render buffer size: %ix%i\n", GL_max_renderbuffer_size, GL_max_renderbuffer_size ));
2054 }
2055
2056 mprintf(( " Can use compressed textures: %s\n", Use_compressed_textures ? NOX("YES") : NOX("NO") ));
2057 mprintf(( " Texture compression available: %s\n", Texture_compression_available ? NOX("YES") : NOX("NO") ));
2058 mprintf(( " Post-processing enabled: %s\n", (Cmdline_postprocess) ? "YES" : "NO"));
2059 mprintf(( " Using %s texture filter.\n", (GL_mipmap_filter) ? NOX("trilinear") : NOX("bilinear") ));
2060
2061 if (Use_GLSL) {
2062 mprintf(( " OpenGL Shader Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) ));
2063 }
2064
2065
2066
2067 // This stops fred crashing if no textures are set
2068 gr_screen.current_bitmap = -1;
2069
2070 mprintf(("... OpenGL init is complete!\n"));
2071
2072 if (Cmdline_ati_color_swap)
2073 GL_read_format = GL_RGBA;
2074
2075 return true;
2076 }
2077
2078 DCF(ogl_minimize, "Minimizes opengl")
2079 {
2080 if ( gr_screen.mode != GR_OPENGL ) {
2081 dc_printf("Command only available in OpenGL mode.\n");
2082 return;
2083 }
2084
2085 if (Dc_command) {
2086 dc_get_arg(ARG_TRUE);
2087
2088 if ( Dc_arg_type & ARG_TRUE ) {
2089 opengl_minimize();
2090 }
2091 }
2092
2093 if (Dc_help)
2094 dc_printf("If set to true then the OpenGL window will minimize.\n");
2095 }
2096
2097 DCF(ogl_anisotropy, "toggles anisotropic filtering")
2098 {
2099 if ( gr_screen.mode != GR_OPENGL ) {
2100 dc_printf("Can only set anisotropic filter in OpenGL mode.\n");
2101 return;
2102 }
2103
2104 if ( Dc_command && !Is_Extension_Enabled(OGL_EXT_TEXTURE_FILTER_ANISOTROPIC) ) {
2105 dc_printf("Error: Anisotropic filter is not settable!\n");
2106 return;
2107 }
2108
2109 if ( Dc_command ) {
2110 dc_get_arg(ARG_INT | ARG_NONE);
2111
2112 if ( Dc_arg_type & ARG_NONE ) {
2113 GL_anisotropy = 1.0f;
2114 // opengl_set_anisotropy();
2115 dc_printf("Anisotropic filter value reset to default level.\n");
2116 }
2117
2118 if ( Dc_arg_type & ARG_INT ) {
2119 GL_anisotropy = (GLfloat)Dc_arg_float;
2120 // opengl_set_anisotropy( (float)Dc_arg_float );
2121 }
2122 }
2123
2124 if ( Dc_status ) {
2125 dc_printf("Current anisotropic filter value is %i\n", (int)GL_anisotropy);
2126 }
2127
2128 if (Dc_help) {
2129 dc_printf("Sets OpenGL anisotropic filtering level.\n");
2130 dc_printf("Valid values are 1 to %i, or 0 to turn off.\n", (int)opengl_get_max_anisotropy());
2131 }
2132 }
2133