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