]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl1.cpp
rendering functions mostly done; more complete shader setup
[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 "2d.h"
15 #include "mouse.h"
16 #include "pstypes.h"
17 #include "cfile.h"
18 #include "bmpman.h"
19 #include "grinternal.h"
20 #include "osapi.h"
21 #include "osregistry.h"
22
23
24 int OGL_fog_mode = 0;
25
26 int GL_one_inited = 0;
27
28
29 static GLuint Gr_saved_screen_tex = 0;
30
31 static int Gr_opengl_mouse_saved = 0;
32 static int Gr_opengl_mouse_saved_x = 0;
33 static int Gr_opengl_mouse_saved_y = 0;
34 static int Gr_opengl_mouse_saved_w = 0;
35 static int Gr_opengl_mouse_saved_h = 0;
36 static ubyte *Gr_opengl_mouse_saved_data = NULL;
37
38
39 PFNGLSECONDARYCOLORPOINTERPROC vglSecondaryColorPointer = NULL;
40
41
42 static gr_alpha_blend GL_current_alpha_blend = (gr_alpha_blend) -1;
43 static gr_zbuffer_type GL_current_zbuffer_type = (gr_zbuffer_type) -1;
44
45 void opengl1_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
46 {
47         opengl1_set_texture_state(ts);
48
49         if (ab != GL_current_alpha_blend) {
50                 switch (ab) {
51                         case ALPHA_BLEND_NONE:                  // 1*SrcPixel + 0*DestPixel
52                                 glBlendFunc(GL_ONE, GL_ZERO);
53                                 break;
54                         case ALPHA_BLEND_ADDITIVE:              // 1*SrcPixel + 1*DestPixel
55                                 glBlendFunc(GL_ONE, GL_ONE);
56                                 break;
57                         case ALPHA_BLEND_ALPHA_ADDITIVE:        // Alpha*SrcPixel + 1*DestPixel
58                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
59                                 break;
60                         case ALPHA_BLEND_ALPHA_BLEND_ALPHA:     // Alpha*SrcPixel + (1-Alpha)*DestPixel
61                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
62                                 break;
63                         case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR: // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
64                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
65                                 break;
66                         default:
67                                 break;
68                 }
69
70                 GL_current_alpha_blend = ab;
71         }
72
73         if (zt != GL_current_zbuffer_type) {
74                 switch (zt) {
75                         case ZBUFFER_TYPE_NONE:
76                                 glDepthFunc(GL_ALWAYS);
77                                 glDepthMask(GL_FALSE);
78                                 break;
79                         case ZBUFFER_TYPE_READ:
80                                 glDepthFunc(GL_LESS);
81                                 glDepthMask(GL_FALSE);
82                                 break;
83                         case ZBUFFER_TYPE_WRITE:
84                                 glDepthFunc(GL_ALWAYS);
85                                 glDepthMask(GL_TRUE);
86                                 break;
87                         case ZBUFFER_TYPE_FULL:
88                                 glDepthFunc(GL_LESS);
89                                 glDepthMask(GL_TRUE);
90                                 break;
91                         default:
92                                 break;
93                 }
94
95                 GL_current_zbuffer_type = zt;
96         }
97 }
98
99 void opengl1_cleanup()
100 {
101         if ( !GL_one_inited ) {
102                 return;
103         }
104
105         gr_opengl_reset_clip();
106         gr_opengl_clear();
107         gr_opengl1_flip();
108
109         gr_opengl1_free_screen(0);
110
111         if (Gr_opengl_mouse_saved_data) {
112                 free(Gr_opengl_mouse_saved_data);
113                 Gr_opengl_mouse_saved_data = NULL;
114         }
115
116         opengl1_tcache_cleanup();
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_opengl_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_set_gamma = gr_opengl1_set_gamma;
162
163         gr_screen.gf_lock = gr_opengl_lock;
164         gr_screen.gf_unlock = gr_opengl_unlock;
165
166         gr_screen.gf_fog_set = gr_opengl1_fog_set;
167
168         gr_screen.gf_get_region = gr_opengl1_get_region;
169
170         gr_screen.gf_set_cull = gr_opengl_set_cull;
171
172         gr_screen.gf_cross_fade = gr_opengl1_cross_fade;
173
174         gr_screen.gf_preload_init = gr_opengl1_preload_init;
175         gr_screen.gf_preload = gr_opengl1_preload;
176
177         gr_screen.gf_zbias = gr_opengl_zbias;
178
179         gr_screen.gf_force_windowed = gr_opengl_force_windowed;
180         gr_screen.gf_force_fullscreen = gr_opengl_force_fullscreen;
181         gr_screen.gf_toggle_fullscreen = gr_opengl_toggle_fullscreen;
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_context = SDL_GL_CreateContext(GL_window);
197
198         if ( !GL_context ) {
199                 return 0;
200         }
201
202         mprintf(("  Vendor   : %s\n", glGetString(GL_VENDOR)));
203         mprintf(("  Renderer : %s\n", glGetString(GL_RENDERER)));
204         mprintf(("  Version  : %s\n", glGetString(GL_VERSION)));
205
206         // set up generic variables
207         opengl_set_variables();
208
209         opengl1_init_func_pointers();
210         opengl1_tcache_init();
211
212         // initial viewport setup
213         gr_opengl1_set_viewport(gr_screen.max_w, gr_screen.max_h);
214
215         /*
216           1 = use secondary color ext
217           2 = use opengl linear fog
218          */
219         OGL_fog_mode = 2;
220
221         // only available with OpenGL 1.2+, must get ptr for Windows
222         vglSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)SDL_GL_GetProcAddress("glSecondaryColorPointer");
223
224         if (vglSecondaryColorPointer) {
225                 OGL_fog_mode = 1;
226         }
227
228         mprintf(("  Fog mode : %s\n", (OGL_fog_mode == 1) ? "secondary color" : "linear"));
229
230         glShadeModel(GL_SMOOTH);
231         glEnable(GL_DITHER);
232         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
233         glHint(GL_FOG_HINT, GL_NICEST);
234
235         glEnable(GL_DEPTH_TEST);
236         glEnable(GL_BLEND);
237
238         glEnable(GL_TEXTURE_2D);
239
240         glDepthRange(0.0, 1.0);
241
242         glPixelStorei(GL_PACK_ALIGNMENT, 1);
243         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
244
245         glFlush();
246
247         gr_opengl_clear();
248         gr_opengl_set_cull(1);
249
250         GL_one_inited = 1;
251
252         return 1;
253 }
254
255 void gr_opengl1_flip()
256 {
257         if ( !GL_one_inited ) {
258                 return;
259         }
260
261         gr_reset_clip();
262
263         mouse_eval_deltas();
264
265         Gr_opengl_mouse_saved = 0;
266
267         if ( mouse_is_visible() )       {
268                 int mx, my;
269
270                 mouse_get_pos( &mx, &my );
271
272                 gr_opengl1_save_mouse_area(mx,my,32,32);
273
274                 if (Gr_cursor == -1) {
275 #ifndef NDEBUG
276                         gr_set_color(255,255,255);
277                         gr_line(mx, my, mx+7, my + 7);
278                         gr_line(mx, my, mx+5, my );
279                         gr_line(mx, my, mx, my+5);
280 #endif
281                 } else {
282                         gr_set_bitmap(Gr_cursor);
283                         gr_bitmap(mx, my);
284                 }
285          }
286
287 #ifndef NDEBUG
288         GLenum error = GL_NO_ERROR;
289
290         do {
291                 error = glGetError();
292
293                 if (error != GL_NO_ERROR) {
294                         nprintf(("Warning", "!!DEBUG!! OpenGL Error: %d\n", error));
295                 }
296         } while (error != GL_NO_ERROR);
297 #endif
298
299         SDL_GL_SwapWindow(GL_window);
300
301         opengl1_tcache_frame();
302
303         int cnt = GL_activate;
304         if ( cnt )      {
305                 GL_activate-=cnt;
306                 opengl1_tcache_flush();
307                 // gr_opengl_clip_cursor(1); /* mouse grab, see opengl_activate */
308         }
309
310         cnt = GL_deactivate;
311         if ( cnt )      {
312                 GL_deactivate-=cnt;
313                 // gr_opengl_clip_cursor(0);  /* mouse grab, see opengl_activate */
314         }
315 }
316
317 void gr_opengl1_set_clip(int x, int y, int w, int h)
318 {
319         // check for sanity of parameters
320         CAP(x, 0, gr_screen.max_w - 1);
321         CAP(y, 0, gr_screen.max_h - 1);
322         CAP(w, 0, gr_screen.max_w - x);
323         CAP(h, 0, gr_screen.max_h - y);
324
325         gr_screen.offset_x = x;
326         gr_screen.offset_y = y;
327         gr_screen.clip_left = 0;
328         gr_screen.clip_right = w-1;
329         gr_screen.clip_top = 0;
330         gr_screen.clip_bottom = h-1;
331         gr_screen.clip_width = w;
332         gr_screen.clip_height = h;
333
334         x = fl2i((x * GL_viewport_scale_w) + 0.5f) + GL_viewport_x;
335         y = fl2i((y * GL_viewport_scale_h) + 0.5f) + GL_viewport_y;
336         w = fl2i((w * GL_viewport_scale_w) + 0.5f);
337         h = fl2i((h * GL_viewport_scale_h) + 0.5f);
338
339         glEnable(GL_SCISSOR_TEST);
340         glScissor(x, GL_viewport_h-y-h, w, h);
341 }
342
343 void gr_opengl1_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
344 {
345         SDL_assert((r >= 0) && (r < 256));
346         SDL_assert((g >= 0) && (g < 256));
347         SDL_assert((b >= 0) && (b < 256));
348
349         if (fog_mode == GR_FOGMODE_NONE) {
350                 if (gr_screen.current_fog_mode != fog_mode) {
351                         glDisable(GL_FOG);
352
353                         if (OGL_fog_mode == 1) {
354                                 glDisable(GL_COLOR_SUM);
355                         }
356                 }
357
358                 gr_screen.current_fog_mode = fog_mode;
359
360                 return;
361         }
362
363         if (gr_screen.current_fog_mode != fog_mode) {
364                 glEnable(GL_FOG);
365
366                 if (OGL_fog_mode == 1) {
367                         glEnable(GL_COLOR_SUM);
368                 } else if (OGL_fog_mode == 2) {
369                         glFogi(GL_FOG_MODE, GL_LINEAR);
370                 }
371
372                 gr_screen.current_fog_mode = fog_mode;
373         }
374
375         if ( (gr_screen.current_fog_color.red != r) ||
376                         (gr_screen.current_fog_color.green != g) ||
377                         (gr_screen.current_fog_color.blue != b) ) {
378                 GLfloat fc[4];
379
380                 gr_init_color( &gr_screen.current_fog_color, r, g, b );
381
382                 fc[0] = r / 255.0f;
383                 fc[1] = g / 255.0f;
384                 fc[2] = b / 255.0f;
385                 fc[3] = 1.0f;
386
387                 glFogfv(GL_FOG_COLOR, fc);
388         }
389
390         if( (fog_near >= 0.0f) && (fog_far >= 0.0f) &&
391                         ((fog_near != gr_screen.fog_near) ||
392                         (fog_far != gr_screen.fog_far)) ) {
393                 gr_screen.fog_near = fog_near;
394                 gr_screen.fog_far = fog_far;
395
396                 if (OGL_fog_mode == 2) {
397                         glFogf(GL_FOG_START, fog_near);
398                         glFogf(GL_FOG_END, fog_far);
399                 }
400         }
401 }
402
403 void gr_opengl1_zbuffer_clear(int mode)
404 {
405         if (mode) {
406                 Gr_zbuffering = 1;
407                 Gr_zbuffering_mode = GR_ZBUFF_FULL;
408                 Gr_global_zbuffering = 1;
409
410                 opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL );
411                 glClear ( GL_DEPTH_BUFFER_BIT );
412         } else {
413                 Gr_zbuffering = 0;
414                 Gr_zbuffering_mode = GR_ZBUFF_NONE;
415                 Gr_global_zbuffering = 0;
416         }
417 }
418
419 void gr_opengl1_fade_in(int instantaneous)
420 {
421         // Empty - DDOI
422 }
423
424 void gr_opengl1_fade_out(int instantaneous)
425 {
426         // Empty - DDOI
427 }
428
429 void gr_opengl1_get_region(int front, int w, int h, ubyte *data)
430 {
431         if (front) {
432                 glReadBuffer(GL_FRONT);
433         } else {
434                 glReadBuffer(GL_BACK);
435         }
436
437         opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
438
439         glPixelStorei(GL_UNPACK_ROW_LENGTH, GL_viewport_w);
440
441         int x = GL_viewport_x;
442         int y = (GL_viewport_y+GL_viewport_h)-h-1;
443
444         GLenum pxtype = GL_UNSIGNED_SHORT_5_5_5_1;
445
446         if (gr_screen.bytes_per_pixel == 4) {
447                 pxtype = GL_UNSIGNED_BYTE;
448         }
449
450         glReadPixels(x, y, w, h, GL_RGBA, pxtype, data);
451
452         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
453 }
454
455 void gr_opengl1_save_mouse_area(int x, int y, int w, int h)
456 {
457         int x1, y1, x2, y2;
458
459         if (Gr_saved_screen_tex) {
460                 // already saved, don't need it again
461                 return;
462         }
463
464         w = fl2i((w * GL_viewport_scale_w) + 0.5f);
465         h = fl2i((h * GL_viewport_scale_h) + 0.5f);
466
467         x1 = x;
468         y1 = y;
469         x2 = x+w-1;
470         y2 = y+h-1;
471
472         CAP(x1, 0, GL_viewport_w);
473         CAP(x2, 0, GL_viewport_w);
474         CAP(y1, 0, GL_viewport_h);
475         CAP(y2, 0, GL_viewport_h);
476
477         Gr_opengl_mouse_saved_x = x1;
478         Gr_opengl_mouse_saved_y = y1;
479         Gr_opengl_mouse_saved_w = x2 - x1 + 1;
480         Gr_opengl_mouse_saved_h = y2 - y1 + 1;
481
482         if ( (Gr_opengl_mouse_saved_w < 1) || (Gr_opengl_mouse_saved_h < 1) ) {
483                 return;
484         }
485
486         if (Gr_opengl_mouse_saved_data == NULL) {
487                 Gr_opengl_mouse_saved_data = (ubyte*)malloc(w * h * 3);
488
489                 if ( !Gr_opengl_mouse_saved_data ) {
490                         return;
491                 }
492         }
493
494         x1 = GL_viewport_x+Gr_opengl_mouse_saved_x;
495         y1 = (GL_viewport_y+GL_viewport_h)-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
496
497         glReadBuffer(GL_BACK);
498
499         glReadPixels(x1, y1, Gr_opengl_mouse_saved_w, Gr_opengl_mouse_saved_h,
500                         GL_RGB, GL_UNSIGNED_BYTE, Gr_opengl_mouse_saved_data);
501
502         Gr_opengl_mouse_saved = 1;
503 }
504
505 int gr_opengl1_save_screen()
506 {
507         gr_reset_clip();
508
509         if (Gr_saved_screen_tex) {
510                 mprintf(( "Screen already saved!\n" ));
511                 return -1;
512         }
513
514         glGenTextures(1, &Gr_saved_screen_tex);
515
516         if ( !Gr_saved_screen_tex ) {
517                 mprintf(( "Couldn't create texture for saved screen!\n" ));
518                 return -1;
519         }
520
521         glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
522
523         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
524         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
525         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
526         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
527         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
528
529         glReadBuffer(GL_FRONT);
530
531         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_viewport_x, GL_viewport_y,
532                         GL_viewport_w, GL_viewport_h, 0);
533
534         if (Gr_opengl_mouse_saved) {
535                 int x = Gr_opengl_mouse_saved_x;
536                 int y = GL_viewport_h-Gr_opengl_mouse_saved_y-Gr_opengl_mouse_saved_h;
537
538                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, Gr_opengl_mouse_saved_w,
539                                 Gr_opengl_mouse_saved_h, GL_RGB, GL_UNSIGNED_BYTE,
540                                 Gr_opengl_mouse_saved_data);
541         }
542
543         glBindTexture(GL_TEXTURE_2D, 0);
544
545         return 0;
546 }
547
548 void gr_opengl1_restore_screen(int)
549 {
550         gr_reset_clip();
551
552         if ( !Gr_saved_screen_tex ) {
553                 gr_clear();
554                 return;
555         }
556
557         int x = 0;
558         int y = 0;
559         int w = fl2i(GL_viewport_w / GL_viewport_scale_w + 0.5f);
560         int h = fl2i(GL_viewport_h / GL_viewport_scale_h + 0.5f);
561
562         const int tex_coord[] = { 0, 1, 0, 0, 1, 1, 1, 0 };     // y-flipped
563         const int ver_coord[] = { x, y, x, h, w, y, w, h };
564
565         glColor4ub(255, 255, 255, 255);
566
567         glBindTexture(GL_TEXTURE_2D, Gr_saved_screen_tex);
568
569         opengl1_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
570
571         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
572         glEnableClientState(GL_VERTEX_ARRAY);
573
574         glTexCoordPointer(2, GL_INT, 0, &tex_coord);
575         glVertexPointer(2, GL_INT, 0, &ver_coord);
576
577         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
578
579         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
580         glDisableClientState(GL_VERTEX_ARRAY);
581
582         glBindTexture(GL_TEXTURE_2D, 0);
583 }
584
585 void gr_opengl1_free_screen(int)
586 {
587         if (Gr_saved_screen_tex) {
588                 glDeleteTextures(1, &Gr_saved_screen_tex);
589                 Gr_saved_screen_tex = 0;
590         }
591 }
592
593 void gr_opengl1_dump_frame_start(int first_frame, int frames_between_dumps)
594 {
595         STUB_FUNCTION;
596 }
597
598 void gr_opengl1_dump_frame_stop()
599 {
600         STUB_FUNCTION;
601 }
602
603 void gr_opengl1_dump_frame()
604 {
605         STUB_FUNCTION;
606 }
607
608 void gr_opengl1_set_viewport(int width, int height)
609 {
610         int w, h, x, y;
611
612         float ratio = gr_screen.max_w / i2fl(gr_screen.max_h);
613
614         w = width;
615         h = fl2i((width / ratio) + 0.5f);
616
617         if (h > height) {
618                 h = height;
619                 w = fl2i((height * ratio) + 0.5f);
620         }
621
622         x = (width - w) / 2;
623         y = (height - h) / 2;
624
625         GL_viewport_x = x;
626         GL_viewport_y = y;
627         GL_viewport_w = w;
628         GL_viewport_h = h;
629         GL_viewport_scale_w = w / i2fl(gr_screen.max_w);
630         GL_viewport_scale_h = h / i2fl(gr_screen.max_h);
631
632         glViewport(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h);
633
634         glMatrixMode(GL_PROJECTION);
635         glLoadIdentity();
636         glOrtho(0, GL_viewport_w, GL_viewport_h, 0, 0.0, 1.0);
637         glMatrixMode(GL_MODELVIEW);
638         glLoadIdentity();
639         glScalef(GL_viewport_scale_w, GL_viewport_scale_h, 1.0f);
640
641         // free mouse cursor storage, since the size might have changed
642         if (Gr_opengl_mouse_saved_data) {
643                 free(Gr_opengl_mouse_saved_data);
644                 Gr_opengl_mouse_saved_data = NULL;
645         }
646
647         // clear screen once to fix issues with edges on non-4:3
648         gr_opengl_clear();
649 }