2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
9 #include "SDL_opengles2.h"
12 #include "gropenglinternal.h"
18 #include "grinternal.h"
19 #include "osregistry.h"
23 int GL_two_inited = 0;
25 static GLuint FB_texture = 0;
26 static GLuint FB_id = 0;
27 static GLuint FB_rb_id = 0;
29 static GLuint GL_saved_screen_tex = 0;
30 static GLuint GL_stream_tex = 0;
33 static gr_alpha_blend GL_current_alpha_blend = (gr_alpha_blend) -1;
34 static gr_zbuffer_type GL_current_zbuffer_type = (gr_zbuffer_type) -1;
36 void opengl2_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
38 opengl2_set_texture_state(ts);
40 if (ab != GL_current_alpha_blend) {
42 case ALPHA_BLEND_NONE: // 1*SrcPixel + 0*DestPixel
43 glBlendFunc(GL_ONE, GL_ZERO);
45 case ALPHA_BLEND_ADDITIVE: // 1*SrcPixel + 1*DestPixel
46 glBlendFunc(GL_ONE, GL_ONE);
48 case ALPHA_BLEND_ALPHA_ADDITIVE: // Alpha*SrcPixel + 1*DestPixel
49 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
51 case ALPHA_BLEND_ALPHA_BLEND_ALPHA: // Alpha*SrcPixel + (1-Alpha)*DestPixel
52 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
54 case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR: // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
55 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
61 GL_current_alpha_blend = ab;
64 if (zt != GL_current_zbuffer_type) {
66 case ZBUFFER_TYPE_NONE:
67 glDepthFunc(GL_ALWAYS);
68 glDepthMask(GL_FALSE);
70 case ZBUFFER_TYPE_READ:
72 glDepthMask(GL_FALSE);
74 case ZBUFFER_TYPE_WRITE:
75 glDepthFunc(GL_ALWAYS);
78 case ZBUFFER_TYPE_FULL:
86 GL_current_zbuffer_type = zt;
90 static void opengl2_init_func_pointers()
92 gr_screen.gf_flip = gr_opengl2_flip;
93 gr_screen.gf_set_clip = gr_opengl2_set_clip;
94 gr_screen.gf_reset_clip = gr_opengl_reset_clip;
96 gr_screen.gf_clear = gr_opengl_clear;
98 gr_screen.gf_aabitmap = gr_opengl2_aabitmap;
99 gr_screen.gf_aabitmap_ex = gr_opengl2_aabitmap_ex;
101 gr_screen.gf_rect = gr_opengl2_rect;
102 gr_screen.gf_shade = gr_opengl2_shade;
103 gr_screen.gf_string = gr_opengl2_string;
104 gr_screen.gf_circle = gr_opengl2_circle;
106 gr_screen.gf_line = gr_opengl2_line;
107 gr_screen.gf_aaline = gr_opengl2_aaline;
108 gr_screen.gf_pixel = gr_opengl2_pixel;
109 gr_screen.gf_scaler = gr_opengl2_scaler;
110 gr_screen.gf_tmapper = gr_opengl2_tmapper;
112 gr_screen.gf_gradient = gr_opengl2_gradient;
114 gr_screen.gf_print_screen = gr_opengl2_print_screen;
116 gr_screen.gf_fade_in = gr_opengl2_fade_in;
117 gr_screen.gf_fade_out = gr_opengl2_fade_out;
118 gr_screen.gf_flash = gr_opengl2_flash;
120 gr_screen.gf_zbuffer_clear = gr_opengl2_zbuffer_clear;
122 gr_screen.gf_save_screen = gr_opengl2_save_screen;
123 gr_screen.gf_restore_screen = gr_opengl2_restore_screen;
124 gr_screen.gf_free_screen = gr_opengl2_free_screen;
126 gr_screen.gf_dump_frame_start = gr_opengl2_dump_frame_start;
127 gr_screen.gf_dump_frame_stop = gr_opengl2_dump_frame_stop;
128 gr_screen.gf_dump_frame = gr_opengl2_dump_frame;
130 gr_screen.gf_stream_start = gr_opengl2_stream_start;
131 gr_screen.gf_stream_frame = gr_opengl2_stream_frame;
132 gr_screen.gf_stream_stop = gr_opengl2_stream_stop;
134 gr_screen.gf_set_gamma = gr_opengl2_set_gamma;
136 gr_screen.gf_lock = gr_opengl_lock;
137 gr_screen.gf_unlock = gr_opengl_unlock;
139 gr_screen.gf_fog_set = gr_opengl2_fog_set;
141 gr_screen.gf_get_region = gr_opengl2_get_region;
143 gr_screen.gf_set_cull = gr_opengl_set_cull;
145 gr_screen.gf_cross_fade = gr_opengl2_cross_fade;
147 gr_screen.gf_preload_init = gr_opengl2_preload_init;
148 gr_screen.gf_preload = gr_opengl2_preload;
150 gr_screen.gf_zbias = gr_opengl_zbias;
152 gr_screen.gf_set_viewport = gr_opengl2_set_viewport;
154 gr_screen.gf_activate = gr_opengl_activate;
156 gr_screen.gf_release_texture = gr_opengl2_release_texture;
159 static int opengl2_create_framebuffer()
162 glGenTextures(1, &FB_texture);
163 glBindTexture(GL_TEXTURE_2D, FB_texture);
165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
170 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gr_screen.max_w, gr_screen.max_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
172 glBindTexture(GL_TEXTURE_2D, 0);
174 // create renderbuffer
175 glGenRenderbuffers(1, &FB_rb_id);
176 glBindRenderbuffer(GL_RENDERBUFFER, FB_rb_id);
178 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, gr_screen.max_w, gr_screen.max_h);
180 glBindRenderbuffer(GL_RENDERBUFFER, 0);
182 // create framebuffer
183 glGenFramebuffers(1, &FB_id);
184 glBindFramebuffer(GL_FRAMEBUFFER, FB_id);
186 // attach texture and renderbuffer
187 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FB_texture, 0);
188 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, FB_rb_id);
190 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
192 glBindFramebuffer(GL_FRAMEBUFFER, 0);
194 if (status != GL_FRAMEBUFFER_COMPLETE) {
196 glDeleteTextures(1, &FB_texture);
201 glDeleteRenderbuffers(1, &FB_rb_id);
206 glDeleteFramebuffers(1, &FB_id);
216 void opengl2_cleanup()
218 if ( !GL_two_inited ) {
222 glBindFramebuffer(GL_FRAMEBUFFER, 0);
225 glDeleteTextures(1, &FB_texture);
230 glDeleteRenderbuffers(1, &FB_rb_id);
235 glDeleteFramebuffers(1, &FB_id);
239 opengl2_tcache_cleanup();
240 opengl2_shader_cleanup();
243 SDL_GL_DeleteContext(GL_context);
258 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
259 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
260 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
262 GL_context = SDL_GL_CreateContext(GL_window);
269 mprintf((" Vendor : %s\n", glGetString(GL_VENDOR)));
270 mprintf((" Renderer : %s\n", glGetString(GL_RENDERER)));
271 mprintf((" Version : %s\n", glGetString(GL_VERSION)));
273 // initial viewport setup
274 gr_opengl2_set_viewport(gr_screen.max_w, gr_screen.max_h);
276 // set up generic variables
277 opengl_set_variables();
279 opengl2_init_func_pointers();
280 opengl2_tcache_init();
282 if ( !opengl2_shader_init() ) {
283 mprintf((" Fallback : shader init failure!\n"));
288 if ( !opengl2_create_framebuffer() ) {
289 mprintf((" Fallback : fbo init failure!\n"));
295 glEnable(GL_DEPTH_TEST);
297 glEnable(GL_TEXTURE_2D);
299 glDepthRangef(0.0f, 1.0f);
301 glPixelStorei(GL_PACK_ALIGNMENT, 1);
302 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
307 gr_opengl_set_cull(1);
312 void gr_opengl2_flip()
314 if ( !GL_two_inited ) {
318 glBindFramebuffer(GL_FRAMEBUFFER, 0);
320 gr_opengl_reset_clip();
322 // set viewport to window size
323 glViewport(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h);
325 glClear(GL_COLOR_BUFFER_BIT);
330 float w = i2fl(GL_viewport_w);
331 float h = i2fl(GL_viewport_h);
333 const float tex_coord[] = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f };
334 const float ver_coord[] = { x, y, x, h, w, y, w, h };
336 opengl2_shader_use(PROG_WINDOW);
338 glEnableVertexAttribArray(SDRI_POSITION);
339 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, 0, &ver_coord);
341 glEnableVertexAttribArray(SDRI_TEXCOORD);
342 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, &tex_coord);
344 glBindTexture(GL_TEXTURE_2D, FB_texture);
346 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
348 glBindTexture(GL_TEXTURE_2D, 0);
350 glDisableVertexAttribArray(SDRI_TEXCOORD);
351 glDisableVertexAttribArray(SDRI_POSITION);
356 if ( mouse_is_visible() ) {
359 mouse_get_pos(&mx, &my);
361 if ( opengl2_tcache_set(Gr_cursor, TCACHE_TYPE_BITMAP_INTERFACE) ) {
362 opengl2_set_state(TEXTURE_SOURCE_DECAL, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
365 bm_get_info(Gr_cursor, &bw, &bh);
367 float x = i2fl(mx) * GL_viewport_scale_w;
368 float y = i2fl(my) * GL_viewport_scale_h;
369 float w = x + (bw * GL_viewport_scale_w);
370 float h = y + (bh * GL_viewport_scale_h);
372 const float tex_coord[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
373 const float ver_coord[] = { x, y, x, h, w, y, w, h };
375 opengl2_shader_use(PROG_WINDOW);
377 glEnableVertexAttribArray(SDRI_POSITION);
378 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, 0, &ver_coord);
380 glEnableVertexAttribArray(SDRI_TEXCOORD);
381 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, &tex_coord);
383 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
385 glDisableVertexAttribArray(SDRI_TEXCOORD);
386 glDisableVertexAttribArray(SDRI_POSITION);
390 gr_set_color(255,255,255);
391 gr_opengl2_line(mx, my, mx+7, my + 7);
392 gr_opengl2_line(mx, my, mx+5, my );
393 gr_opengl2_line(mx, my, mx, my+5);
399 GLenum error = glGetError();
401 if (error != GL_NO_ERROR) {
402 mprintf(("!!DEBUG!! OpenGL Error: %d\n", error));
406 SDL_GL_SwapWindow(GL_window);
408 opengl2_tcache_frame();
410 glBindFramebuffer(GL_FRAMEBUFFER, FB_id);
412 // set viewport to game screen size
413 glViewport(0, 0, gr_screen.max_w, gr_screen.max_h);
416 void gr_opengl2_set_clip(int x, int y, int w, int h)
418 // check for sanity of parameters
419 CAP(x, 0, gr_screen.max_w - 1);
420 CAP(y, 0, gr_screen.max_h - 1);
421 CAP(w, 0, gr_screen.max_w - x);
422 CAP(h, 0, gr_screen.max_h - y);
424 gr_screen.offset_x = x;
425 gr_screen.offset_y = y;
426 gr_screen.clip_left = 0;
427 gr_screen.clip_right = w-1;
428 gr_screen.clip_top = 0;
429 gr_screen.clip_bottom = h-1;
430 gr_screen.clip_width = w;
431 gr_screen.clip_height = h;
433 glEnable(GL_SCISSOR_TEST);
434 glScissor(x, gr_screen.max_h-y-h, w, h);
437 void gr_opengl2_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
439 gr_screen.current_fog_mode = fog_mode;
441 if (fog_mode == GR_FOGMODE_NONE) {
445 gr_screen.fog_near = fog_near;
446 gr_screen.fog_far = fog_far;
448 gr_init_color(&gr_screen.current_fog_color, r, g, b);
451 void gr_opengl2_zbuffer_clear(int mode)
455 Gr_zbuffering_mode = GR_ZBUFF_FULL;
456 Gr_global_zbuffering = 1;
458 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL);
459 glClear(GL_DEPTH_BUFFER_BIT);
462 Gr_zbuffering_mode = GR_ZBUFF_NONE;
463 Gr_global_zbuffering = 0;
467 void gr_opengl2_print_screen(const char *filename)
469 char tmp[MAX_FILENAME_LEN];
472 SDL_strlcpy( tmp, filename, SDL_arraysize(tmp) );
473 SDL_strlcat( tmp, NOX(".tga"), SDL_arraysize(tmp) );
475 int b_size = gr_screen.max_w * gr_screen.max_h;
477 buf = (ubyte*)malloc(b_size * 4);
483 CFILE *f = cfopen(tmp, "wb", CFILE_NORMAL, CF_TYPE_ROOT);
490 // Write the TGA header
491 cfwrite_ubyte( 0, f ); // IDLength;
492 cfwrite_ubyte( 0, f ); // ColorMapType;
493 cfwrite_ubyte( 2, f ); // ImageType; // 2 = 24bpp, uncompressed, 10=24bpp rle compressed
494 cfwrite_ushort( 0, f ); // CMapStart;
495 cfwrite_ushort( 0, f ); // CMapLength;
496 cfwrite_ubyte( 0, f ); // CMapDepth;
497 cfwrite_ushort( 0, f ); // XOffset;
498 cfwrite_ushort( 0, f ); // YOffset;
499 cfwrite_ushort( (ushort)gr_screen.max_w, f ); // Width;
500 cfwrite_ushort( (ushort)gr_screen.max_h, f ); // Height;
501 cfwrite_ubyte( 24, f ); //PixelDepth;
502 cfwrite_ubyte( 0, f ); //ImageDesc;
504 memset(buf, 0, b_size * 4);
506 glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
510 // convert from rgba to bgr
511 for (int i = 0; i < (b_size * 4); i += 4) {
521 cfwrite(buf, b_size * 3, 1, f);
528 void gr_opengl2_fade_in(int instantaneous)
533 void gr_opengl2_fade_out(int instantaneous)
538 void gr_opengl2_get_region(int, int w, int h, ubyte *data)
540 opengl2_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
542 glReadPixels(0, gr_screen.max_h-h-1, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
545 int gr_opengl2_save_screen()
547 gr_opengl_reset_clip();
549 if (GL_saved_screen_tex) {
550 mprintf(( "Screen already saved!\n" ));
554 glGenTextures(1, &GL_saved_screen_tex);
556 if ( !GL_saved_screen_tex ) {
557 mprintf(( "Couldn't create texture for saved screen!\n" ));
561 glBindTexture(GL_TEXTURE_2D, GL_saved_screen_tex);
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_CLAMP_TO_EDGE);
566 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
568 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0,
569 gr_screen.max_w, gr_screen.max_h, 0);
571 glBindTexture(GL_TEXTURE_2D, 0);
576 void gr_opengl2_restore_screen(int)
578 gr_opengl_reset_clip();
580 if ( !GL_saved_screen_tex ) {
587 float w = i2fl(gr_screen.max_w);
588 float h = i2fl(gr_screen.max_h);
590 const float tex_coord[] = { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f }; // y-flipped
591 const float ver_coord[] = { x, y, x, h, w, y, w, h };
593 opengl2_shader_use(PROG_TEX);
595 glVertexAttrib4f(SDRI_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
597 glEnableVertexAttribArray(SDRI_POSITION);
598 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, 0, &ver_coord);
600 glEnableVertexAttribArray(SDRI_TEXCOORD);
601 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, &tex_coord);
603 glBindTexture(GL_TEXTURE_2D, GL_saved_screen_tex);
605 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
607 glBindTexture(GL_TEXTURE_2D, 0);
609 glDisableVertexAttribArray(SDRI_TEXCOORD);
610 glDisableVertexAttribArray(SDRI_POSITION);
613 void gr_opengl2_free_screen(int)
615 if (GL_saved_screen_tex) {
616 glDeleteTextures(1, &GL_saved_screen_tex);
617 GL_saved_screen_tex = 0;
621 void gr_opengl2_dump_frame_start(int first_frame, int frames_between_dumps)
626 void gr_opengl2_dump_frame_stop()
631 void gr_opengl2_dump_frame()
636 static int GL_stream_w = 0;
637 static int GL_stream_h = 0;
639 static rb_t GL_stream[4];
641 void gr_opengl2_stream_start(int x, int y, int w, int h)
647 glGenTextures(1, &GL_stream_tex);
649 glBindTexture(GL_TEXTURE_2D, GL_stream_tex);
651 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
653 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
654 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
656 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL);
658 glBindTexture(GL_TEXTURE_2D, 0);
660 uint scale = os_config_read_uint("Video", "ScaleMovies", 1);
666 sx = scale ? 0 : ((gr_screen.max_w - w) / 2);
671 float h_factor = scale ? (gr_screen.max_w / i2fl(w)) : 1.0f;
674 sy = (gr_screen.max_h - fl2i(h * h_factor)) / 2;
683 sw = gr_screen.max_w - (sx * 2);
684 sh = gr_screen.max_h - (sy * 2);
690 GL_stream[0].x = i2fl(sx);
691 GL_stream[0].y = i2fl(sy);
692 GL_stream[0].u = 0.0f;
693 GL_stream[0].v = 0.0f;
695 GL_stream[1].x = i2fl(sx);
696 GL_stream[1].y = i2fl(sy + sh);
697 GL_stream[1].u = 0.0f;
698 GL_stream[1].v = 1.0f;
700 GL_stream[2].x = i2fl(sx + sw);
701 GL_stream[2].y = i2fl(sy);
702 GL_stream[2].u = 1.0f;
703 GL_stream[2].v = 0.0f;
705 GL_stream[3].x = i2fl(sx + sw);
706 GL_stream[3].y = i2fl(sy + sh);
707 GL_stream[3].u = 1.0f;
708 GL_stream[3].v = 1.0f;
710 glDisable(GL_DEPTH_TEST);
713 void gr_opengl2_stream_frame(ubyte *frame)
715 if ( !GL_stream_tex ) {
719 opengl2_shader_use(PROG_TEX);
721 glVertexAttrib4f(SDRI_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
723 glEnableVertexAttribArray(SDRI_POSITION);
724 glVertexAttribPointer(SDRI_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &GL_stream[0].x);
726 glEnableVertexAttribArray(SDRI_TEXCOORD);
727 glVertexAttribPointer(SDRI_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(rb_t), &GL_stream[0].u);
729 glBindTexture(GL_TEXTURE_2D, GL_stream_tex);
731 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GL_stream_w, GL_stream_h, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, frame);
733 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
735 glBindTexture(GL_TEXTURE_2D, 0);
737 glDisableVertexAttribArray(SDRI_TEXCOORD);
738 glDisableVertexAttribArray(SDRI_POSITION);
741 void gr_opengl2_stream_stop()
744 glBindTexture(GL_TEXTURE_2D, 0);
745 glDeleteTextures(1, &GL_stream_tex);
748 glEnable(GL_DEPTH_TEST);
752 void gr_opengl2_set_viewport(int width, int height)
756 float ratio = gr_screen.max_w / i2fl(gr_screen.max_h);
759 h = fl2i((width / ratio) + 0.5f);
763 w = fl2i((height * ratio) + 0.5f);
767 y = (height - h) / 2;
773 GL_viewport_scale_w = w / i2fl(gr_screen.max_w);
774 GL_viewport_scale_h = h / i2fl(gr_screen.max_h);
776 opengl2_shader_update();