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