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