]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl1.cpp
remove some debugging code
[taylor/freespace2.git] / src / graphics / grgl1.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "gropengl.h"
10 #include "grgl1.h"
11 #include "gropenglinternal.h"
12 #include "2d.h"
13 #include "mouse.h"
14 #include "pstypes.h"
15 #include "cfile.h"
16 #include "bmpman.h"
17 #include "grinternal.h"
18
19
20 int OGL_fog_mode = 0;
21
22 int GL_one_inited = 0;
23
24
25 volatile int GL_activate = 0;
26 volatile int GL_deactivate = 0;
27
28 static GLuint Gr_saved_screen_tex = 0;
29
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;
36
37
38 PFNGLSECONDARYCOLORPOINTERPROC vglSecondaryColorPointer = NULL;
39
40
41 static gr_alpha_blend GL_current_alpha_blend = (gr_alpha_blend) -1;
42 static gr_zbuffer_type GL_current_zbuffer_type = (gr_zbuffer_type) -1;
43
44 void opengl1_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
45 {
46         opengl1_set_texture_state(ts);
47
48         if (ab != GL_current_alpha_blend) {
49                 switch (ab) {
50                         case ALPHA_BLEND_NONE:                  // 1*SrcPixel + 0*DestPixel
51                                 glBlendFunc(GL_ONE, GL_ZERO);
52                                 break;
53                         case ALPHA_BLEND_ADDITIVE:              // 1*SrcPixel + 1*DestPixel
54                                 glBlendFunc(GL_ONE, GL_ONE);
55                                 break;
56                         case ALPHA_BLEND_ALPHA_ADDITIVE:        // Alpha*SrcPixel + 1*DestPixel
57                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
58                                 break;
59                         case ALPHA_BLEND_ALPHA_BLEND_ALPHA:     // Alpha*SrcPixel + (1-Alpha)*DestPixel
60                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
61                                 break;
62                         case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR: // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
63                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
64                                 break;
65                         default:
66                                 break;
67                 }
68
69                 GL_current_alpha_blend = ab;
70         }
71
72         if (zt != GL_current_zbuffer_type) {
73                 switch (zt) {
74                         case ZBUFFER_TYPE_NONE:
75                                 glDepthFunc(GL_ALWAYS);
76                                 glDepthMask(GL_FALSE);
77                                 break;
78                         case ZBUFFER_TYPE_READ:
79                                 glDepthFunc(GL_LESS);
80                                 glDepthMask(GL_FALSE);
81                                 break;
82                         case ZBUFFER_TYPE_WRITE:
83                                 glDepthFunc(GL_ALWAYS);
84                                 glDepthMask(GL_TRUE);
85                                 break;
86                         case ZBUFFER_TYPE_FULL:
87                                 glDepthFunc(GL_LESS);
88                                 glDepthMask(GL_TRUE);
89                                 break;
90                         default:
91                                 break;
92                 }
93
94                 GL_current_zbuffer_type = zt;
95         }
96 }
97
98 void opengl1_cleanup()
99 {
100         if ( !GL_one_inited ) {
101                 return;
102         }
103
104         gr_opengl1_reset_clip();
105         gr_opengl1_clear();
106         gr_opengl1_flip();
107
108         gr_opengl1_free_screen(0);
109
110         if (Gr_opengl_mouse_saved_data) {
111                 free(Gr_opengl_mouse_saved_data);
112                 Gr_opengl_mouse_saved_data = NULL;
113         }
114
115         opengl1_tcache_cleanup();
116
117         GL_one_inited = 0;
118 }
119
120 static void opengl1_init_func_pointers()
121 {
122         gr_screen.gf_flip = gr_opengl1_flip;
123         gr_screen.gf_set_clip = gr_opengl1_set_clip;
124         gr_screen.gf_reset_clip = gr_opengl1_reset_clip;
125
126         gr_screen.gf_clear = gr_opengl1_clear;
127
128         gr_screen.gf_aabitmap = gr_opengl1_aabitmap;
129         gr_screen.gf_aabitmap_ex = gr_opengl1_aabitmap_ex;
130
131         gr_screen.gf_rect = gr_opengl1_rect;
132         gr_screen.gf_shade = gr_opengl1_shade;
133         gr_screen.gf_string = gr_opengl1_string;
134         gr_screen.gf_circle = gr_opengl1_circle;
135
136         gr_screen.gf_line = gr_opengl1_line;
137         gr_screen.gf_aaline = gr_opengl1_aaline;
138         gr_screen.gf_pixel = gr_opengl1_pixel;
139         gr_screen.gf_scaler = gr_opengl1_scaler;
140         gr_screen.gf_tmapper = gr_opengl1_tmapper;
141
142         gr_screen.gf_gradient = gr_opengl1_gradient;
143
144         gr_screen.gf_print_screen = gr_opengl1_print_screen;
145
146         gr_screen.gf_fade_in = gr_opengl1_fade_in;
147         gr_screen.gf_fade_out = gr_opengl1_fade_out;
148         gr_screen.gf_flash = gr_opengl1_flash;
149
150         gr_screen.gf_zbuffer_clear = gr_opengl1_zbuffer_clear;
151
152         gr_screen.gf_save_screen = gr_opengl1_save_screen;
153         gr_screen.gf_restore_screen = gr_opengl1_restore_screen;
154         gr_screen.gf_free_screen = gr_opengl1_free_screen;
155
156         gr_screen.gf_dump_frame_start = gr_opengl1_dump_frame_start;
157         gr_screen.gf_dump_frame_stop = gr_opengl1_dump_frame_stop;
158         gr_screen.gf_dump_frame = gr_opengl1_dump_frame;
159
160         gr_screen.gf_set_gamma = gr_opengl1_set_gamma;
161
162         gr_screen.gf_lock = gr_opengl1_lock;
163         gr_screen.gf_unlock = gr_opengl1_unlock;
164
165         gr_screen.gf_fog_set = gr_opengl1_fog_set;
166
167         gr_screen.gf_get_region = gr_opengl1_get_region;
168
169         gr_screen.gf_set_cull = gr_opengl1_set_cull;
170
171         gr_screen.gf_cross_fade = gr_opengl1_cross_fade;
172
173         gr_screen.gf_preload_init = gr_opengl1_preload_init;
174         gr_screen.gf_preload = gr_opengl1_preload;
175
176         gr_screen.gf_zbias = gr_opengl1_zbias;
177
178         gr_screen.gf_force_windowed = gr_opengl_force_windowed;
179         gr_screen.gf_force_fullscreen = gr_opengl_force_fullscreen;
180         gr_screen.gf_toggle_fullscreen = gr_opengl_toggle_fullscreen;
181
182         gr_screen.gf_set_viewport = gr_opengl1_set_viewport;
183
184         gr_screen.gf_activate = gr_opengl1_activate;
185
186         gr_screen.gf_release_texture = gr_opengl1_release_texture;
187 }
188
189 void opengl1_init()
190 {
191         if (GL_one_inited) {
192                 return;
193         }
194
195         /*
196           1 = use secondary color ext
197           2 = use opengl linear fog
198          */
199         OGL_fog_mode = 2;
200
201         // only available with OpenGL 1.2+, must get ptr for Windows
202         vglSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)SDL_GL_GetProcAddress("glSecondaryColorPointer");
203
204         if (vglSecondaryColorPointer) {
205                 OGL_fog_mode = 1;
206         }
207
208         mprintf(("  Fog mode : %s\n", (OGL_fog_mode == 1) ? "secondary color" : "linear"));
209
210         glShadeModel(GL_SMOOTH);
211         glEnable(GL_DITHER);
212         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
213         glHint(GL_FOG_HINT, GL_NICEST);
214
215         glEnable(GL_DEPTH_TEST);
216         glEnable(GL_BLEND);
217
218         glEnable(GL_TEXTURE_2D);
219
220         glDepthRange(0.0, 1.0);
221
222         glPixelStorei(GL_PACK_ALIGNMENT, 1);
223         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
224
225         glFlush();
226
227         opengl1_init_func_pointers();
228         opengl1_tcache_init();
229
230         gr_opengl1_clear();
231         gr_opengl1_set_cull(1);
232
233         GL_one_inited = 1;
234 }
235
236 void gr_opengl1_activate(int active)
237 {
238         if (active) {
239                 GL_activate++;
240
241                 // don't grab key/mouse if cmdline says so or if we're fullscreen
242         //      if(!Cmdline_no_grab && !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN)) {
243         //              SDL_WM_GrabInput(SDL_GRAB_ON);
244         //      }
245         } else {
246                 GL_deactivate++;
247
248                 // let go of mouse/keyboard
249         //      SDL_WM_GrabInput(SDL_GRAB_OFF);
250         }
251 }
252
253 void gr_opengl1_clear()
254 {
255         glClearColor(gr_screen.current_clear_color.red / 255.0f,
256                 gr_screen.current_clear_color.green / 255.0f,
257                 gr_screen.current_clear_color.blue / 255.0f, 1.0f);
258
259         glClear( GL_COLOR_BUFFER_BIT );
260 }
261
262 void gr_opengl1_flip()
263 {
264         if ( !GL_one_inited ) {
265                 return;
266         }
267
268         gr_reset_clip();
269
270         mouse_eval_deltas();
271
272         Gr_opengl_mouse_saved = 0;
273
274         if ( mouse_is_visible() )       {
275                 int mx, my;
276
277                 gr_reset_clip();
278                 mouse_get_pos( &mx, &my );
279
280                 gr_opengl1_save_mouse_area(mx,my,32,32);
281
282                 if (Gr_cursor == -1) {
283 #ifndef NDEBUG
284                         gr_set_color(255,255,255);
285                         gr_line(mx, my, mx+7, my + 7);
286                         gr_line(mx, my, mx+5, my );
287                         gr_line(mx, my, mx, my+5);
288 #endif
289                 } else {
290                         gr_set_bitmap(Gr_cursor);
291                         gr_bitmap(mx, my);
292                 }
293          }
294
295 #ifndef NDEBUG
296         GLenum error = GL_NO_ERROR;
297
298         do {
299                 error = glGetError();
300
301                 if (error != GL_NO_ERROR) {
302                         nprintf(("Warning", "!!DEBUG!! OpenGL Error: %d\n", error));
303                 }
304         } while (error != GL_NO_ERROR);
305 #endif
306
307         SDL_GL_SwapWindow(GL_window);
308
309         opengl1_tcache_frame();
310
311         int cnt = GL_activate;
312         if ( cnt )      {
313                 GL_activate-=cnt;
314                 opengl1_tcache_flush();
315                 // gr_opengl_clip_cursor(1); /* mouse grab, see opengl_activate */
316         }
317
318         cnt = GL_deactivate;
319         if ( cnt )      {
320                 GL_deactivate-=cnt;
321                 // gr_opengl_clip_cursor(0);  /* mouse grab, see opengl_activate */
322         }
323 }
324
325 void gr_opengl1_set_clip(int x,int y,int w,int h)
326 {
327         // check for sanity of parameters
328         if (x < 0)
329                 x = 0;
330         if (y < 0)
331                 y = 0;
332
333         if (x >= gr_screen.max_w)
334                 x = gr_screen.max_w - 1;
335         if (y >= gr_screen.max_h)
336                 y = gr_screen.max_h - 1;
337
338         if (x + w > gr_screen.max_w)
339                 w = gr_screen.max_w - x;
340         if (y + h > gr_screen.max_h)
341                 h = gr_screen.max_h - y;
342
343         if (w > gr_screen.max_w)
344                 w = gr_screen.max_w;
345         if (h > gr_screen.max_h)
346                 h = gr_screen.max_h;
347
348         gr_screen.offset_x = x;
349         gr_screen.offset_y = y;
350         gr_screen.clip_left = 0;
351         gr_screen.clip_right = w-1;
352         gr_screen.clip_top = 0;
353         gr_screen.clip_bottom = h-1;
354         gr_screen.clip_width = w;
355         gr_screen.clip_height = h;
356
357         x = fl2i((x * GL_viewport_scale_w) + 0.5f) + GL_viewport_x;
358         y = fl2i((y * GL_viewport_scale_h) + 0.5f) + GL_viewport_y;
359         w = fl2i((w * GL_viewport_scale_w) + 0.5f);
360         h = fl2i((h * GL_viewport_scale_h) + 0.5f);
361
362         glEnable(GL_SCISSOR_TEST);
363         glScissor(x, GL_viewport_h-y-h, w, h);
364 }
365
366 void gr_opengl1_reset_clip()
367 {
368         gr_screen.offset_x = 0;
369         gr_screen.offset_y = 0;
370         gr_screen.clip_left = 0;
371         gr_screen.clip_top = 0;
372         gr_screen.clip_right = gr_screen.max_w - 1;
373         gr_screen.clip_bottom = gr_screen.max_h - 1;
374         gr_screen.clip_width = gr_screen.max_w;
375         gr_screen.clip_height = gr_screen.max_h;
376
377         glDisable(GL_SCISSOR_TEST);
378 }
379
380 void gr_opengl1_print_screen(const char *filename)
381 {
382         char tmp[MAX_FILENAME_LEN];
383         ubyte *buf = NULL;
384
385         SDL_strlcpy( tmp, filename, SDL_arraysize(tmp) );
386         SDL_strlcat( tmp, NOX(".tga"), SDL_arraysize(tmp) );
387
388         buf = (ubyte*)malloc(GL_viewport_w * GL_viewport_h * 3);
389
390         if (buf == NULL) {
391                 return;
392         }
393
394         CFILE *f = cfopen(tmp, "wb", CFILE_NORMAL, CF_TYPE_ROOT);
395
396         if (f == NULL) {
397                 free(buf);
398                 return;
399         }
400
401         // Write the TGA header
402         cfwrite_ubyte( 0, f );  //      IDLength;
403         cfwrite_ubyte( 0, f );  //      ColorMapType;
404         cfwrite_ubyte( 2, f );  //      ImageType;              // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
405         cfwrite_ushort( 0, f ); // CMapStart;
406         cfwrite_ushort( 0, f ); //      CMapLength;
407         cfwrite_ubyte( 0, f );  // CMapDepth;
408         cfwrite_ushort( 0, f ); //      XOffset;
409         cfwrite_ushort( 0, f ); //      YOffset;
410         cfwrite_ushort( (ushort)GL_viewport_w, f );     //      Width;
411         cfwrite_ushort( (ushort)GL_viewport_h, f );     //      Height;
412         cfwrite_ubyte( 24, f ); //PixelDepth;
413         cfwrite_ubyte( 0, f );  //ImageDesc;
414
415         memset(buf, 0, GL_viewport_w * GL_viewport_h * 3);
416
417         glReadPixels(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h, GL_BGR, GL_UNSIGNED_BYTE, buf);
418
419         cfwrite(buf, GL_viewport_w * GL_viewport_h * 3, 1, f);
420
421         cfclose(f);
422
423         free(buf);
424 }
425
426 void gr_opengl1_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
427 {
428         SDL_assert((r >= 0) && (r < 256));
429         SDL_assert((g >= 0) && (g < 256));
430         SDL_assert((b >= 0) && (b < 256));
431
432         if (fog_mode == GR_FOGMODE_NONE) {
433                 if (gr_screen.current_fog_mode != fog_mode) {
434                         glDisable(GL_FOG);
435
436                         if (OGL_fog_mode == 1) {
437                                 glDisable(GL_COLOR_SUM);
438                         }
439                 }
440
441                 gr_screen.current_fog_mode = fog_mode;
442
443                 return;
444         }
445
446         if (gr_screen.current_fog_mode != fog_mode) {
447                 glEnable(GL_FOG);
448
449                 if (OGL_fog_mode == 1) {
450                         glEnable(GL_COLOR_SUM);
451                 } else if (OGL_fog_mode == 2) {
452                         glFogi(GL_FOG_MODE, GL_LINEAR);
453                 }
454
455                 gr_screen.current_fog_mode = fog_mode;
456         }
457
458         if ( (gr_screen.current_fog_color.red != r) ||
459                         (gr_screen.current_fog_color.green != g) ||
460                         (gr_screen.current_fog_color.blue != b) ) {
461                 GLfloat fc[4];
462
463                 gr_init_color( &gr_screen.current_fog_color, r, g, b );
464
465                 fc[0] = r / 255.0f;
466                 fc[1] = g / 255.0f;
467                 fc[2] = b / 255.0f;
468                 fc[3] = 1.0f;
469
470                 glFogfv(GL_FOG_COLOR, fc);
471         }
472
473         if( (fog_near >= 0.0f) && (fog_far >= 0.0f) &&
474                         ((fog_near != gr_screen.fog_near) ||
475                         (fog_far != gr_screen.fog_far)) ) {
476                 gr_screen.fog_near = fog_near;
477                 gr_screen.fog_far = fog_far;
478
479                 if (OGL_fog_mode == 2) {
480                         glFogf(GL_FOG_START, fog_near);
481                         glFogf(GL_FOG_END, fog_far);
482                 }
483         }
484 }
485
486 void gr_opengl1_set_cull(int cull)
487 {
488         if (cull) {
489                 glEnable (GL_CULL_FACE);
490                 glFrontFace (GL_CCW);
491         } else {
492                 glDisable (GL_CULL_FACE);
493         }
494 }
495
496 void gr_opengl1_zbuffer_clear(int mode)
497 {
498         if (mode) {
499                 Gr_zbuffering = 1;
500                 Gr_zbuffering_mode = GR_ZBUFF_FULL;
501                 Gr_global_zbuffering = 1;
502
503                 opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL );
504                 glClear ( GL_DEPTH_BUFFER_BIT );
505         } else {
506                 Gr_zbuffering = 0;
507                 Gr_zbuffering_mode = GR_ZBUFF_NONE;
508                 Gr_global_zbuffering = 0;
509         }
510 }
511
512 void gr_opengl1_fade_in(int instantaneous)
513 {
514         // Empty - DDOI
515 }
516
517 void gr_opengl1_fade_out(int instantaneous)
518 {
519         // Empty - DDOI
520 }
521
522 void gr_opengl1_get_region(int front, int w, int h, ubyte *data)
523 {
524         if (front) {
525                 glReadBuffer(GL_FRONT);
526         } else {
527                 glReadBuffer(GL_BACK);
528         }
529
530         opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
531
532         glPixelStorei(GL_UNPACK_ROW_LENGTH, GL_viewport_w);
533
534         int x = GL_viewport_x;
535         int y = (GL_viewport_y+GL_viewport_h)-h-1;
536
537         GLenum pxtype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
538
539         if (gr_screen.bytes_per_pixel == 4) {
540                 pxtype = GL_UNSIGNED_BYTE;
541         }
542
543         glReadPixels(x, y, w, h, GL_BGRA, pxtype, data);
544
545         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
546 }
547
548 void gr_opengl1_save_mouse_area(int x, int y, int w, int h)
549 {
550         int x1, y1, x2, y2;
551
552         if (Gr_saved_screen_tex) {
553                 // already saved, don't need it again
554                 return;
555         }
556
557         w = fl2i((w * GL_viewport_scale_w) + 0.5f);
558         h = fl2i((h * GL_viewport_scale_h) + 0.5f);
559
560         x1 = x;
561         y1 = y;
562         x2 = x+w-1;
563         y2 = y+h-1;
564
565         CAP(x1, 0, GL_viewport_w);
566         CAP(x2, 0, GL_viewport_w);
567         CAP(y1, 0, GL_viewport_h);
568         CAP(y2, 0, GL_viewport_h);
569
570         Gr_opengl_mouse_saved_x = x1;
571         Gr_opengl_mouse_saved_y = y1;
572         Gr_opengl_mouse_saved_w = x2 - x1 + 1;
573         Gr_opengl_mouse_saved_h = y2 - y1 + 1;
574
575         if ( (Gr_opengl_mouse_saved_w < 1) || (Gr_opengl_mouse_saved_h < 1) ) {
576                 return;
577         }
578
579         if (Gr_opengl_mouse_saved_data == NULL) {
580                 Gr_opengl_mouse_saved_data = (ubyte*)malloc(w * h * 3);
581
582                 if ( !Gr_opengl_mouse_saved_data ) {
583                         return;
584                 }
585         }
586
587         x1 = GL_viewport_x+Gr_opengl_mouse_saved_x;
588         y1 = (GL_viewport_y+GL_viewport_h)-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
589
590         glReadBuffer(GL_BACK);
591
592         glReadPixels(x1, y1, Gr_opengl_mouse_saved_w, Gr_opengl_mouse_saved_h,
593                         GL_BGR, GL_UNSIGNED_BYTE, Gr_opengl_mouse_saved_data);
594
595         Gr_opengl_mouse_saved = 1;
596 }
597
598 int gr_opengl1_save_screen()
599 {
600         gr_reset_clip();
601
602         if (Gr_saved_screen_tex) {
603                 mprintf(( "Screen already saved!\n" ));
604                 return -1;
605         }
606
607         glGenTextures(1, &Gr_saved_screen_tex);
608
609         if ( !Gr_saved_screen_tex ) {
610                 mprintf(( "Couldn't create texture for saved screen!\n" ));
611                 return -1;
612         }
613
614         glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
615
616         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
617         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
618         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
619         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
620         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
621
622         glReadBuffer(GL_FRONT);
623
624         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_viewport_x, GL_viewport_y,
625                         GL_viewport_w, GL_viewport_h, 0);
626
627         if (Gr_opengl_mouse_saved) {
628                 int x = Gr_opengl_mouse_saved_x;
629                 int y = GL_viewport_h-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
630
631                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, Gr_opengl_mouse_saved_w,
632                                 Gr_opengl_mouse_saved_h, GL_BGR, GL_UNSIGNED_BYTE,
633                                 Gr_opengl_mouse_saved_data);
634         }
635
636         glBindTexture(GL_TEXTURE_2D, 0);
637
638         return 0;
639 }
640
641 void gr_opengl1_restore_screen(int)
642 {
643         gr_reset_clip();
644
645         if ( !Gr_saved_screen_tex ) {
646                 gr_clear();
647                 return;
648         }
649
650         int x = 0;
651         int y = 0;
652         int w = fl2i(GL_viewport_w / GL_viewport_scale_w + 0.5f);
653         int h = fl2i(GL_viewport_h / GL_viewport_scale_h + 0.5f);
654
655         const int tex_coord[] = { 0, 1, 0, 0, 1, 1, 1, 0 };     // y-flipped
656         const int ver_coord[] = { x, y, x, h, w, y, w, h };
657
658         glColor4ub(255, 255, 255, 255);
659
660         glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
661
662         opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
663
664         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
665         glEnableClientState(GL_VERTEX_ARRAY);
666
667         glTexCoordPointer(2, GL_INT, 0, &tex_coord);
668         glVertexPointer(2, GL_INT, 0, &ver_coord);
669
670         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
671
672         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
673         glDisableClientState(GL_VERTEX_ARRAY);
674
675         glBindTexture(GL_TEXTURE_2D, 0);
676 }
677
678 void gr_opengl1_free_screen(int)
679 {
680         if (Gr_saved_screen_tex) {
681                 glDeleteTextures(1, &Gr_saved_screen_tex);
682                 Gr_saved_screen_tex = 0;
683         }
684 }
685
686 void gr_opengl1_dump_frame_start(int first_frame, int frames_between_dumps)
687 {
688         STUB_FUNCTION;
689 }
690
691 void gr_opengl1_dump_frame_stop()
692 {
693         STUB_FUNCTION;
694 }
695
696 void gr_opengl1_dump_frame()
697 {
698         STUB_FUNCTION;
699 }
700
701 uint gr_opengl1_lock()
702 {
703         return 1;
704 }
705
706 void gr_opengl1_unlock()
707 {
708 }
709
710 void gr_opengl1_zbias(int bias)
711 {
712         if (bias) {
713                 glEnable(GL_POLYGON_OFFSET_FILL);
714                 glPolygonOffset(0.0f, GLfloat(-bias));
715         } else {
716                 glDisable(GL_POLYGON_OFFSET_FILL);
717         }
718 }
719
720 void gr_opengl1_set_viewport(int width, int height)
721 {
722         int w, h, x, y;
723
724         float ratio = gr_screen.max_w / i2fl(gr_screen.max_h);
725
726         w = width;
727         h = fl2i((width / ratio) + 0.5f);
728
729         if (h > height) {
730                 h = height;
731                 w = fl2i((height * ratio) + 0.5f);
732         }
733
734         x = (width - w) / 2;
735         y = (height - h) / 2;
736
737         GL_viewport_x = x;
738         GL_viewport_y = y;
739         GL_viewport_w = w;
740         GL_viewport_h = h;
741         GL_viewport_scale_w = w / i2fl(gr_screen.max_w);
742         GL_viewport_scale_h = h / i2fl(gr_screen.max_h);
743
744         glViewport(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h);
745
746         glMatrixMode(GL_PROJECTION);
747         glLoadIdentity();
748         glOrtho(0, GL_viewport_w, GL_viewport_h, 0, 0.0, 1.0);
749         glMatrixMode(GL_MODELVIEW);
750         glLoadIdentity();
751         glScalef(GL_viewport_scale_w, GL_viewport_scale_h, 1.0f);
752
753         // free mouse cursor storage, since the size might have changed
754         if (Gr_opengl_mouse_saved_data) {
755                 free(Gr_opengl_mouse_saved_data);
756                 Gr_opengl_mouse_saved_data = NULL;
757         }
758
759         // clear screen once to fix issues with edges on non-4:3
760         gr_opengl1_clear();
761 }