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