2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 #include "gropengl1.h"
11 #include "gropenglinternal.h"
17 #include "grinternal.h"
22 static int Inited = 0;
25 volatile int GL_activate = 0;
26 volatile int GL_deactivate = 0;
28 static GLuint Gr_saved_screen_tex = 0;
30 static int Gr_opengl_mouse_saved = 0;
31 static int Gr_opengl_mouse_saved_x = 0;
32 static int Gr_opengl_mouse_saved_y = 0;
33 static int Gr_opengl_mouse_saved_w = 0;
34 static int Gr_opengl_mouse_saved_h = 0;
35 static ubyte *Gr_opengl_mouse_saved_data = NULL;
37 #define CLAMP(x,r1,r2) do { if ( (x) < (r1) ) (x) = (r1); else if ((x) > (r2)) (x) = (r2); } while(0)
40 PFNGLSECONDARYCOLORPOINTEREXTPROC vglSecondaryColorPointerEXT = NULL;
43 static gr_alpha_blend GL_current_alpha_blend = (gr_alpha_blend) -1;
44 static gr_zbuffer_type GL_current_zbuffer_type = (gr_zbuffer_type) -1;
46 void opengl1_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
48 opengl1_set_texture_state(ts);
50 if (ab != GL_current_alpha_blend) {
52 case ALPHA_BLEND_NONE: // 1*SrcPixel + 0*DestPixel
53 glBlendFunc(GL_ONE, GL_ZERO);
55 case ALPHA_BLEND_ADDITIVE: // 1*SrcPixel + 1*DestPixel
56 glBlendFunc(GL_ONE, GL_ONE);
58 case ALPHA_BLEND_ALPHA_ADDITIVE: // Alpha*SrcPixel + 1*DestPixel
59 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
61 case ALPHA_BLEND_ALPHA_BLEND_ALPHA: // Alpha*SrcPixel + (1-Alpha)*DestPixel
62 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
64 case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR: // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
65 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
71 GL_current_alpha_blend = ab;
74 if (zt != GL_current_zbuffer_type) {
76 case ZBUFFER_TYPE_NONE:
77 glDepthFunc(GL_ALWAYS);
78 glDepthMask(GL_FALSE);
80 case ZBUFFER_TYPE_READ:
82 glDepthMask(GL_FALSE);
84 case ZBUFFER_TYPE_WRITE:
85 glDepthFunc(GL_ALWAYS);
88 case ZBUFFER_TYPE_FULL:
96 GL_current_zbuffer_type = zt;
100 void gr_opengl1_activate(int active)
105 // don't grab key/mouse if cmdline says so or if we're fullscreen
106 // if(!Cmdline_no_grab && !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN)) {
107 // SDL_WM_GrabInput(SDL_GRAB_ON);
112 // let go of mouse/keyboard
113 // SDL_WM_GrabInput(SDL_GRAB_OFF);
117 void gr_opengl1_clear()
119 glClearColor(gr_screen.current_clear_color.red / 255.0,
120 gr_screen.current_clear_color.green / 255.0,
121 gr_screen.current_clear_color.blue / 255.0, 1.0);
123 glClear ( GL_COLOR_BUFFER_BIT );
126 void gr_opengl1_flip()
134 Gr_opengl_mouse_saved = 0;
136 if ( mouse_is_visible() ) {
140 mouse_get_pos( &mx, &my );
142 gr_opengl1_save_mouse_area(mx,my,32,32);
144 if (Gr_cursor == -1) {
146 gr_set_color(255,255,255);
147 gr_line(mx, my, mx+7, my + 7);
148 gr_line(mx, my, mx+5, my );
149 gr_line(mx, my, mx, my+5);
152 gr_set_bitmap(Gr_cursor);
158 GLenum error = GL_NO_ERROR;
161 error = glGetError();
163 if (error != GL_NO_ERROR) {
164 nprintf(("Warning", "!!DEBUG!! OpenGL Error: %d (%d this frame)\n", error, ic));
168 } while (error != GL_NO_ERROR);
171 SDL_GL_SwapWindow(GL_window);
173 opengl1_tcache_frame();
175 int cnt = GL_activate;
178 opengl1_tcache_flush();
179 // gr_opengl_clip_cursor(1); /* mouse grab, see opengl_activate */
185 // gr_opengl_clip_cursor(0); /* mouse grab, see opengl_activate */
189 void gr_opengl1_set_clip(int x,int y,int w,int h)
191 // check for sanity of parameters
197 if (x >= gr_screen.max_w)
198 x = gr_screen.max_w - 1;
199 if (y >= gr_screen.max_h)
200 y = gr_screen.max_h - 1;
202 if (x + w > gr_screen.max_w)
203 w = gr_screen.max_w - x;
204 if (y + h > gr_screen.max_h)
205 h = gr_screen.max_h - y;
207 if (w > gr_screen.max_w)
209 if (h > gr_screen.max_h)
212 gr_screen.offset_x = x;
213 gr_screen.offset_y = y;
214 gr_screen.clip_left = 0;
215 gr_screen.clip_right = w-1;
216 gr_screen.clip_top = 0;
217 gr_screen.clip_bottom = h-1;
218 gr_screen.clip_width = w;
219 gr_screen.clip_height = h;
221 x = fl2i((x * GL_viewport_scale_w) + 0.5f) + GL_viewport_x;
222 y = fl2i((y * GL_viewport_scale_h) + 0.5f) + GL_viewport_y;
223 w = fl2i((w * GL_viewport_scale_w) + 0.5f);
224 h = fl2i((h * GL_viewport_scale_h) + 0.5f);
226 glEnable(GL_SCISSOR_TEST);
227 glScissor(x, GL_viewport_h-y-h, w, h);
230 void gr_opengl1_reset_clip()
232 gr_screen.offset_x = 0;
233 gr_screen.offset_y = 0;
234 gr_screen.clip_left = 0;
235 gr_screen.clip_top = 0;
236 gr_screen.clip_right = gr_screen.max_w - 1;
237 gr_screen.clip_bottom = gr_screen.max_h - 1;
238 gr_screen.clip_width = gr_screen.max_w;
239 gr_screen.clip_height = gr_screen.max_h;
241 glDisable(GL_SCISSOR_TEST);
242 // glScissor(0, 0, gr_screen.max_w, gr_screen.max_h);
246 void gr_opengl1_set_palette(ubyte *new_palette, int is_alphacolor)
251 void gr_opengl1_print_screen(const char *filename)
253 char tmp[MAX_FILENAME_LEN];
256 strcpy( tmp, filename );
257 strcat( tmp, NOX(".tga"));
259 buf = (ubyte*)malloc(GL_viewport_w * GL_viewport_h * 3);
265 CFILE *f = cfopen(tmp, "wb", CFILE_NORMAL, CF_TYPE_ROOT);
272 // Write the TGA header
273 cfwrite_ubyte( 0, f ); // IDLength;
274 cfwrite_ubyte( 0, f ); // ColorMapType;
275 cfwrite_ubyte( 2, f ); // ImageType; // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
276 cfwrite_ushort( 0, f ); // CMapStart;
277 cfwrite_ushort( 0, f ); // CMapLength;
278 cfwrite_ubyte( 0, f ); // CMapDepth;
279 cfwrite_ushort( 0, f ); // XOffset;
280 cfwrite_ushort( 0, f ); // YOffset;
281 cfwrite_ushort( (ushort)GL_viewport_w, f ); // Width;
282 cfwrite_ushort( (ushort)GL_viewport_h, f ); // Height;
283 cfwrite_ubyte( 24, f ); //PixelDepth;
284 cfwrite_ubyte( 0, f ); //ImageDesc;
286 memset(buf, 0, GL_viewport_w * GL_viewport_h * 3);
288 glReadPixels(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h, GL_BGR, GL_UNSIGNED_BYTE, buf);
290 cfwrite(buf, GL_viewport_w * GL_viewport_h * 3, 1, f);
297 int gr_opengl1_supports_res_ingame(int res)
302 int gr_opengl1_supports_res_interface(int res)
307 void opengl1_cleanup()
309 if ( !Inited ) return;
316 opengl1_tcache_cleanup();
321 void gr_opengl1_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
323 Assert((r >= 0) && (r < 256));
324 Assert((g >= 0) && (g < 256));
325 Assert((b >= 0) && (b < 256));
327 if (fog_mode == GR_FOGMODE_NONE) {
328 if (gr_screen.current_fog_mode != fog_mode) {
331 if (OGL_fog_mode == 1) {
332 glDisable(GL_COLOR_SUM);
336 gr_screen.current_fog_mode = fog_mode;
341 if (gr_screen.current_fog_mode != fog_mode) {
344 if (OGL_fog_mode == 1) {
345 glEnable(GL_COLOR_SUM);
346 } else if (OGL_fog_mode == 2) {
347 glFogi(GL_FOG_MODE, GL_LINEAR);
350 gr_screen.current_fog_mode = fog_mode;
353 if ( (gr_screen.current_fog_color.red != r) ||
354 (gr_screen.current_fog_color.green != g) ||
355 (gr_screen.current_fog_color.blue != b) ) {
358 gr_opengl_init_color( &gr_screen.current_fog_color, r, g, b );
360 fc[0] = (float)r/255.0;
361 fc[1] = (float)g/255.0;
362 fc[2] = (float)b/255.0;
365 glFogfv(GL_FOG_COLOR, fc);
368 if( (fog_near >= 0.0f) && (fog_far >= 0.0f) &&
369 ((fog_near != gr_screen.fog_near) ||
370 (fog_far != gr_screen.fog_far)) ) {
371 gr_screen.fog_near = fog_near;
372 gr_screen.fog_far = fog_far;
374 if (OGL_fog_mode == 2) {
375 glFogf(GL_FOG_START, fog_near);
376 glFogf(GL_FOG_END, fog_far);
381 void gr_opengl1_get_pixel(int x, int y, int *r, int *g, int *b)
386 void gr_opengl1_set_cull(int cull)
389 glEnable (GL_CULL_FACE);
390 glFrontFace (GL_CCW);
392 glDisable (GL_CULL_FACE);
396 void gr_opengl1_filter_set(int filter)
401 void gr_opengl1_zbuffer_clear(int mode)
405 gr_zbuffering_mode = GR_ZBUFF_FULL;
406 gr_global_zbuffering = 1;
408 opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL );
409 glClear ( GL_DEPTH_BUFFER_BIT );
412 gr_zbuffering_mode = GR_ZBUFF_NONE;
413 gr_global_zbuffering = 0;
417 void gr_opengl1_fade_in(int instantaneous)
422 void gr_opengl1_fade_out(int instantaneous)
427 void gr_opengl1_get_region(int front, int w, int h, ubyte *data)
430 glReadBuffer(GL_FRONT);
432 glReadBuffer(GL_BACK);
435 opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
437 glPixelStorei(GL_UNPACK_ROW_LENGTH, GL_viewport_w);
439 int x = GL_viewport_x;
440 int y = (GL_viewport_y+GL_viewport_h)-h-1;
442 if (gr_screen.bytes_per_pixel == 2) {
443 glReadPixels(x, y, w, h, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, data);
444 } else if (gr_screen.bytes_per_pixel == 4) {
445 glReadPixels(x, y, w, h, GL_BGRA, GL_UNSIGNED_BYTE, data);
448 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
451 void gr_opengl1_save_mouse_area(int x, int y, int w, int h)
455 w = fl2i((w * GL_viewport_scale_w) + 0.5f);
456 h = fl2i((h * GL_viewport_scale_h) + 0.5f);
463 CLAMP(x1, 0, GL_viewport_w);
464 CLAMP(x2, 0, GL_viewport_w);
465 CLAMP(y1, 0, GL_viewport_h);
466 CLAMP(y2, 0, GL_viewport_h);
468 Gr_opengl_mouse_saved_x = x1;
469 Gr_opengl_mouse_saved_y = y1;
470 Gr_opengl_mouse_saved_w = x2 - x1 + 1;
471 Gr_opengl_mouse_saved_h = y2 - y1 + 1;
473 if ( (Gr_opengl_mouse_saved_w < 1) || (Gr_opengl_mouse_saved_h < 1) ) {
477 if (Gr_opengl_mouse_saved_data == NULL) {
478 Gr_opengl_mouse_saved_data = (ubyte*)malloc(w * h * gr_screen.bytes_per_pixel);
480 if ( !Gr_opengl_mouse_saved_data ) {
485 opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
487 x1 = GL_viewport_x+Gr_opengl_mouse_saved_x;
488 y1 = (GL_viewport_y+GL_viewport_h)-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
490 glReadBuffer(GL_BACK);
491 glReadPixels(x1, y1, Gr_opengl_mouse_saved_w, Gr_opengl_mouse_saved_h,
492 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, Gr_opengl_mouse_saved_data);
494 Gr_opengl_mouse_saved = 1;
497 int gr_opengl1_save_screen()
501 if (Gr_saved_screen_tex) {
502 mprintf(( "Screen already saved!\n" ));
506 glGenTextures(1, &Gr_saved_screen_tex);
508 if ( !Gr_saved_screen_tex ) {
509 mprintf(( "Couldn't create texture for saved screen!\n" ));
513 opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
515 glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
520 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
521 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
523 glReadBuffer(GL_FRONT);
524 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_viewport_x, GL_viewport_y,
525 GL_viewport_w, GL_viewport_h, 0);
527 if (Gr_opengl_mouse_saved) {
528 int x = Gr_opengl_mouse_saved_x;
529 int y = GL_viewport_h-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
531 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, Gr_opengl_mouse_saved_w,
532 Gr_opengl_mouse_saved_h, GL_BGRA, GL_UNSIGNED_BYTE,
533 Gr_opengl_mouse_saved_data);
536 glBindTexture(GL_TEXTURE_2D, 0);
541 void gr_opengl1_restore_screen(int id)
545 if ( !Gr_saved_screen_tex ) {
550 glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
552 if (Gr_opengl_mouse_saved) {
553 int x = Gr_opengl_mouse_saved_x;
554 int y = GL_viewport_h-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
556 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, Gr_opengl_mouse_saved_w,
557 Gr_opengl_mouse_saved_h, GL_BGRA, GL_UNSIGNED_BYTE,
558 Gr_opengl_mouse_saved_data);
561 glMatrixMode(GL_MODELVIEW);
564 glScalef(1.0f, -1.0f, 1.0f);
566 int tex_coord[] = { 0, 0, 0, 1, 1, 1, 1, 0 };
567 int ver_coord[] = { GL_viewport_x, GL_viewport_y, GL_viewport_x,
568 GL_viewport_h, GL_viewport_w, GL_viewport_h, GL_viewport_w,
572 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
573 glEnableClientState(GL_VERTEX_ARRAY);
575 glTexCoordPointer(2, GL_INT, 0, &tex_coord);
576 glVertexPointer(2, GL_INT, 0, &ver_coord);
578 glDrawArrays(GL_QUADS, 0, 4);
580 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
581 glDisableClientState(GL_VERTEX_ARRAY);
585 glBindTexture(GL_TEXTURE_2D, 0);
588 void gr_opengl1_free_screen(int id)
590 if (Gr_saved_screen_tex) {
591 glDeleteTextures(1, &Gr_saved_screen_tex);
592 Gr_saved_screen_tex = 0;
596 void gr_opengl1_dump_frame_start(int first_frame, int frames_between_dumps)
601 void gr_opengl1_dump_frame_stop()
606 void gr_opengl1_dump_frame()
611 uint gr_opengl1_lock()
618 void gr_opengl1_unlock()
622 void gr_opengl1_zbias(int bias)
625 glEnable(GL_POLYGON_OFFSET_FILL);
626 glPolygonOffset(0.0, -bias);
628 glDisable(GL_POLYGON_OFFSET_FILL);
632 void opengl1_init_func_pointers()
634 gr_screen.gf_flip = gr_opengl1_flip;
635 gr_screen.gf_set_clip = gr_opengl1_set_clip;
636 gr_screen.gf_reset_clip = gr_opengl1_reset_clip;
637 gr_screen.gf_set_font = grx_set_font;
639 gr_screen.gf_set_color = gr_opengl_set_color;
640 gr_screen.gf_set_bitmap = gr_opengl_set_bitmap;
641 gr_screen.gf_create_shader = gr_opengl_create_shader;
642 gr_screen.gf_set_shader = gr_opengl_set_shader;
643 gr_screen.gf_clear = gr_opengl1_clear;
645 gr_screen.gf_aabitmap = gr_opengl1_aabitmap;
646 gr_screen.gf_aabitmap_ex = gr_opengl1_aabitmap_ex;
648 gr_screen.gf_rect = gr_opengl1_rect;
649 gr_screen.gf_shade = gr_opengl1_shade;
650 gr_screen.gf_string = gr_opengl1_string;
651 gr_screen.gf_circle = gr_opengl1_circle;
653 gr_screen.gf_line = gr_opengl1_line;
654 gr_screen.gf_aaline = gr_opengl1_aaline;
655 gr_screen.gf_pixel = gr_opengl1_pixel;
656 gr_screen.gf_scaler = gr_opengl1_scaler;
657 gr_screen.gf_tmapper = gr_opengl1_tmapper;
659 gr_screen.gf_gradient = gr_opengl1_gradient;
661 gr_screen.gf_set_palette = gr_opengl1_set_palette;
662 gr_screen.gf_get_color = gr_opengl_get_color;
663 gr_screen.gf_init_color = gr_opengl_init_color;
664 gr_screen.gf_init_alphacolor = gr_opengl_init_alphacolor;
665 gr_screen.gf_set_color_fast = gr_opengl_set_color_fast;
666 gr_screen.gf_print_screen = gr_opengl1_print_screen;
668 gr_screen.gf_fade_in = gr_opengl1_fade_in;
669 gr_screen.gf_fade_out = gr_opengl1_fade_out;
670 gr_screen.gf_flash = gr_opengl1_flash;
672 gr_screen.gf_zbuffer_get = gr_opengl_zbuffer_get;
673 gr_screen.gf_zbuffer_set = gr_opengl_zbuffer_set;
674 gr_screen.gf_zbuffer_clear = gr_opengl1_zbuffer_clear;
676 gr_screen.gf_save_screen = gr_opengl1_save_screen;
677 gr_screen.gf_restore_screen = gr_opengl1_restore_screen;
678 gr_screen.gf_free_screen = gr_opengl1_free_screen;
680 gr_screen.gf_dump_frame_start = gr_opengl1_dump_frame_start;
681 gr_screen.gf_dump_frame_stop = gr_opengl1_dump_frame_stop;
682 gr_screen.gf_dump_frame = gr_opengl1_dump_frame;
684 gr_screen.gf_set_gamma = gr_opengl1_set_gamma;
686 gr_screen.gf_lock = gr_opengl1_lock;
687 gr_screen.gf_unlock = gr_opengl1_unlock;
689 gr_screen.gf_fog_set = gr_opengl1_fog_set;
691 gr_screen.gf_get_region = gr_opengl1_get_region;
693 gr_screen.gf_get_pixel = gr_opengl1_get_pixel;
695 gr_screen.gf_set_cull = gr_opengl1_set_cull;
697 gr_screen.gf_cross_fade = gr_opengl1_cross_fade;
699 gr_screen.gf_filter_set = gr_opengl1_filter_set;
701 gr_screen.gf_set_clear_color = gr_opengl_set_clear_color;
703 gr_screen.gf_preload_init = gr_opengl1_preload_init;
704 gr_screen.gf_preload = gr_opengl1_preload;
706 gr_screen.gf_zbias = gr_opengl1_zbias;
708 gr_screen.gf_force_windowed = gr_opengl_force_windowed;
709 gr_screen.gf_force_fullscreen = gr_opengl_force_fullscreen;
711 gr_screen.gf_activate = gr_opengl1_activate;
722 1 = use secondary color ext
723 2 = use opengl linear fog
727 if ( SDL_GL_ExtensionSupported("GL_EXT_secondary_color") ) {
728 vglSecondaryColorPointerEXT = (PFNGLSECONDARYCOLORPOINTEREXTPROC)SDL_GL_GetProcAddress("glSecondaryColorPointerEXT");
729 Assert( vglSecondaryColorPointerEXT != NULL );
731 mprintf((" Using extension: GL_EXT_secondary_color\n"));
736 glShadeModel(GL_SMOOTH);
738 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
739 glHint(GL_FOG_HINT, GL_NICEST);
741 glEnable(GL_DEPTH_TEST);
744 glEnable(GL_TEXTURE_2D);
746 glDepthRange(0.0, 1.0);
748 glPixelStorei(GL_PACK_ALIGNMENT, 1);
749 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
754 Bm_pixel_format = BM_PIXEL_FORMAT_ARGB;
757 opengl1_init_func_pointers();
758 opengl1_tcache_init(1);