]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl1render.cpp
use a better multi_sw_ok_to_commit() check
[taylor/freespace2.git] / src / graphics / grgl1render.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 "pstypes.h"
12 #include "2d.h"
13 #include "gropengl.h"
14 #include "gropenglinternal.h"
15 #include "grgl1.h"
16 #include "bmpman.h"
17 #include "grinternal.h"
18 #include "3d.h"
19 #include "neb.h"
20 #include "line.h"
21 #include "palman.h"
22
23
24 #define NEBULA_COLORS 20
25
26
27 static void opengl1_rect_internal(int x, int y, int w, int h, int r, int g, int b, int a)
28 {
29         int saved_zbuf = gr_zbuffer_get();
30
31         // no zbuffering, no culling
32         gr_zbuffer_set(GR_ZBUFF_NONE);
33         gr_opengl_set_cull(0);
34
35         opengl1_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE);
36
37         opengl_alloc_render_buffer(4);
38
39         render_buffer[0].x = i2fl(x);
40         render_buffer[0].y = i2fl(y);
41
42         render_buffer[1].x = i2fl(x);
43         render_buffer[1].y = i2fl(y + h);
44
45         render_buffer[2].x = i2fl(x + w);
46         render_buffer[2].y = i2fl(y);
47
48         render_buffer[3].x = i2fl(x + w);
49         render_buffer[3].y = i2fl(y + h);
50
51         r = Gr_gamma_lookup[r];
52         g = Gr_gamma_lookup[g];
53         b = Gr_gamma_lookup[b];
54
55         glColor4ub((ubyte)r, (ubyte)g, (ubyte)b, (ubyte)a);
56
57         glEnableClientState(GL_VERTEX_ARRAY);
58
59         glVertexPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
60
61         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
62
63         glDisableClientState(GL_VERTEX_ARRAY);
64
65         // restore zbuffer and culling
66         gr_zbuffer_set(saved_zbuf);
67         gr_opengl_set_cull(1);
68 }
69
70 static void opengl1_aabitmap_ex_internal(int x,int y,int w,int h,int sx,int sy)
71 {
72         if ( (w < 1) || (h < 1) ) {
73                 return;
74         }
75
76         if ( !gr_screen.current_color.is_alphacolor ) {
77                 return;
78         }
79
80         float u_scale, v_scale;
81
82         if ( !opengl1_tcache_set(gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP,
83                         &u_scale, &v_scale, 0, -1, -1, 0) )
84         {
85                 // Couldn't set texture
86                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
87                 return;
88         }
89
90         opengl1_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
91
92         float u0, u1, v0, v1;
93         float x1, x2, y1, y2;
94         int bw, bh;
95
96         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
97
98         u0 = u_scale*i2fl(sx)/i2fl(bw);
99         v0 = v_scale*i2fl(sy)/i2fl(bh);
100
101         u1 = u_scale*i2fl(sx+w)/i2fl(bw);
102         v1 = v_scale*i2fl(sy+h)/i2fl(bh);
103
104         x1 = i2fl(x+gr_screen.offset_x);
105         y1 = i2fl(y+gr_screen.offset_y);
106         x2 = i2fl(x+w+gr_screen.offset_x);
107         y2 = i2fl(y+h+gr_screen.offset_y);
108
109         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
110                         gr_screen.current_color.blue,gr_screen.current_color.alpha);
111
112         opengl_alloc_render_buffer(4);
113
114         render_buffer[0].x = x1;
115         render_buffer[0].y = y1;
116         render_buffer[0].u = u0;
117         render_buffer[0].v = v0;
118
119         render_buffer[1].x = x1;
120         render_buffer[1].y = y2;
121         render_buffer[1].u = u0;
122         render_buffer[1].v = v1;
123
124         render_buffer[2].x = x2;
125         render_buffer[2].y = y1;
126         render_buffer[2].u = u1;
127         render_buffer[2].v = v0;
128
129         render_buffer[3].x = x2;
130         render_buffer[3].y = y2;
131         render_buffer[3].u = u1;
132         render_buffer[3].v = v1;
133
134         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
135         glEnableClientState(GL_VERTEX_ARRAY);
136
137         glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
138         glVertexPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
139
140         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
141
142         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
143         glDisableClientState(GL_VERTEX_ARRAY);
144 }
145
146 static void opengl1_tmapper_internal( int nv, vertex ** verts, uint flags, int is_scaler )
147 {
148         int i;
149         float u_scale = 1.0f, v_scale = 1.0f;
150
151         gr_texture_source texture_source = TEXTURE_SOURCE_NONE;
152         gr_alpha_blend alpha_blend = ALPHA_BLEND_ALPHA_BLEND_ALPHA;
153         gr_zbuffer_type zbuffer_type = ZBUFFER_TYPE_NONE;
154
155         if (Gr_zbuffering) {
156                 if ( is_scaler || (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) ) {
157                         zbuffer_type = ZBUFFER_TYPE_READ;
158                 } else {
159                         zbuffer_type = ZBUFFER_TYPE_FULL;
160                 }
161         }
162
163         int tmap_type = TCACHE_TYPE_NORMAL;
164
165         ubyte r = 255, g = 255, b = 255, a = 255;
166
167         if ( !(flags & TMAP_FLAG_TEXTURED) ) {
168                 r = gr_screen.current_color.red;
169                 g = gr_screen.current_color.green;
170                 b = gr_screen.current_color.blue;
171         }
172
173         if (gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER) {
174                 alpha_blend = ALPHA_BLEND_ALPHA_ADDITIVE;
175
176                 // Blend with screen pixel using src*alpha+dst
177
178                 if (gr_screen.current_alpha < 1.0f) {
179                         r = ubyte((r * gr_screen.current_alpha) + 0.5f);
180                         g = ubyte((g * gr_screen.current_alpha) + 0.5f);
181                         b = ubyte((b * gr_screen.current_alpha) + 0.5f);
182                 }
183         }
184
185         if (flags & TMAP_FLAG_BITMAP_SECTION) {
186                 SDL_assert( !(flags & TMAP_FLAG_BITMAP_INTERFACE) );
187                 tmap_type = TCACHE_TYPE_BITMAP_SECTION;
188         } else if (flags & TMAP_FLAG_BITMAP_INTERFACE) {
189                 SDL_assert( !(flags & TMAP_FLAG_BITMAP_SECTION) );
190                 tmap_type = TCACHE_TYPE_BITMAP_INTERFACE;
191         }
192
193         if (flags & TMAP_FLAG_TEXTURED) {
194                 if ( !opengl1_tcache_set(gr_screen.current_bitmap, tmap_type, &u_scale,
195                                 &v_scale, 0, gr_screen.current_bitmap_sx, gr_screen.current_bitmap_sy, 0) )
196                 {
197                         mprintf(( "Not rendering a texture because it didn't fit in VRAM!\n" ));
198                         return;
199                 }
200
201                 // use non-filtered textures for bitmap sections and UI graphics
202                 switch (tmap_type) {
203                         case TCACHE_TYPE_BITMAP_INTERFACE:
204                         case TCACHE_TYPE_BITMAP_SECTION:
205                                 texture_source = TEXTURE_SOURCE_NO_FILTERING;
206                                 break;
207
208                         default:
209                                 texture_source = TEXTURE_SOURCE_DECAL;
210                                 break;
211                 }
212         }
213
214
215         opengl1_set_state( texture_source, alpha_blend, zbuffer_type );
216
217         float ox = gr_screen.offset_x * 16.0f;
218         float oy = gr_screen.offset_y * 16.0f;
219
220         if (flags & TMAP_FLAG_PIXEL_FOG) {
221                 int fr, fg, fb;
222                 int ra, ga, ba;
223                 float sx, sy;
224
225                 ra = ga = ba = 0;
226
227                 for (i = nv-1; i >= 0; i--) {
228                         vertex * va = verts[i];
229
230                         sx = (va->sx * 16.0f + ox) / 16.0f;
231                         sy = (va->sy * 16.0f + oy) / 16.0f;
232
233                         neb2_get_pixel((int)sx, (int)sy, &fr, &fg, &fb);
234
235                         ra += fr;
236                         ga += fg;
237                         ba += fb;
238                 }
239
240                 ra /= nv;
241                 ga /= nv;
242                 ba /= nv;
243
244                 gr_opengl1_fog_set(GR_FOGMODE_FOG, ra, ga, ba, -1.0f, -1.0f);
245         }
246
247         opengl_alloc_render_buffer(nv);
248
249         int rb_offset = 0;
250
251         float sx, sy, sz = 0.99f, rhw = 1.0f;
252
253         bool bZval = (Gr_zbuffering || (flags & TMAP_FLAG_NEBULA));
254         bool bCorrect = ((flags & TMAP_FLAG_CORRECT) == TMAP_FLAG_CORRECT);
255         bool bAlpha = ((flags & TMAP_FLAG_ALPHA) == TMAP_FLAG_ALPHA);
256         bool bNebula = ((flags & TMAP_FLAG_NEBULA) == TMAP_FLAG_NEBULA);
257         bool bRamp = ((flags & TMAP_FLAG_RAMP) && (flags & TMAP_FLAG_GOURAUD));
258         bool bRGB = ((flags & TMAP_FLAG_RGB) && (flags & TMAP_FLAG_GOURAUD));
259         bool bTextured = ((flags & TMAP_FLAG_TEXTURED) == TMAP_FLAG_TEXTURED);
260
261         for (i = nv-1; i >= 0; i--) {
262                 vertex *va = verts[i];
263
264                 if (bZval) {
265                         sz = 1.0f - 1.0f / (1.0f + va->z / (32768.0f / 256.0f));
266
267                         if ( sz > 0.98f ) {
268                                 sz = 0.98f;
269                         }
270                 }
271
272                 if (bCorrect) {
273                         rhw = 1.0f / va->sw;
274                 }
275
276                 if (bAlpha) {
277                         a = va->a;
278                 }
279
280                 if (bRGB) {
281                         // Make 0.75 be 256.0f
282                         r = (ubyte)Gr_gamma_lookup[va->r];
283                         g = (ubyte)Gr_gamma_lookup[va->g];
284                         b = (ubyte)Gr_gamma_lookup[va->b];
285                 } else if (bNebula) {
286                         int pal = (va->b*(NEBULA_COLORS-1))/255;
287                         r = gr_palette[pal*3+0];
288                         g = gr_palette[pal*3+1];
289                         b = gr_palette[pal*3+2];
290                 } else if (bRamp) {
291                         r = g = b = (ubyte)Gr_gamma_lookup[va->b];
292                 }
293
294                 render_buffer[rb_offset].r = r;
295                 render_buffer[rb_offset].g = g;
296                 render_buffer[rb_offset].b = b;
297                 render_buffer[rb_offset].a = a;
298
299                 sx = (va->sx * 16.0f + ox) / 16.0f;
300                 sy = (va->sy * 16.0f + oy) / 16.0f;
301
302                 if (bTextured) {
303                         render_buffer[rb_offset].u = va->u * u_scale;
304                         render_buffer[rb_offset].v = va->v * v_scale;
305                 }
306
307                 render_buffer[rb_offset].x = sx * rhw;
308                 render_buffer[rb_offset].y = sy * rhw;
309                 render_buffer[rb_offset].z = -sz * rhw;
310                 render_buffer[rb_offset].w = rhw;
311
312                 ++rb_offset;
313         }
314
315         if (flags & TMAP_FLAG_TEXTURED) {
316                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
317                 glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
318         }
319
320         glEnableClientState(GL_COLOR_ARRAY);
321         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(rb_t), &render_buffer[0].r);
322
323         glEnableClientState(GL_VERTEX_ARRAY);
324         glVertexPointer(4, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
325
326         glDrawArrays(GL_TRIANGLE_FAN, 0, rb_offset);
327
328         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
329         glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
330         glDisableClientState(GL_COLOR_ARRAY);
331         glDisableClientState(GL_VERTEX_ARRAY);
332 }
333
334 void gr_opengl1_rect(int x,int y,int w,int h)
335 {
336         opengl1_rect_internal(x, y, w, h, gr_screen.current_color.red,
337                         gr_screen.current_color.green, gr_screen.current_color.blue,
338                         gr_screen.current_color.alpha);
339 }
340
341 void gr_opengl1_shade(int x,int y,int w,int h)
342 {
343         int r,g,b,a;
344
345         float shade1 = 1.0f;
346         float shade2 = 6.0f;
347
348         r = fl2i(gr_screen.current_shader.r*255.0f*shade1);
349         CAP(r, 0, 255);
350         g = fl2i(gr_screen.current_shader.g*255.0f*shade1);
351         CAP(g, 0, 255);
352         b = fl2i(gr_screen.current_shader.b*255.0f*shade1);
353         CAP(b, 0, 255);
354         a = fl2i(gr_screen.current_shader.c*255.0f*shade2);
355         CAP(a, 0, 255);
356
357         opengl1_rect_internal(x, y, w, h, r, g, b, a);
358 }
359
360 void gr_opengl1_aabitmap_ex(int x,int y,int w,int h,int sx,int sy)
361 {
362         if ( (x > gr_screen.clip_right ) || ((x+w-1) < gr_screen.clip_left) )
363                 return;
364
365         if ( (y > gr_screen.clip_bottom ) || ((y+h-1) < gr_screen.clip_top) )
366                 return;
367
368         opengl1_aabitmap_ex_internal(x, y, w, h, sx, sy);
369 }
370
371 void gr_opengl1_aabitmap(int x, int y)
372 {
373         int w, h;
374
375         bm_get_info( gr_screen.current_bitmap, &w, &h, NULL );
376
377         gr_opengl1_aabitmap_ex(x, y, w, h, 0, 0);
378 }
379
380 void gr_opengl1_string( int sx, int sy, const char *s )
381 {
382         int width, spacing, letter;
383         int x, y;
384         int rb_offset;
385         float u_scale, v_scale;
386         float u0, u1, v0, v1;
387         float x1, x2, y1, y2;
388         int bw, bh;
389         float fbw, fbh;
390
391         if ( !Current_font )    {
392                 return;
393         }
394
395         gr_set_bitmap(Current_font->bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
396
397         if ( !opengl1_tcache_set( gr_screen.current_bitmap, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 0, -1, -1, 0 ) )  {
398                 // Couldn't set texture
399                 mprintf(( "WARNING: Error setting aabitmap texture!\n" ));
400                 return;
401         }
402
403         bm_get_info( gr_screen.current_bitmap, &bw, &bh );
404
405         fbw = 1.0f / i2fl(bw);
406         fbh = 1.0f / i2fl(bh);
407
408         opengl1_set_state( TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
409
410         // don't want to create a super huge buffer size (i.e. credits text)
411         const int alocsize = 320;       // 80 characters max per render call
412         opengl_alloc_render_buffer(alocsize);
413
414         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
415                         gr_screen.current_color.blue, gr_screen.current_color.alpha);
416
417         glEnableClientState(GL_VERTEX_ARRAY);
418         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
419
420         glVertexPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
421         glTexCoordPointer(2, GL_FLOAT, sizeof(rb_t), &render_buffer[0].u);
422
423         y = sy;
424
425         if (sx==0x8000) {                       //centered
426                 x = get_centered_x(s);
427         } else {
428                 x = sx;
429         }
430
431         spacing = 0;
432         rb_offset = 0;
433
434         while (*s)      {
435                 x += spacing;
436
437                 while (*s== '\n' )      {
438                         s++;
439                         y += Current_font->h;
440                         if (sx==0x8000) {                       //centered
441                                 x = get_centered_x(s);
442                         } else {
443                                 x = sx;
444                         }
445                 }
446                 if (*s == 0 ) break;
447
448                 letter = get_char_width(s[0],s[1],&width,&spacing);
449                 s++;
450
451                 //not in font, draw as space
452                 if (letter<0)   {
453                         continue;
454                 }
455
456                 int xd, yd, xc, yc;
457                 int wc, hc;
458
459                 // Check if this character is totally clipped
460                 if ( x + width < gr_screen.clip_left ) continue;
461                 if ( y + Current_font->h < gr_screen.clip_top ) continue;
462                 if ( x > gr_screen.clip_right ) continue;
463                 if ( y > gr_screen.clip_bottom ) continue;
464
465                 xd = yd = 0;
466                 if ( x < gr_screen.clip_left ) xd = gr_screen.clip_left - x;
467                 if ( y < gr_screen.clip_top ) yd = gr_screen.clip_top - y;
468                 xc = x+xd;
469                 yc = y+yd;
470
471                 wc = width - xd; hc = Current_font->h - yd;
472                 if ( xc + wc > gr_screen.clip_right ) wc = gr_screen.clip_right - xc;
473                 if ( yc + hc > gr_screen.clip_bottom ) hc = gr_screen.clip_bottom - yc;
474
475                 if ( wc < 1 ) continue;
476                 if ( hc < 1 ) continue;
477
478                 float u = i2fl(Current_font->bm_u[letter] + xd);
479                 float v = i2fl(Current_font->bm_v[letter] + yd);
480
481                 x1 = i2fl(xc + gr_screen.offset_x);
482                 y1 = i2fl(yc + gr_screen.offset_y);
483                 x2 = x1 + i2fl(wc);
484                 y2 = y1 + i2fl(hc);
485
486                 u0 = u_scale * (u * fbw);
487                 v0 = v_scale * (v * fbh);
488
489                 u1 = u_scale * ((u+i2fl(wc)) * fbw);
490                 v1 = v_scale * ((v+i2fl(hc)) * fbh);
491
492                 // maybe go ahead and draw
493                 if (rb_offset == alocsize) {
494                         glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
495                         rb_offset = 0;
496                 }
497
498                 render_buffer[rb_offset].x = x1;
499                 render_buffer[rb_offset].y = y1;
500                 render_buffer[rb_offset].u = u0;
501                 render_buffer[rb_offset].v = v0;
502                 ++rb_offset;
503
504                 render_buffer[rb_offset].x = x1;
505                 render_buffer[rb_offset].y = y2;
506                 render_buffer[rb_offset].u = u0;
507                 render_buffer[rb_offset].v = v1;
508                 ++rb_offset;
509
510                 render_buffer[rb_offset].x = x2;
511                 render_buffer[rb_offset].y = y1;
512                 render_buffer[rb_offset].u = u1;
513                 render_buffer[rb_offset].v = v0;
514                 ++rb_offset;
515
516                 render_buffer[rb_offset].x = x2;
517                 render_buffer[rb_offset].y = y2;
518                 render_buffer[rb_offset].u = u1;
519                 render_buffer[rb_offset].v = v1;
520                 ++rb_offset;
521         }
522
523         if (rb_offset) {
524                 glDrawArrays(GL_TRIANGLE_STRIP, 0, rb_offset);
525         }
526
527         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
528         glDisableClientState(GL_VERTEX_ARRAY);
529 }
530
531 void gr_opengl1_line(int x1,int y1,int x2,int y2)
532 {
533         opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
534
535         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,
536                         gr_screen.clip_right,gr_screen.clip_bottom,return,void(),void());
537
538         float sx1, sy1;
539         float sx2, sy2;
540
541         sx1 = i2fl(x1 + gr_screen.offset_x)+0.5f;
542         sy1 = i2fl(y1 + gr_screen.offset_y)+0.5f;
543         sx2 = i2fl(x2 + gr_screen.offset_x)+0.5f;
544         sy2 = i2fl(y2 + gr_screen.offset_y)+0.5f;
545
546         opengl_alloc_render_buffer(2);
547
548         if ( x1 == x2 && y1 == y2 ) {
549                 render_buffer[0].x = sx1;
550                 render_buffer[0].y = sy1;
551                 render_buffer[0].z = -0.99f;
552
553                 glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
554                                 gr_screen.current_color.blue, gr_screen.current_color.alpha);
555
556                 glEnableClientState(GL_VERTEX_ARRAY);
557                 glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
558
559                 glDrawArrays(GL_POINTS, 0, 1);
560
561                 glDisableClientState(GL_VERTEX_ARRAY);
562
563                 return;
564         }
565
566         if ( x1 == x2 ) {
567                 if ( sy1 < sy2 )    {
568                         sy2 += 0.5f;
569                 } else {
570                         sy1 += 0.5f;
571                 }
572         } else if ( y1 == y2 )  {
573                 if ( sx1 < sx2 )    {
574                         sx2 += 0.5f;
575                 } else {
576                         sx1 += 0.5f;
577                 }
578         }
579
580         render_buffer[0].x = sx2;
581         render_buffer[0].y = sy2;
582         render_buffer[0].z = -0.99f;
583
584         render_buffer[1].x = sx1;
585         render_buffer[1].y = sy1;
586         render_buffer[1].z = -0.99f;
587
588         glColor4ub(gr_screen.current_color.red, gr_screen.current_color.green,
589                         gr_screen.current_color.blue, gr_screen.current_color.alpha);
590
591         glEnableClientState(GL_VERTEX_ARRAY);
592         glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
593
594         glDrawArrays(GL_LINES, 0, 2);
595
596         glDisableClientState(GL_VERTEX_ARRAY);
597 }
598
599 void gr_opengl1_aaline(vertex *v1, vertex *v2)
600 {
601         gr_opengl1_line( fl2i(v1->sx), fl2i(v1->sy), fl2i(v2->sx), fl2i(v2->sy) );
602 }
603
604 void gr_opengl1_gradient(int x1,int y1,int x2,int y2)
605 {
606         int swapped=0;
607
608         if ( !gr_screen.current_color.is_alphacolor )   {
609                 gr_line( x1, y1, x2, y2 );
610                 return;
611         }
612
613         INT_CLIPLINE(x1,y1,x2,y2,gr_screen.clip_left,gr_screen.clip_top,
614                         gr_screen.clip_right,gr_screen.clip_bottom,return,void(),swapped=1);
615
616         opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_BLEND_ALPHA, ZBUFFER_TYPE_NONE );
617
618         int aa = swapped ? 0 : gr_screen.current_color.alpha;
619         int ba = swapped ? gr_screen.current_color.alpha : 0;
620
621         float sx1, sy1;
622         float sx2, sy2;
623
624         sx1 = i2fl(x1 + gr_screen.offset_x)+0.5f;
625         sy1 = i2fl(y1 + gr_screen.offset_y)+0.5f;
626         sx2 = i2fl(x2 + gr_screen.offset_x)+0.5f;
627         sy2 = i2fl(y2 + gr_screen.offset_y)+0.5f;
628
629         if ( x1 == x2 ) {
630                 if ( sy1 < sy2 )    {
631                         sy2 += 0.5f;
632                 } else {
633                         sy1 += 0.5f;
634                 }
635         } else if ( y1 == y2 )  {
636                 if ( sx1 < sx2 )    {
637                         sx2 += 0.5f;
638                 } else {
639                         sx1 += 0.5f;
640                 }
641         }
642
643         opengl_alloc_render_buffer(2);
644
645         render_buffer[0].r = gr_screen.current_color.red;
646         render_buffer[0].g = gr_screen.current_color.green;
647         render_buffer[0].b = gr_screen.current_color.blue;
648         render_buffer[0].a = (ubyte)ba;
649         render_buffer[0].x = sx2;
650         render_buffer[0].y = sy2;
651         render_buffer[0].z = -0.99f;
652
653         render_buffer[1].r = gr_screen.current_color.red;
654         render_buffer[1].g = gr_screen.current_color.green;
655         render_buffer[1].b = gr_screen.current_color.blue;
656         render_buffer[1].a = (ubyte)aa;
657         render_buffer[1].x = sx1;
658         render_buffer[1].y = sy1;
659         render_buffer[1].z = -0.99f;
660
661         glEnableClientState(GL_COLOR_ARRAY);
662         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(rb_t), &render_buffer[0].r);
663
664         glEnableClientState(GL_VERTEX_ARRAY);
665         glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
666
667         glDrawArrays(GL_LINES, 0, 2);
668
669         glDisableClientState(GL_COLOR_ARRAY);
670         glDisableClientState(GL_VERTEX_ARRAY);
671 }
672
673 void gr_opengl1_circle( int xc, int yc, int d )
674 {
675         int p,x, y, r;
676
677         r = d/2;
678         p=3-d;
679         x=0;
680         y=r;
681
682         // Big clip
683         if ( (xc+r) < gr_screen.clip_left ) return;
684         if ( (xc-r) > gr_screen.clip_right ) return;
685         if ( (yc+r) < gr_screen.clip_top ) return;
686         if ( (yc-r) > gr_screen.clip_bottom ) return;
687
688         while(x<y)      {
689                 // Draw the first octant
690                 gr_opengl1_line( xc-y, yc-x, xc+y, yc-x );
691                 gr_opengl1_line( xc-y, yc+x, xc+y, yc+x );
692
693                 if (p<0)
694                         p=p+(x<<2)+6;
695                 else    {
696                         // Draw the second octant
697                         gr_opengl1_line( xc-x, yc-y, xc+x, yc-y );
698                         gr_opengl1_line( xc-x, yc+y, xc+x, yc+y );
699
700                         p=p+((x-y)<<2)+10;
701                         y--;
702                 }
703                 x++;
704         }
705         if(x==y) {
706                 gr_opengl1_line( xc-x, yc-y, xc+x, yc-y );
707                 gr_opengl1_line( xc-x, yc+y, xc+x, yc+y );
708         }
709         return;
710 }
711
712 void gr_opengl1_pixel(int x, int y)
713 {
714         gr_opengl1_line(x, y, x, y);
715 }
716
717
718 // cross fade
719 void gr_opengl1_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
720 {
721         gr_set_bitmap(bmap1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - pct );
722         gr_bitmap(x1, y1);
723
724         gr_set_bitmap(bmap2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, pct );
725         gr_bitmap(x2, y2);
726 }
727
728 void gr_opengl1_flash(int r, int g, int b)
729 {
730         CAP(r,0,255);
731         CAP(g,0,255);
732         CAP(b,0,255);
733
734         if ( r || g || b ) {
735                 opengl1_set_state( TEXTURE_SOURCE_NONE, ALPHA_BLEND_ALPHA_ADDITIVE, ZBUFFER_TYPE_NONE );
736
737                 float x1, x2, y1, y2;
738                 x1 = i2fl(gr_screen.clip_left+gr_screen.offset_x);
739                 y1 = i2fl(gr_screen.clip_top+gr_screen.offset_y);
740                 x2 = i2fl(gr_screen.clip_right+gr_screen.offset_x);
741                 y2 = i2fl(gr_screen.clip_bottom+gr_screen.offset_y);
742
743                 glColor4ub((GLubyte)r, (GLubyte)g, (GLubyte)b, 255);
744
745                 opengl_alloc_render_buffer(4);
746
747                 render_buffer[0].x = x1;
748                 render_buffer[0].y = y1;
749                 render_buffer[0].z = -0.99f;
750
751                 render_buffer[1].x = x1;
752                 render_buffer[1].y = y2;
753                 render_buffer[1].z = -0.99f;
754
755                 render_buffer[2].x = x2;
756                 render_buffer[2].y = y1;
757                 render_buffer[2].z = -0.99f;
758
759                 render_buffer[3].x = x2;
760                 render_buffer[3].y = y2;
761                 render_buffer[3].z = -0.99f;
762
763                 glEnableClientState(GL_VERTEX_ARRAY);
764                 glVertexPointer(3, GL_FLOAT, sizeof(rb_t), &render_buffer[0].x);
765
766                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
767
768                 glDisableClientState(GL_VERTEX_ARRAY);
769         }
770 }
771
772 void gr_opengl1_tmapper( int nverts, vertex **verts, uint flags )
773 {
774         opengl1_tmapper_internal( nverts, verts, flags, 0 );
775 }
776
777 #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (((((x)-(x0))*((y1)-(y0)))/((x1)-(x0)))+(y0))
778
779 void gr_opengl1_scaler(vertex *va, vertex *vb )
780 {
781         float x0, y0, x1, y1;
782         float u0, v0, u1, v1;
783         float clipped_x0, clipped_y0, clipped_x1, clipped_y1;
784         float clipped_u0, clipped_v0, clipped_u1, clipped_v1;
785         float xmin, xmax, ymin, ymax;
786         int dx0, dy0, dx1, dy1;
787
788         //============= CLIP IT =====================
789
790         x0 = va->sx; y0 = va->sy;
791         x1 = vb->sx; y1 = vb->sy;
792
793         xmin = i2fl(gr_screen.clip_left); ymin = i2fl(gr_screen.clip_top);
794         xmax = i2fl(gr_screen.clip_right); ymax = i2fl(gr_screen.clip_bottom);
795
796         u0 = va->u; v0 = va->v;
797         u1 = vb->u; v1 = vb->v;
798
799         // Check for obviously offscreen bitmaps...
800         if ( (y1<=y0) || (x1<=x0) ) return;
801         if ( (x1<xmin ) || (x0>xmax) ) return;
802         if ( (y1<ymin ) || (y0>ymax) ) return;
803
804         clipped_u0 = u0; clipped_v0 = v0;
805         clipped_u1 = u1; clipped_v1 = v1;
806
807         clipped_x0 = x0; clipped_y0 = y0;
808         clipped_x1 = x1; clipped_y1 = y1;
809
810         // Clip the left, moving u0 right as necessary
811         if ( x0 < xmin )        {
812                 clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1);
813                 clipped_x0 = xmin;
814         }
815
816         // Clip the right, moving u1 left as necessary
817         if ( x1 > xmax )        {
818                 clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1);
819                 clipped_x1 = xmax;
820         }
821
822         // Clip the top, moving v0 down as necessary
823         if ( y0 < ymin )        {
824                 clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1);
825                 clipped_y0 = ymin;
826         }
827
828         // Clip the bottom, moving v1 up as necessary
829         if ( y1 > ymax )        {
830                 clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1);
831                 clipped_y1 = ymax;
832         }
833
834         dx0 = fl2i(clipped_x0); dx1 = fl2i(clipped_x1);
835         dy0 = fl2i(clipped_y0); dy1 = fl2i(clipped_y1);
836
837         if (dx1<=dx0) return;
838         if (dy1<=dy0) return;
839
840         //============= DRAW IT =====================
841
842         vertex v[4];
843         vertex *vl[4];
844
845         vl[0] = &v[0];
846         v[0].sx = clipped_x0;
847         v[0].sy = clipped_y0;
848         v[0].sw = va->sw;
849         v[0].z = va->z;
850         v[0].u = clipped_u0;
851         v[0].v = clipped_v0;
852
853         vl[1] = &v[1];
854         v[1].sx = clipped_x1;
855         v[1].sy = clipped_y0;
856         v[1].sw = va->sw;
857         v[1].z = va->z;
858         v[1].u = clipped_u1;
859         v[1].v = clipped_v0;
860
861         vl[2] = &v[2];
862         v[2].sx = clipped_x1;
863         v[2].sy = clipped_y1;
864         v[2].sw = va->sw;
865         v[2].z = va->z;
866         v[2].u = clipped_u1;
867         v[2].v = clipped_v1;
868
869         vl[3] = &v[3];
870         v[3].sx = clipped_x0;
871         v[3].sy = clipped_y1;
872         v[3].sw = va->sw;
873         v[3].z = va->z;
874         v[3].u = clipped_u0;
875         v[3].v = clipped_v1;
876
877         opengl1_tmapper_internal( 4, vl, TMAP_FLAG_TEXTURED, 1 );
878 }