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