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, &current_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, &current_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, &current_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