1 /* This code is (C) AllegroGL contributors, and double licensed under
2 * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3 */
4 /** \file glvtable.c
5 * \brief Allegro->OpenGL conversion vtable.
6 */
7
8 #include <string.h>
9
10 #include <allegro.h>
11
12 #ifdef ALLEGRO_WINDOWS
13 #include <winalleg.h>
14 #endif
15
16 #include "alleggl.h"
17 #include "allglint.h"
18 #include "glvtable.h"
19 #include <allegro/internal/aintern.h>
20 #ifdef ALLEGRO_MACOSX
21 #include <OpenGL/glu.h>
22 #else
23 #include <GL/glu.h>
24 #endif
25
26
27 static GFX_VTABLE allegro_gl_screen_vtable;
28 static GLuint __allegro_gl_pool_texture = 0;
29
30 static GLuint __allegro_gl_dummy_texture = 0; /* For ATI Rage Pro */
31
32 static int __agl_owning_drawing_pattern_tex = FALSE;
33 GLuint __agl_drawing_pattern_tex = 0;
34 BITMAP *__agl_drawing_pattern_bmp = 0;
35 static int __agl_drawing_mode = DRAW_MODE_SOLID;
36
37
38 /** \defgroup glvtable Allegro Graphics Driver
39 * These functions are used to implement Allegro function over an
40 * OpenGL screen.
41 *
42 * Keep in mind that some restictions mentioned in Allegro docs about video
43 * bitmaps and the screen do not apply when using AllegroGL GFX driver. Namely:
44 * - Reading from video bitmaps is just as fast as reading from memory bitmaps.
45 * - Doing translucent/transparent drawing on the screen can be very fast if
46 * the source is a video bitmap.
47 * - Drawing from video bitmap to a video bitmap will be pretty fast on modern
48 * GFX cards with appropiate drivers installed.
49 * - There are dozen of places in the Allegro docs where it says that a memory
50 * bitmap must be used (drawing_mode(), polygon3d(), stretch_sprite() etc.).
51 * This doesn't apply when AllegroGL is used. You can also use video bitmaps
52 * and it will be quite fast.
53 *
54 * \{
55 */
56
57
58 /* Computes the next power of two if the number wasn't a power of two to start
59 * with. Ref: http://bob.allegronetwork.com/prog/tricks.html#roundtonextpowerof2
60 */
__allegro_gl_make_power_of_2(int x)61 int __allegro_gl_make_power_of_2(int x) {
62 x--;
63 x |= (x >> 1);
64 x |= (x >> 2);
65 x |= (x >> 4);
66 x |= (x >> 8);
67 x |= (x >> 16);
68 x++;
69 return x;
70 }
71
72
73
74 /* allegro_gl_drawing_mode (GFX_DRIVER vtable entry):
75 * Sets the drawing mode. Same implementation to all GFX vtables.
76 */
allegro_gl_drawing_mode(void)77 void allegro_gl_drawing_mode(void) {
78 if (__agl_drawing_mode == _drawing_mode)
79 return;
80
81 switch (__agl_drawing_mode) {
82 case DRAW_MODE_TRANS:
83 glDisable(GL_BLEND);
84 break;
85 case DRAW_MODE_XOR:
86 glDisable(GL_COLOR_LOGIC_OP);
87 break;
88 case DRAW_MODE_COPY_PATTERN:
89 glDisable(GL_TEXTURE_2D);
90 glBindTexture(GL_TEXTURE_2D, 0);
91 if (__agl_owning_drawing_pattern_tex && __agl_drawing_pattern_tex)
92 glDeleteTextures(1, &__agl_drawing_pattern_tex);
93 __agl_drawing_pattern_tex = 0;
94 __agl_drawing_pattern_bmp = 0;
95 break;
96 }
97
98 __agl_drawing_mode = _drawing_mode;
99
100 switch (_drawing_mode) {
101 case DRAW_MODE_TRANS:
102 glEnable(GL_BLEND);
103 break;
104
105 case DRAW_MODE_XOR:
106 glEnable(GL_COLOR_LOGIC_OP);
107 glLogicOp(GL_XOR);
108 break;
109
110 case DRAW_MODE_COPY_PATTERN:
111 if (is_memory_bitmap(_drawing_pattern)) {
112 __agl_drawing_pattern_tex =
113 allegro_gl_make_texture(_drawing_pattern);
114 __agl_drawing_pattern_bmp = _drawing_pattern;
115 __agl_owning_drawing_pattern_tex = TRUE;
116 }
117 else if (is_video_bitmap(_drawing_pattern)) {
118 AGL_VIDEO_BITMAP *bmp = _drawing_pattern->extra;
119 __agl_drawing_pattern_tex = bmp->tex;
120 __agl_drawing_pattern_bmp = bmp->memory_copy;
121 __agl_owning_drawing_pattern_tex = FALSE;
122 }
123
124 glEnable(GL_TEXTURE_2D);
125 glBindTexture(GL_TEXTURE_2D, __agl_drawing_pattern_tex);
126
127 break;
128 }
129 }
130
131
split_color(int color,GLubyte * r,GLubyte * g,GLubyte * b,GLubyte * a,int color_depth)132 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
133 int color_depth)
134 {
135 AGL_LOG(2, "glvtable.c:split_color\n");
136 *r = getr_depth(color_depth, color);
137 *g = getg_depth(color_depth, color);
138 *b = getb_depth(color_depth, color);
139 if (color_depth == 32)
140 *a = geta_depth(color_depth, color);
141 else
142 *a = 255;
143 }
144
145
146 /* allegro_gl_created_sub_bitmap:
147 */
allegro_gl_created_sub_bitmap(BITMAP * bmp,BITMAP * parent)148 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
149 {
150 bmp->extra = parent;
151 }
152
153
154 /* static void allegro_gl_screen_acquire(struct BITMAP *bmp) */
155 /** acquire_bitmap(screen) overload.
156 * This doesn't do anything, since OpenGL rendering context
157 * doesn't need locking. You don't need to call this function
158 * in your program.
159 */
allegro_gl_screen_acquire(struct BITMAP * bmp)160 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
161
162
163
164 /* static void allegro_gl_screen_release(struct BITMAP *bmp) */
165 /** release_bitmap(screen) overload.
166 * This doesn't do anything, since OpenGL rendering context
167 * doesn't need locking. You don't need to call this function
168 * in your program.
169 */
allegro_gl_screen_release(struct BITMAP * bmp)170 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
171
172
173
allegro_gl_screen_getpixel(struct BITMAP * bmp,int x,int y)174 static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y)
175 {
176 GLubyte pixel[3];
177 AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
178 if (bmp->clip && (x < bmp->cl || x >= bmp->cr
179 || y < bmp->ct || y >= bmp->cb)) {
180 return -1;
181 }
182 if (is_sub_bitmap(bmp)) {
183 x += bmp->x_ofs;
184 y += bmp->y_ofs;
185 }
186 glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
187
188 return makecol_depth(bitmap_color_depth(screen),
189 pixel[0], pixel[1], pixel[2]);
190 }
191
192
193
allegro_gl_screen_putpixel(struct BITMAP * bmp,int x,int y,int color)194 static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y,
195 int color)
196 {
197 GLubyte r, g, b, a;
198 AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n");
199 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
200 if (bmp->clip && (x < bmp->cl || x >= bmp->cr
201 || y < bmp->ct || y >= bmp->cb)) {
202 return;
203 }
204
205 if (is_sub_bitmap(bmp)) {
206 x += bmp->x_ofs;
207 y += bmp->y_ofs;
208 }
209
210 glColor4ub(r, g, b, a);
211 glBegin(GL_POINTS);
212 glVertex2f(x, y);
213 glEnd();
214 }
215
216
217
allegro_gl_screen_vline(struct BITMAP * bmp,int x,int y1,int y2,int color)218 static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2,
219 int color)
220 {
221 GLubyte r, g, b, a;
222 AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n");
223
224 if (y1 > y2) {
225 int temp = y1;
226 y1 = y2;
227 y2 = temp;
228 }
229
230 if (bmp->clip) {
231 if ((x < bmp->cl) || (x >= bmp->cr)) {
232 return;
233 }
234 if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
235 return;
236 }
237 if (y1 < bmp->ct) {
238 y1 = bmp->ct;
239 }
240 if (y2 >= bmp->cb) {
241 y2 = bmp->cb - 1;
242 }
243 }
244
245 if (is_sub_bitmap(bmp)) {
246 x += bmp->x_ofs;
247 y1 += bmp->y_ofs;
248 y2 += bmp->y_ofs;
249 }
250
251 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
252
253 glColor4ub(r, g, b, a);
254 glBegin(GL_LINES);
255 glVertex2f(x, y1);
256 glVertex2f(x, y2 + 0.325 * 3);
257 glEnd();
258
259 return;
260 }
261
262
263
allegro_gl_screen_hline(struct BITMAP * bmp,int x1,int y,int x2,int color)264 static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2,
265 int color)
266 {
267 GLubyte r, g, b, a;
268 AGL_LOG(2, "glvtable.c:allegro_gl_hline\n");
269
270 if (x1 > x2) {
271 int temp = x1;
272 x1 = x2;
273 x2 = temp;
274 }
275 if (bmp->clip) {
276 if ((y < bmp->ct) || (y >= bmp->cb)) {
277 return;
278 }
279 if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
280 return;
281 }
282 if (x1 < bmp->cl) {
283 x1 = bmp->cl;
284 }
285 if (x2 >= bmp->cr) {
286 x2 = bmp->cr - 1;
287 }
288 }
289 if (is_sub_bitmap(bmp)) {
290 x1 += bmp->x_ofs;
291 x2 += bmp->x_ofs;
292 y += bmp->y_ofs;
293 }
294
295 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
296
297 glColor4ub(r, g, b, a);
298 glBegin(GL_LINES);
299 glVertex2f(x1 - 0.325, y);
300 glVertex2f(x2 + 0.325 * 2, y);
301 glEnd();
302
303 return;
304 }
305
306
307
allegro_gl_screen_line(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)308 static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2,
309 int y2, int color)
310 {
311 GLubyte r, g, b, a;
312 AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n");
313
314 if (bmp->clip) {
315 glPushAttrib(GL_SCISSOR_BIT);
316 glEnable(GL_SCISSOR_TEST);
317 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
318 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
319 }
320 if (is_sub_bitmap(bmp)) {
321 x1 += bmp->x_ofs;
322 x2 += bmp->x_ofs;
323 y1 += bmp->y_ofs;
324 y2 += bmp->y_ofs;
325 }
326
327 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
328
329 glColor4ub(r, g, b, a);
330 glBegin(GL_LINES);
331 glVertex2f(x1 + 0.1625, y1 + 0.1625);
332 glVertex2f(x2 + 0.1625, y2 + 0.1625);
333 glEnd();
334
335 /* OpenGL skips the endpoint when drawing lines */
336 glBegin(GL_POINTS);
337 glVertex2f(x2 + 0.1625, y2 + 0.1625);
338 glEnd();
339
340 if (bmp->clip) {
341 glPopAttrib();
342 }
343
344 return;
345 }
346
347
348 #define SET_TEX_COORDS(x, y) \
349 do { \
350 if (__agl_drawing_pattern_tex) { \
351 glTexCoord2f ( \
352 (x - _drawing_x_anchor) / (float)__agl_drawing_pattern_bmp->w,\
353 (y - _drawing_y_anchor) / (float)__agl_drawing_pattern_bmp->h \
354 ); \
355 } \
356 } while(0)
357
358
allegro_gl_screen_rectfill(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)359 void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1,
360 int x2, int y2, int color)
361 {
362 GLubyte r, g, b, a;
363 GLfloat old_col[4];
364 AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n");
365
366 if (x1 > x2) {
367 int temp = x1;
368 x1 = x2;
369 x2 = temp;
370 }
371
372 if (y1 > y2) {
373 int temp = y1;
374 y1 = y2;
375 y2 = temp;
376 }
377
378 if (bmp->clip) {
379 if ((x1 > bmp->cr) || (x2 < bmp->cl)) {
380 return;
381 }
382 if (x1 < bmp->cl) {
383 x1 = bmp->cl;
384 }
385 if (x2 > bmp->cr) {
386 x2 = bmp->cr;
387 }
388 if ((y1 > bmp->cb) || (y2 < bmp->ct)) {
389 return;
390 }
391 if (y1 < bmp->ct) {
392 y1 = bmp->ct;
393 }
394 if (y2 > bmp->cb) {
395 y2 = bmp->cb;
396 }
397 }
398 if (is_sub_bitmap(bmp)) {
399 x1 += bmp->x_ofs;
400 x2 += bmp->x_ofs;
401 y1 += bmp->y_ofs;
402 y2 += bmp->y_ofs;
403 }
404
405 glGetFloatv(GL_CURRENT_COLOR, old_col);
406 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
407 glColor4ub(r, g, b, a);
408
409 glBegin(GL_QUADS);
410 SET_TEX_COORDS(x1, y1);
411 glVertex2f(x1, y1);
412 SET_TEX_COORDS(x2, y1);
413 glVertex2f(x2, y1);
414 SET_TEX_COORDS(x2, y2);
415 glVertex2f(x2, y2);
416 SET_TEX_COORDS(x1, y2);
417 glVertex2f(x1, y2);
418 glEnd();
419
420 glColor4fv(old_col);
421
422 return;
423 }
424
425
426
allegro_gl_screen_triangle(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int x3,int y3,int color)427 static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1,
428 int x2, int y2, int x3, int y3, int color)
429 {
430 GLubyte r, g, b, a;
431 AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n");
432
433 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
434
435 if (bmp->clip) {
436 glPushAttrib(GL_SCISSOR_BIT);
437 glEnable(GL_SCISSOR_TEST);
438 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
439 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
440 }
441 if (is_sub_bitmap(bmp)) {
442 x1 += bmp->x_ofs;
443 y1 += bmp->y_ofs;
444 x2 += bmp->x_ofs;
445 y2 += bmp->y_ofs;
446 x3 += bmp->x_ofs;
447 y3 += bmp->y_ofs;
448 }
449
450 glColor4ub(r, g, b, a);
451 glBegin(GL_TRIANGLES);
452 SET_TEX_COORDS(x1, y1);
453 glVertex2f(x1, y1);
454 SET_TEX_COORDS(x2, y2);
455 glVertex2f(x2, y2);
456 SET_TEX_COORDS(x3, y3);
457 glVertex2f(x3, y3);
458 glEnd();
459
460 if (bmp->clip) {
461 glPopAttrib();
462 }
463 }
464
465
466
467 #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \
468 width, height) { \
469 if (dest->clip) { \
470 if ((dest_x >= dest->cr) || (dest_y >= dest->cb) \
471 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \
472 width = 0; \
473 } \
474 if (dest_x < dest->cl) { \
475 width += dest_x - dest->cl; \
476 source_x -= dest_x - dest->cl; \
477 dest_x = dest->cl; \
478 } \
479 if (dest_y < dest->ct) { \
480 height += dest_y - dest->ct; \
481 source_y -= dest_y - dest->ct; \
482 dest_y = dest->ct; \
483 } \
484 if (dest_x + width > dest->cr) { \
485 width = dest->cr - dest_x; \
486 } \
487 if (dest_y + height > dest->cb) { \
488 height = dest->cb - dest_y; \
489 } \
490 } \
491 if (source->clip) { \
492 if ((source_x >= source->cr) || (source_y >= source->cb) \
493 || (source_x + width < source->cl) \
494 || (source_y + height < source->ct)) { \
495 width = 0; \
496 } \
497 if (source_x < source->cl) { \
498 width += source_x - source->cl; \
499 dest_x -= source_x - source->cl; \
500 source_x = source->cl; \
501 } \
502 if (source_y < source->ct) { \
503 height += source_y - source->ct; \
504 dest_y -= source_y - source->ct; \
505 source_y = source->ct; \
506 } \
507 if (source_x + width > source->cr) { \
508 width = source->cr - source_x; \
509 } \
510 if (source_y + height > source->cb) { \
511 height = source->cb - source_y; \
512 } \
513 } \
514 }
515
516
517
518
allegro_gl_screen_blit_from_memory(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)519 static void allegro_gl_screen_blit_from_memory(
520 struct BITMAP *source, struct BITMAP *dest,
521 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
522 {
523 GLfloat saved_zoom_x, saved_zoom_y;
524 GLint saved_row_length;
525 BITMAP *temp = NULL;
526 void *data;
527 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n");
528
529 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
530 width, height);
531
532 if (width <= 0 || height <= 0) {
533 return;
534 }
535
536
537 if (is_sub_bitmap(dest)) {
538 dest_x += dest->x_ofs;
539 dest_y += dest->y_ofs;
540 }
541
542 /* Note: We don't need to offset the source bitmap coordinates
543 * because we use source->line[] directly, which is already offsetted for
544 * us.
545 */
546 data = source->line[source_y]
547 + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source));
548
549 /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
550 * the bitmap into something GL can understand - 24-bpp should do it.
551 */
552 if (!allegro_gl_extensions_GL.EXT_packed_pixels
553 && bitmap_color_depth(source) < 24) {
554 temp = create_bitmap_ex(24, width, height);
555
556 if (temp) {
557 blit(source, temp, source_x, source_y, 0, 0, width, height);
558 source_x = 0;
559 source_y = 0;
560 data = temp->line[0];
561 }
562 else {
563 /* XXX <rohannessian> Report error? */
564 return;
565 }
566 source = temp;
567 }
568
569
570 /* Save state */
571 glGetFloatv(GL_ZOOM_X, &saved_zoom_x);
572 glGetFloatv(GL_ZOOM_Y, &saved_zoom_y);
573 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
574
575 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
576
577 glRasterPos2i(dest_x, dest_y);
578
579 /* XXX <rohannessian> I wonder if it would be faster to use glDrawPixels()
580 * one line at a time instead of playing with the Zoom factor.
581 */
582 glPixelZoom (1.0, -1.0);
583 glPixelStorei(GL_UNPACK_ROW_LENGTH,
584 (source->line[1] - source->line[0])
585 / BYTES_PER_PIXEL(source->vtable->color_depth));
586
587 glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0),
588 __allegro_gl_get_bitmap_type(source, 0), data);
589
590 /* Restore state */
591 glPixelZoom(saved_zoom_x, saved_zoom_y);
592 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
593
594 if (temp) {
595 destroy_bitmap(temp);
596 }
597 return;
598 }
599
600
601
allegro_gl_screen_blit_to_memory(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)602 static void allegro_gl_screen_blit_to_memory(
603 struct BITMAP *source, struct BITMAP *dest,
604 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
605 {
606 GLint saved_row_length;
607 GLint saved_alignment;
608 GLint saved_pack_invert;
609
610 BITMAP *bmp = NULL;
611
612 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n");
613
614 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
615 width, height);
616
617 if (is_sub_bitmap(source)) {
618 source_x += source->x_ofs;
619 source_y += source->y_ofs;
620 }
621 if (is_sub_bitmap(dest)) {
622 dest_x += dest->x_ofs;
623 dest_y += dest->y_ofs;
624 }
625
626 if (width <= 0 || height <= 0) {
627 return;
628 }
629
630 /* Note that glPixelZoom doesn't affect reads -- so we have to do a flip.
631 * We can do this by reading into a temporary bitmap then flipping that to
632 * the destination, -OR- use the GL_MESA_pack_invert extension to do it
633 * for us.
634 *
635 * If GL_EXT_packed_pixels isn't supported, then we can't use
636 * MESA_pack_invert on 16-bpp bitmaps or less.
637 */
638
639 if ( !allegro_gl_extensions_GL.MESA_pack_invert
640 || (!allegro_gl_extensions_GL.EXT_packed_pixels
641 && bitmap_color_depth(dest) < 24)) {
642
643 /* XXX <rohannessian> Bitmap format should be the same as the source
644 * dest bitmap!
645 */
646 if ((!allegro_gl_extensions_GL.EXT_packed_pixels
647 && bitmap_color_depth(dest) < 24)) {
648 bmp = create_bitmap_ex(24, width, height);
649 }
650 else {
651 bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height);
652 }
653 if (!bmp)
654 return;
655 }
656
657 glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length);
658 glGetIntegerv(GL_PACK_ALIGNMENT, &saved_alignment);
659 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
660 glPixelStorei(GL_PACK_ALIGNMENT, 1);
661
662 if (!allegro_gl_extensions_GL.MESA_pack_invert) {
663
664 glReadPixels(source_x, source->h - source_y - height, width, height,
665 __allegro_gl_get_bitmap_color_format(bmp, 0),
666 __allegro_gl_get_bitmap_type(bmp, 0), bmp->dat);
667 }
668 else {
669 glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert);
670 glPixelStorei(GL_PACK_INVERT_MESA, TRUE);
671 glPixelStorei(GL_PACK_ROW_LENGTH,
672 (dest->line[1] - dest->line[0])
673 / BYTES_PER_PIXEL(dest->vtable->color_depth));
674
675 glReadPixels(source_x, source->h - source_y - height, width, height,
676 __allegro_gl_get_bitmap_color_format(dest, 0),
677 __allegro_gl_get_bitmap_type(dest, 0), dest->line[0]);
678
679 glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert);
680 }
681
682 glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length);
683 glPixelStorei(GL_PACK_ALIGNMENT, saved_alignment);
684
685 /* Flip image if needed (glPixelZoom doesn't affect reads) */
686 if (bmp) {
687
688 int y, dy;
689
690 for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) {
691 blit(bmp, dest, 0, y, dest_x, dy, width, 1);
692 }
693
694 destroy_bitmap(bmp);
695 }
696
697 return;
698 }
699
700
701
702
allegro_gl_screen_blit_to_self(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)703 void allegro_gl_screen_blit_to_self (
704 struct BITMAP *source, struct BITMAP *dest,
705 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
706 {
707 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n");
708
709 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
710 width, height);
711
712 if (is_sub_bitmap(source)) {
713 source_x += source->x_ofs;
714 source_y += source->y_ofs;
715 }
716 if (is_sub_bitmap(dest)) {
717 dest_x += dest->x_ofs;
718 dest_y += dest->y_ofs;
719 }
720
721 if (width <= 0 || height <= 0) {
722 return;
723 }
724
725 /* screen -> screen */
726 if (is_screen_bitmap(source) && is_screen_bitmap(dest)) {
727 glRasterPos2i(dest_x, dest_y + height - 1);
728 glCopyPixels(source_x, SCREEN_H - source_y - height, width, height,
729 GL_COLOR);
730 }
731 /* video -> screen */
732 else if (is_screen_bitmap(dest) && is_video_bitmap(source)) {
733 AGL_VIDEO_BITMAP *vid;
734 BITMAP *source_parent = source;
735 GLfloat current_color[4];
736
737 while (source_parent->id & BMP_ID_SUB) {
738 source_parent = (BITMAP *)source_parent->extra;
739 }
740 vid = source_parent->extra;
741
742 glGetFloatv(GL_CURRENT_COLOR, current_color);
743 glColor4ub(255, 255, 255, 255);
744
745 while (vid) {
746 int sx, sy; /* source coordinates */
747 int dx, dy; /* destination coordinates */
748 int w, h;
749
750 if (source_x >= vid->x_ofs + vid->memory_copy->w ||
751 source_y >= vid->y_ofs + vid->memory_copy->h ||
752 vid->x_ofs >= source_x + width ||
753 vid->y_ofs >= source_y + height) {
754 vid = vid->next;
755 continue;
756 }
757
758 sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;
759 w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)
760 - vid->x_ofs - sx;
761 sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;
762 h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height)
763 - vid->y_ofs - sy;
764
765 dx = dest_x + vid->x_ofs + sx - source_x;
766 dy = dest_y + vid->y_ofs + sy - source_y;
767
768 glEnable(vid->target);
769 glBindTexture(vid->target, vid->tex);
770
771 if (vid->target == GL_TEXTURE_2D) {
772 float tx = sx / (float)vid->memory_copy->w;
773 float ty = sy / (float)vid->memory_copy->h;
774 float tw = w / (float)vid->memory_copy->w;
775 float th = h / (float)vid->memory_copy->h;
776
777 glBegin(GL_QUADS);
778 glTexCoord2f(tx, ty);
779 glVertex2f(dx, dy);
780 glTexCoord2f(tx, ty + th);
781 glVertex2f(dx, dy + h);
782 glTexCoord2f(tx + tw, ty + th);
783 glVertex2f(dx + w, dy + h);
784 glTexCoord2f(tx + tw, ty);
785 glVertex2f(dx + w, dy);
786 glEnd();
787 }
788 else {
789 glBegin(GL_QUADS);
790 glTexCoord2i(sx, sy);
791 glVertex2f(dx, dy);
792 glTexCoord2i(sx, sy + h);
793 glVertex2f(dx, dy + h);
794 glTexCoord2i(sx + w, sy + h);
795 glVertex2f(dx + w, dy + h);
796 glTexCoord2i(sx + w, sy);
797 glVertex2f(dx + w, dy);
798 glEnd();
799 }
800
801 glBindTexture(vid->target, 0);
802 glDisable(vid->target);
803
804 vid = vid->next;
805 }
806
807 glColor4fv(current_color);
808 }
809 /* screen -> video */
810 else if (is_screen_bitmap(source) && is_video_bitmap(dest)) {
811
812 AGL_VIDEO_BITMAP *vid;
813 BITMAP *source_parent = source;
814
815 while (source_parent->id & BMP_ID_SUB) {
816 source_parent = (BITMAP *)source_parent->extra;
817 }
818
819 vid = dest->extra;
820
821 while (vid) {
822 int sx, sy; /* source coordinates */
823 int dx, dy; /* destination coordinates */
824 int w, h;
825
826 if (dest_x >= vid->x_ofs + vid->memory_copy->w ||
827 dest_y >= vid->y_ofs + vid->memory_copy->h ||
828 vid->x_ofs >= dest_x + width ||
829 vid->y_ofs >= dest_y + height) {
830 vid = vid->next;
831 continue;
832 }
833
834 dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;
835 w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)
836 - vid->x_ofs - dx;
837 dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;
838 h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)
839 - vid->y_ofs - dy;
840
841 sx = source_x + vid->x_ofs + dx - dest_x;
842 sy = source_y + vid->y_ofs + dy - dest_y;
843
844 /* We cannot use glCopyTexSubImage2D() here because it will flip the image. */
845 allegro_gl_screen_blit_to_memory(source, vid->memory_copy,
846 sx, sy, dx, dy, w, h);
847
848 allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0,
849 vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h);
850
851 vid = vid->next;
852 }
853 }
854 else if (is_video_bitmap(source) && is_video_bitmap(dest)) {
855 allegro_gl_video_blit_to_self(source, dest, source_x, source_y,
856 dest_x, dest_y, width, height);
857 }
858 }
859
860
861
allegro_gl_upload_and_display_texture(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,GLint format,GLint type)862 void allegro_gl_upload_and_display_texture(struct BITMAP *source,
863 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
864 int flip_dir, GLint format, GLint type)
865 {
866 float tx, ty;
867 GLint saved_row_length;
868 int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
869 int i, j;
870
871 glEnable(GL_ALPHA_TEST);
872 glAlphaFunc(GL_GREATER, 0.0f);
873
874 glEnable(GL_TEXTURE_2D);
875 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
876
877 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
878 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
879
880 glPixelStorei(GL_UNPACK_ROW_LENGTH,
881 (source->line[1] - source->line[0]) / bytes_per_pixel);
882
883 for (i = 0; i <= abs(width) / 256; i++) {
884 for (j = 0; j <= abs(height) / 256; j++) {
885
886 void *data = source->line[source_y + j * 256]
887 + (source_x + i * 256) * bytes_per_pixel;
888 int w = abs(width) - i * 256;
889 int h = abs(height) - j * 256;
890 int dx = dest_x + i * 256;
891 int dy = dest_y + j * 256;
892
893 w = (w & -256) ? 256 : w;
894 h = (h & -256) ? 256 : h;
895
896 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
897
898 tx = (float)w / 256.;
899 ty = (float)h / 256.;
900
901 if (flip_dir & AGL_H_FLIP) {
902 dx = 2*dest_x + width - dx;
903 w = -w;
904 }
905
906 if (flip_dir & AGL_V_FLIP) {
907 dy = 2*dest_y + height - dy;
908 h = -h;
909 }
910
911 if (width < 0) w = -w;
912 if (height < 0) h = -h;
913
914 glBegin(GL_QUADS);
915 glTexCoord2f(0., 0.);
916 glVertex2i(dx, dy);
917 glTexCoord2f(0., ty);
918 glVertex2i(dx, dy + h);
919 glTexCoord2f(tx, ty);
920 glVertex2i(dx + w, dy + h);
921 glTexCoord2f(tx, 0.);
922 glVertex2i(dx + w, dy);
923 glEnd();
924 }
925 }
926
927 /* Restore state */
928 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
929 glBindTexture(GL_TEXTURE_2D, 0);
930 glDisable(GL_TEXTURE_2D);
931 glDisable(GL_ALPHA_TEST);
932
933 return;
934 }
935
936
937
do_screen_masked_blit_standard(GLint format,GLint type,struct BITMAP * temp,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)938 static void do_screen_masked_blit_standard(GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
939 {
940 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
941
942 if (blit_type & AGL_NO_ROTATION) {
943 GLint saved_row_length;
944 float dx = dest_x, dy = dest_y;
945 GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y;
946
947 glEnable(GL_ALPHA_TEST);
948 glAlphaFunc(GL_GREATER, 0.0f);
949
950 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
951 glGetFloatv(GL_ZOOM_X, &old_zoom_x);
952 glGetFloatv(GL_ZOOM_Y, &old_zoom_y);
953
954 if (flip_dir & AGL_H_FLIP) {
955 zoom_x = -1.0f;
956 /* Without the -0.5 below, we get an invalid position,
957 * and the operation is ignored by OpenGL. */
958 dx += abs(width) - 0.5;
959 }
960 else {
961 zoom_x = (float) width / abs(width);
962 }
963
964 if (flip_dir & AGL_V_FLIP) {
965 zoom_y = 1.0f;
966 dy += abs(height) - 0.5;
967 }
968 else {
969 zoom_y = -1.0f * width / abs(width);
970 }
971
972 glRasterPos2f(dx, dy);
973 glPixelZoom(zoom_x, zoom_y);
974 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
975 glPixelStorei(GL_UNPACK_ROW_LENGTH,
976 (temp->line[1] - temp->line[0])
977 / BYTES_PER_PIXEL(bitmap_color_depth(temp)));
978
979 glDrawPixels(abs(width), abs(height), format, type, temp->line[0]);
980
981 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
982 glPixelZoom(old_zoom_x, old_zoom_y);
983 }
984 else {
985 allegro_gl_upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height,
986 flip_dir, format, type);
987 }
988
989 glPopAttrib();
990 }
991
992
993
screen_masked_blit_standard(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)994 static void screen_masked_blit_standard(struct BITMAP *source,
995 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
996 int flip_dir, int blit_type)
997 {
998 BITMAP *temp = NULL;
999
1000 GLint format, type;
1001
1002 format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED);
1003 type = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED);
1004
1005 temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source,
1006 source_x, source_y, abs(width), abs(height),
1007 &type, &format);
1008
1009 if (temp) {
1010 source = temp;
1011 }
1012
1013 do_screen_masked_blit_standard(format, type, source, source_x, source_y,
1014 dest_x, dest_y, width, height, flip_dir, blit_type);
1015
1016 if (temp) {
1017 destroy_bitmap(temp);
1018 }
1019
1020 return;
1021 }
1022
1023
1024
__allegro_gl_init_nv_register_combiners(BITMAP * bmp)1025 static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp)
1026 {
1027 GLfloat mask_color[4];
1028 int depth = bitmap_color_depth(bmp);
1029 int color = bitmap_mask_color(bmp);
1030
1031 mask_color[0] = getr_depth(depth, color) / 255.;
1032 mask_color[1] = getg_depth(depth, color) / 255.;
1033 mask_color[2] = getb_depth(depth, color) / 255.;
1034 mask_color[3] = 0.;
1035
1036 glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color);
1037 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
1038 glEnable(GL_REGISTER_COMBINERS_NV);
1039
1040 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
1041 GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
1042 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
1043 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
1044 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
1045 GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1046 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
1047 GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB);
1048 glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV,
1049 GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE,
1050 GL_FALSE, GL_FALSE, GL_FALSE);
1051
1052 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
1053 GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1054 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
1055 GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
1056 glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV,
1057 GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE,
1058 GL_TRUE, GL_FALSE, GL_FALSE);
1059
1060 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
1061 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1062 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO,
1063 GL_UNSIGNED_INVERT_NV, GL_RGB);
1064 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO,
1065 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1066 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO,
1067 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
1068 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV,
1069 GL_UNSIGNED_IDENTITY_NV, GL_BLUE);
1070
1071 return;
1072 }
1073
1074
1075
screen_masked_blit_nv_register(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1076 static void screen_masked_blit_nv_register(struct BITMAP *source,
1077 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1078 int flip_dir, int blit_type)
1079 {
1080 BITMAP *temp = NULL;
1081 GLint type = __allegro_gl_get_bitmap_type(source, 0);
1082 GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
1083
1084 if (type == -1) {
1085 temp = create_bitmap_ex(24, width, height);
1086 if (!temp) {
1087 return;
1088 }
1089 blit(source, temp, source_x, source_y, 0, 0, width, height);
1090 source = temp;
1091 source_x = 0;
1092 source_y = 0;
1093
1094 type = __allegro_gl_get_bitmap_type(source, 0);
1095 format = __allegro_gl_get_bitmap_color_format(source, 0);
1096 }
1097
1098 glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1099 __allegro_gl_init_nv_register_combiners(source);
1100
1101 allegro_gl_upload_and_display_texture(source, source_x, source_y, dest_x, dest_y,
1102 width, height, flip_dir, format, type);
1103
1104 glPopAttrib();
1105
1106 if (temp) {
1107 destroy_bitmap(temp);
1108 }
1109 return;
1110 }
1111
1112
1113
__allegro_gl_init_combine_textures(BITMAP * bmp)1114 static void __allegro_gl_init_combine_textures(BITMAP *bmp)
1115 {
1116 GLubyte mask_color[4];
1117
1118 split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1],
1119 &mask_color[2], &mask_color[3], bitmap_color_depth(bmp));
1120 glColor4ubv(mask_color);
1121
1122 glActiveTexture(GL_TEXTURE0);
1123 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1124 glEnable(GL_TEXTURE_2D);
1125 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
1126 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1127 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
1128 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
1129
1130 /* Dot the result of the subtract with itself. Store it in the alpha
1131 * component. The alpha should then be 0 if the color fragment was equal to
1132 * the mask color, or >0 otherwise.
1133 */
1134 glActiveTexture(GL_TEXTURE1);
1135 glEnable(GL_TEXTURE_2D);
1136 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1137 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
1138 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1139 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
1140
1141 /* Put the original RGB value in its place */
1142
1143 glActiveTexture(GL_TEXTURE2);
1144 glEnable(GL_TEXTURE_2D);
1145 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1146 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
1147 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1148 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1149 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1150
1151 glActiveTexture(GL_TEXTURE0);
1152
1153 return;
1154 }
1155
1156
1157
screen_masked_blit_combine_tex(struct BITMAP * source,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1158 static void screen_masked_blit_combine_tex(struct BITMAP *source,
1159 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1160 int flip_dir, int blit_type)
1161 {
1162 float tx, ty;
1163 BITMAP *temp = NULL;
1164 GLint saved_row_length;
1165 GLint type = __allegro_gl_get_bitmap_type(source, 0);
1166 GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
1167 int bytes_per_pixel;
1168 int i, j;
1169 GLfloat current_color[4];
1170
1171 if (type == -1) {
1172 temp = create_bitmap_ex(24, width, height);
1173 if (!temp)
1174 return;
1175 blit(source, temp, source_x, source_y, 0, 0, width, height);
1176 source = temp;
1177 source_x = 0;
1178 source_y = 0;
1179
1180 type = __allegro_gl_get_bitmap_type(source, 0);
1181 format = __allegro_gl_get_bitmap_color_format(source, 0);
1182 }
1183
1184 glEnable(GL_TEXTURE_2D);
1185 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1186
1187 glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1188 glGetFloatv(GL_CURRENT_COLOR, current_color);
1189 __allegro_gl_init_combine_textures(source);
1190
1191 glActiveTexture(GL_TEXTURE0);
1192 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1193 glActiveTexture(GL_TEXTURE1);
1194 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1195 glActiveTexture(GL_TEXTURE2);
1196 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
1197 glActiveTexture(GL_TEXTURE0);
1198
1199 bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
1200
1201 glEnable(GL_ALPHA_TEST);
1202 glAlphaFunc(GL_GREATER, 0.0f);
1203
1204 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
1205 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1206
1207 glPixelStorei(GL_UNPACK_ROW_LENGTH,
1208 (source->line[1] - source->line[0]) / bytes_per_pixel);
1209
1210 for (i = 0; i <= width / 256; i++) {
1211 for (j = 0; j <= height / 256; j++) {
1212
1213 void *data = source->line[source_y + j * 256]
1214 + (source_x + i * 256) * bytes_per_pixel;
1215 int w = width - i * 256;
1216 int h = height - j * 256;
1217 int dx = dest_x + i * 256;
1218 int dy = dest_y + j * 256;
1219
1220 w = (w & -256) ? 256 : w;
1221 h = (h & -256) ? 256 : h;
1222
1223 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
1224
1225 tx = (float)w / 256.;
1226 ty = (float)h / 256.;
1227
1228 if (flip_dir & AGL_H_FLIP) {
1229 dx = 2*dest_x + width - dx;
1230 w = -w;
1231 }
1232
1233 if (flip_dir & AGL_V_FLIP) {
1234 dy = 2*dest_y + height - dy;
1235 h = -h;
1236 }
1237
1238 glBegin(GL_QUADS);
1239 glMultiTexCoord2f(GL_TEXTURE0, 0., 0.);
1240 glMultiTexCoord2f(GL_TEXTURE1, 0., 0.);
1241 glMultiTexCoord2f(GL_TEXTURE2, 0., 0.);
1242 glVertex2f(dx, dy);
1243 glMultiTexCoord2f(GL_TEXTURE0, 0., ty);
1244 glMultiTexCoord2f(GL_TEXTURE1, 0., ty);
1245 glMultiTexCoord2f(GL_TEXTURE2, 0., ty);
1246 glVertex2f(dx, dy + h);
1247 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
1248 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
1249 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
1250 glVertex2f(dx + w, dy + h);
1251 glMultiTexCoord2f(GL_TEXTURE0, tx, 0.);
1252 glMultiTexCoord2f(GL_TEXTURE1, tx, 0.);
1253 glMultiTexCoord2f(GL_TEXTURE2, tx, 0.);
1254 glVertex2f(dx + w, dy);
1255 glEnd();
1256 }
1257 }
1258
1259 /* Restore state */
1260 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
1261 glBindTexture(GL_TEXTURE_2D, 0);
1262 glDisable(GL_TEXTURE_2D);
1263 glPopAttrib();
1264 glColor4fv(current_color);
1265
1266 if (temp) {
1267 destroy_bitmap(temp);
1268 }
1269
1270 return;
1271 }
1272
1273
1274
do_masked_blit_screen(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height,int flip_dir,int blit_type)1275 void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
1276 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
1277 int flip_dir, int blit_type)
1278 {
1279
1280 /* XXX <rohannessian> We should merge this clip code with the
1281 * BITMAP_BLIT_CLIP macro
1282 */
1283
1284 /* Clipping of destination bitmap */
1285 if (dest->clip && (blit_type & AGL_NO_ROTATION)) {
1286 if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
1287 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) {
1288 return;
1289 }
1290 if (flip_dir & AGL_H_FLIP) {
1291 if (dest_x < dest->cl) {
1292 width += dest_x - dest->cl;
1293 dest_x = dest->cl;
1294 }
1295 if (dest_x + width > dest->cr) {
1296 source_x += dest_x + width - dest->cr;
1297 width = dest->cr - dest_x;
1298 }
1299 }
1300 else {
1301 if (dest_x < dest->cl) {
1302 width += dest_x - dest->cl;
1303 source_x -= dest_x - dest->cl;
1304 dest_x = dest->cl;
1305 }
1306 if (dest_x + width > dest->cr) {
1307 width = dest->cr - dest_x;
1308 }
1309 }
1310 if (flip_dir & AGL_V_FLIP) {
1311 if (dest_y < dest->ct) {
1312 height += dest_y - dest->ct;
1313 dest_y = dest->ct;
1314 }
1315 if (dest_y + height > dest->cb) {
1316 source_y += dest_y + height - dest->cb;
1317 height = dest->cb - dest_y;
1318 }
1319 }
1320 else {
1321 if (dest_y < dest->ct) {
1322 height += dest_y - dest->ct;
1323 source_y -= dest_y - dest->ct;
1324 dest_y = dest->ct;
1325 }
1326 if (dest_y + height > dest->cb) {
1327 height = dest->cb - dest_y;
1328 }
1329 }
1330 }
1331
1332 /* Clipping of source bitmap */
1333 if (source->clip && (blit_type & AGL_REGULAR_BMP)) {
1334 if ((source_x >= source->cr) || (source_y >= source->cb)
1335 || (source_x + width < source->cl)
1336 || (source_y + height < source->ct)) {
1337 return;
1338 }
1339 if (source_x < source->cl) {
1340 width += source_x - source->cl;
1341 dest_x -= source_x - source->cl;
1342 source_x = source->cl;
1343 }
1344 if (source_y < source->ct) {
1345 height += source_y - source->ct;
1346 dest_y -= source_y - source->ct;
1347 source_y = source->ct;
1348 }
1349 if (source_x + width > source->cr) {
1350 width = source->cr - source_x;
1351 }
1352 if (source_y + height > source->cb) {
1353 height = source->cb - source_y;
1354 }
1355 }
1356 if (is_sub_bitmap(dest)) {
1357 dest_x += dest->x_ofs;
1358 dest_y += dest->y_ofs;
1359 }
1360 if (width <= 0 || height <= 0)
1361 return;
1362
1363 /* memory -> screen */
1364 if (!is_video_bitmap(source) && !is_screen_bitmap(source)) {
1365
1366 __allegro_gl_driver->screen_masked_blit(source, source_x, source_y,
1367 dest_x, dest_y, width, height, flip_dir, blit_type);
1368 }
1369 /* video -> screen */
1370 else if (is_video_bitmap(source)) {
1371 AGL_VIDEO_BITMAP *vid;
1372 BITMAP *source_parent = source;
1373
1374 int use_combiners = 0;
1375
1376 /* Special combiner paths */
1377 if (allegro_gl_extensions_GL.NV_register_combiners
1378 || allegro_gl_info.num_texture_units >= 3) {
1379
1380 use_combiners = 1;
1381
1382 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
1383
1384 if (allegro_gl_extensions_GL.NV_register_combiners) {
1385 __allegro_gl_init_nv_register_combiners(source);
1386 }
1387 else {
1388 __allegro_gl_init_combine_textures(source);
1389 }
1390
1391 glEnable(GL_ALPHA_TEST);
1392 glAlphaFunc(GL_GREATER, 0.0f);
1393 }
1394
1395 while (source_parent->id & BMP_ID_SUB) {
1396 source_parent = (BITMAP *)source_parent->extra;
1397 }
1398 vid = source_parent->extra;
1399
1400 while (vid) {
1401 int sx, sy; /* source coordinates */
1402 int dx, dy; /* destination coordinates */
1403 int w, h;
1404
1405 if (source_x >= vid->x_ofs + vid->memory_copy->w ||
1406 source_y >= vid->y_ofs + vid->memory_copy->h ||
1407 vid->x_ofs >= source_x + width ||
1408 vid->y_ofs >= source_y + height) {
1409 vid = vid->next;
1410 continue;
1411 }
1412
1413 sx = MAX (vid->x_ofs, source_x) - vid->x_ofs;
1414 w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width)
1415 - vid->x_ofs - sx;
1416 sy = MAX (vid->y_ofs, source_y) - vid->y_ofs;
1417 h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height)
1418 - vid->y_ofs - sy;
1419
1420 dx = dest_x + vid->x_ofs + sx - source_x;
1421 dy = dest_y + vid->y_ofs + sy - source_y;
1422
1423 if (flip_dir & AGL_H_FLIP) {
1424 dx = 2*dest_x + width - dx;
1425 w = -w;
1426 }
1427
1428 if (flip_dir & AGL_V_FLIP) {
1429 dy = 2*dest_y + height - dy;
1430 h = -h;
1431 }
1432
1433 if (use_combiners) {
1434 if (allegro_gl_extensions_GL.NV_register_combiners) {
1435 glEnable(vid->target);
1436 glBindTexture(vid->target, vid->tex);
1437 glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1438 glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1439
1440 if (vid->target == GL_TEXTURE_2D) {
1441 float tx = sx / (float)vid->memory_copy->w;
1442 float ty = sy / (float)vid->memory_copy->h;
1443 float tw = abs(w) / (float)vid->memory_copy->w;
1444 float th = abs(h) / (float)vid->memory_copy->h;
1445
1446 glBegin(GL_QUADS);
1447 glTexCoord2f(tx, ty);
1448 glVertex2f(dx, dy);
1449 glTexCoord2f(tx, ty + th);
1450 glVertex2f(dx, dy + h);
1451 glTexCoord2f(tx + tw, ty + th);
1452 glVertex2f(dx + w, dy + h);
1453 glTexCoord2f(tx + tw, ty);
1454 glVertex2f(dx + w, dy);
1455 glEnd();
1456 }
1457 else {
1458 glBegin(GL_QUADS);
1459 glTexCoord2i(sx, sy);
1460 glVertex2f(dx, dy);
1461 glTexCoord2i(sx, sy + h);
1462 glVertex2f(dx, dy + h);
1463 glTexCoord2i(sx + w, sy + h);
1464 glVertex2f(dx + w, dy + h);
1465 glTexCoord2i(sx + w, sy);
1466 glVertex2f(dx + w, dy);
1467 glEnd();
1468 }
1469
1470 glBindTexture(vid->target, 0);
1471 glDisable(vid->target);
1472 }
1473 else {
1474 glEnable(vid->target);
1475 glActiveTexture(GL_TEXTURE0);
1476 glBindTexture(vid->target, vid->tex);
1477 glActiveTexture(GL_TEXTURE1);
1478 glBindTexture(vid->target, vid->tex);
1479 glActiveTexture(GL_TEXTURE2);
1480 glBindTexture(vid->target, vid->tex);
1481 glActiveTexture(GL_TEXTURE0);
1482 glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1483 glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1484
1485 if (vid->target == GL_TEXTURE_2D) {
1486 float tx, ty, tw, th; /* texture coordinates */
1487 tx = sx / (float)vid->memory_copy->w;
1488 ty = sy / (float)vid->memory_copy->h;
1489 tw = abs(w) / (float)vid->memory_copy->w;
1490 th = abs(h) / (float)vid->memory_copy->h;
1491
1492 glBegin(GL_QUADS);
1493 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
1494 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
1495 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
1496 glVertex2f(dx, dy);
1497 glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th);
1498 glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th);
1499 glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th);
1500 glVertex2f(dx, dy + h);
1501 glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th);
1502 glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th);
1503 glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th);
1504 glVertex2f(dx + w, dy + h);
1505 glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty);
1506 glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty);
1507 glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty);
1508 glVertex2f(dx + w, dy);
1509 glEnd();
1510 }
1511 else {
1512 glBegin(GL_QUADS);
1513 glMultiTexCoord2i(GL_TEXTURE0, dx, dy);
1514 glMultiTexCoord2i(GL_TEXTURE1, dx, dy);
1515 glMultiTexCoord2i(GL_TEXTURE2, dx, dy);
1516 glVertex2f(dx, dy);
1517 glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h);
1518 glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h);
1519 glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h);
1520 glVertex2f(dx, dy + h);
1521 glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h);
1522 glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h);
1523 glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h);
1524 glVertex2f(dx + w, dy + h);
1525 glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy);
1526 glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy);
1527 glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy);
1528 glVertex2f(dx + w, dy);
1529 glEnd();
1530 }
1531
1532 glBindTexture(vid->target, 0);
1533 glDisable(vid->target);
1534 }
1535 }
1536 else {
1537 screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy,
1538 w, h, FALSE, blit_type);
1539 }
1540
1541 vid = vid->next;
1542 }
1543
1544 if (use_combiners) {
1545 glPopAttrib();
1546 }
1547 }
1548 return;
1549 }
1550
1551
1552
__allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE * sprite,int trans)1553 static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans)
1554 {
1555 BITMAP *temp = NULL;
1556 int y, x, src_depth;
1557 signed long src_mask;
1558
1559 #define DRAW_RLE_8888(bits) \
1560 { \
1561 for (y = 0; y < sprite->h; y++) { \
1562 signed long c = *s++; \
1563 for (x = 0; x < sprite->w;) { \
1564 if (c == src_mask) \
1565 break; \
1566 if (c > 0) { \
1567 /* Run of solid pixels */ \
1568 for (c--; c>=0; c--) { \
1569 unsigned long col = *s++; \
1570 if (bits == 32 && trans) \
1571 _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
1572 else \
1573 _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
1574 } \
1575 } \
1576 else { \
1577 /* Run of transparent pixels */ \
1578 hline(temp, x, y, x-c+1, 0); \
1579 x -= c; \
1580 } \
1581 c = *s++; \
1582 } \
1583 } \
1584 }
1585
1586 src_depth = sprite->color_depth;
1587 if (src_depth == 8)
1588 src_mask = 0;
1589 else
1590 src_mask = makecol_depth(src_depth, 255, 0, 255);
1591
1592 temp = create_bitmap_ex(32, sprite->w, sprite->h);
1593 if (!temp) return NULL;
1594
1595 /* RGBA 8888 */
1596 switch(src_depth) {
1597 case 8:
1598 {
1599 signed char *s = (signed char*)sprite->dat;
1600 DRAW_RLE_8888(8);
1601 break;
1602 }
1603 case 15:
1604 {
1605 int16_t *s = (int16_t*)sprite->dat;
1606 DRAW_RLE_8888(15);
1607 break;
1608 }
1609 case 16:
1610 {
1611 int16_t *s = (int16_t*)sprite->dat;
1612 DRAW_RLE_8888(16);
1613 break;
1614 }
1615 case 24:
1616 {
1617 int32_t *s = (int32_t*)sprite->dat;
1618 DRAW_RLE_8888(24);
1619 break;
1620 }
1621 case 32:
1622 {
1623 int32_t *s = (int32_t*)sprite->dat;
1624 DRAW_RLE_8888(32);
1625 break;
1626 }
1627 }
1628
1629 return temp;
1630 }
1631
1632
1633
allegro_gl_screen_draw_rle_sprite(struct BITMAP * bmp,AL_CONST struct RLE_SPRITE * sprite,int x,int y)1634 void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
1635 {
1636 BITMAP *temp = NULL, *temp2 = NULL;
1637 int source_x = 0, source_y = 0;
1638 int width = sprite->w, height = sprite->h;
1639
1640 temp = __allegro_gl_convert_rle_sprite(sprite, FALSE);
1641 if (!temp)
1642 return;
1643
1644 BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
1645
1646 if (is_sub_bitmap(bmp)) {
1647 x += bmp->x_ofs;
1648 y += bmp->y_ofs;
1649 }
1650
1651 if (width <= 0 || height <= 0) {
1652 destroy_bitmap(temp);
1653 return;
1654 }
1655
1656 temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
1657 if (!temp2) {
1658 destroy_bitmap(temp);
1659 return;
1660 }
1661
1662 do_screen_masked_blit_standard(GL_RGBA,
1663 __allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2,
1664 0, 0, x, y, width, height, FALSE, AGL_NO_ROTATION);
1665
1666 destroy_bitmap(temp2);
1667 destroy_bitmap(temp);
1668 }
1669
1670
allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP * bmp,AL_CONST struct RLE_SPRITE * sprite,int x,int y)1671 static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp,
1672 AL_CONST struct RLE_SPRITE *sprite, int x, int y) {
1673 BITMAP *temp = NULL, *temp2 = NULL;
1674 int source_x = 0, source_y = 0;
1675 int width = sprite->w, height = sprite->h;
1676
1677 temp = __allegro_gl_convert_rle_sprite(sprite, TRUE);
1678 if (!temp)
1679 return;
1680
1681 BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
1682
1683 if (is_sub_bitmap(bmp)) {
1684 x += bmp->x_ofs;
1685 y += bmp->y_ofs;
1686 }
1687
1688 if (width <= 0 || height <= 0) {
1689 destroy_bitmap(temp);
1690 return;
1691 }
1692
1693 temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
1694 if (!temp2) {
1695 destroy_bitmap(temp);
1696 return;
1697 }
1698
1699 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1700 glEnable(GL_COLOR_LOGIC_OP);
1701 else
1702 glEnable(GL_BLEND);
1703
1704 allegro_gl_upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE);
1705
1706 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1707 glDisable(GL_COLOR_LOGIC_OP);
1708 else
1709 glDisable(GL_BLEND);
1710
1711 destroy_bitmap(temp2);
1712 destroy_bitmap(temp);
1713 }
1714
1715
1716
allegro_gl_screen_masked_blit(struct BITMAP * source,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)1717 static void allegro_gl_screen_masked_blit(struct BITMAP *source,
1718 struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
1719 int width, int height)
1720 {
1721 AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n");
1722 do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y,
1723 width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
1724 }
1725
1726
1727
allegro_gl_screen_draw_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1728 static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp,
1729 struct BITMAP *sprite, int x, int y)
1730 {
1731 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n");
1732 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1733 FALSE, AGL_NO_ROTATION);
1734 }
1735
1736
1737
allegro_gl_screen_draw_sprite_v_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1738 static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp,
1739 struct BITMAP *sprite, int x, int y)
1740 {
1741 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n");
1742 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1743 AGL_V_FLIP, AGL_NO_ROTATION);
1744 }
1745
1746
1747
allegro_gl_screen_draw_sprite_h_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1748 static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp,
1749 struct BITMAP *sprite, int x, int y)
1750 {
1751 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n");
1752 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1753 AGL_H_FLIP, AGL_NO_ROTATION);
1754 }
1755
1756
1757
allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1758 static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp,
1759 struct BITMAP *sprite, int x, int y)
1760 {
1761 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n");
1762 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1763 AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
1764 }
1765
1766
1767
allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP * bmp,struct BITMAP * sprite,fixed x,fixed y,fixed cx,fixed cy,fixed angle,fixed scale,int v_flip)1768 static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp,
1769 struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle,
1770 fixed scale, int v_flip)
1771 {
1772 double dscale = fixtof(scale);
1773 GLint matrix_mode;
1774 AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n");
1775
1776 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
1777
1778 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
1779 glMatrixMode(GL_MODELVIEW);
1780 glPushMatrix();
1781 glTranslated(fixtof(x), fixtof(y), 0.);
1782 glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
1783 glScaled(dscale, dscale, dscale);
1784 glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
1785
1786 do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
1787 sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
1788 glPopMatrix();
1789 glMatrixMode(matrix_mode);
1790
1791 #undef BIN_2_DEG
1792
1793 return;
1794 }
1795
1796
1797
allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)1798 static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp,
1799 struct BITMAP *sprite, int x, int y) {
1800
1801 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1802 glEnable(GL_COLOR_LOGIC_OP);
1803 else
1804 glEnable(GL_BLEND);
1805
1806 /* video -> screen */
1807 if (is_video_bitmap(sprite)) {
1808 allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h);
1809 }
1810 /* memory -> screen */
1811 else if (is_memory_bitmap(sprite)) {
1812 GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
1813 GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
1814 allegro_gl_upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, format, type);
1815 }
1816
1817 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
1818 glDisable(GL_COLOR_LOGIC_OP);
1819 else
1820 glDisable(GL_BLEND);
1821
1822 return;
1823 }
1824
1825
1826
allegro_gl_screen_draw_sprite_ex(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int mode,int flip)1827 static void allegro_gl_screen_draw_sprite_ex(struct BITMAP *bmp,
1828 struct BITMAP *sprite, int x, int y, int mode, int flip)
1829 {
1830 int lflip = 0;
1831 int matrix_mode;
1832 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_ex\n");
1833
1834 /* convert allegro's flipping flags to AGL's flags */
1835 switch (flip) {
1836 case DRAW_SPRITE_NO_FLIP:
1837 lflip = FALSE;
1838 break;
1839 case DRAW_SPRITE_V_FLIP:
1840 lflip = AGL_V_FLIP;
1841 break;
1842 case DRAW_SPRITE_H_FLIP:
1843 lflip = AGL_H_FLIP;
1844 break;
1845 case DRAW_SPRITE_VH_FLIP:
1846 lflip = AGL_V_FLIP | AGL_H_FLIP;
1847 break;
1848 }
1849
1850 switch (mode) {
1851 case DRAW_SPRITE_NORMAL:
1852 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
1853 lflip, AGL_NO_ROTATION);
1854 break;
1855 case DRAW_SPRITE_TRANS:
1856 if (lflip) {
1857 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
1858 glMatrixMode(GL_MODELVIEW);
1859 glPushMatrix();
1860
1861 glTranslatef(x, y, 0.f);
1862 glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1);
1863 glTranslatef(-x, -y, 0);
1864 glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0,
1865 (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0);
1866 }
1867
1868 allegro_gl_screen_draw_trans_rgba_sprite(bmp, sprite, x, y);
1869
1870 if (lflip) {
1871 glPopMatrix();
1872 glMatrixMode(matrix_mode);
1873 }
1874 break;
1875 case DRAW_SPRITE_LIT:
1876 /* unsupported */
1877 break;
1878 }
1879 }
1880
1881
1882
allegro_gl_screen_draw_glyph_ex(struct BITMAP * bmp,AL_CONST struct FONT_GLYPH * glyph,int x,int y,int color,int bg,int flip)1883 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
1884 AL_CONST struct FONT_GLYPH *glyph, int x, int y,
1885 int color, int bg, int flip)
1886 {
1887 GLubyte r, g, b, a;
1888 int x_offs = 0;
1889 int i;
1890
1891 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n");
1892
1893 if (bmp->clip) {
1894 glPushAttrib(GL_SCISSOR_BIT);
1895 glEnable(GL_SCISSOR_TEST);
1896 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
1897 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
1898
1899 if (x < bmp->cl) {
1900 x_offs -= x - bmp->cl;
1901 x = bmp->cl;
1902 }
1903 }
1904 if (is_sub_bitmap(bmp)) {
1905 x += bmp->x_ofs;
1906 y += bmp->y_ofs;
1907 }
1908
1909 if (bg != -1) {
1910 split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
1911 glColor4ub(r, g, b, a);
1912 glRecti(x, y, x + glyph->w, y + glyph->h);
1913 }
1914
1915 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
1916 glColor4ub(r, g, b, a);
1917 glRasterPos2i(x, y);
1918 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1919 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1920
1921 if (flip) {
1922 for (i = 0; i < glyph->h; i++) {
1923 glBitmap(glyph->w, 1, x_offs, i, 0, 2,
1924 glyph->dat + i * ((glyph->w + 7) / 8));
1925 }
1926 }
1927 else {
1928 for (i = 0; i < glyph->h; i++) {
1929 glBitmap(glyph->w, 1, x_offs, i, 0, 0,
1930 glyph->dat + i * ((glyph->w + 7) / 8));
1931 }
1932 }
1933
1934 if (bmp->clip) {
1935 glPopAttrib();
1936 }
1937
1938 return;
1939 }
1940
1941
1942
allegro_gl_screen_draw_glyph(struct BITMAP * bmp,AL_CONST struct FONT_GLYPH * glyph,int x,int y,int color,int bg)1943 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
1944 AL_CONST struct FONT_GLYPH *glyph, int x, int y,
1945 int color, int bg) {
1946 allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0);
1947 }
1948
1949
1950
allegro_gl_screen_draw_color_glyph_ex(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg,int flip)1951 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
1952 struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
1953 {
1954
1955 /* Implementation note: we should try building textures and see how well
1956 * those work instead of of DrawPixels with a weird I_TO_RGBA mapping.
1957 */
1958 static GLfloat red_map[256];
1959 static GLfloat green_map[256];
1960 static GLfloat blue_map[256];
1961 static GLfloat alpha_map[256];
1962 GLubyte r, g, b, a;
1963 int i;
1964 GLint saved_row_length;
1965 GLint width, height;
1966 int sprite_x = 0, sprite_y = 0;
1967 void *data;
1968 int *table;
1969
1970 width = sprite->w;
1971 height = sprite->h;
1972
1973 if (bmp->clip) {
1974 if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
1975 || (y + height < bmp->ct)) {
1976 return;
1977 }
1978 if (x < bmp->cl) {
1979 width += x - bmp->cl;
1980 sprite_x -= (x - bmp->cl);
1981 x = bmp->cl;
1982 }
1983 if (y < bmp->ct) {
1984 height += y - bmp->ct;
1985 sprite_y -= (y - bmp->ct);
1986 y = bmp->ct;
1987 }
1988 if (x + width > bmp->cr) {
1989 width = bmp->cr - x;
1990 }
1991 if (y + height > bmp->cb) {
1992 height = bmp->cb - y;
1993 }
1994 }
1995 if (is_sub_bitmap(bmp)) {
1996 x += bmp->x_ofs;
1997 y += bmp->y_ofs;
1998 }
1999
2000 data = sprite->line[sprite_y]
2001 + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
2002
2003 if (bg < 0) {
2004 glAlphaFunc(GL_GREATER, 0.0f);
2005 glEnable(GL_ALPHA_TEST);
2006 alpha_map[0] = 0.;
2007 }
2008 else {
2009 split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
2010 red_map[0] = r / 255.;
2011 green_map[0] = g / 255.;
2012 blue_map[0] = b / 255.;
2013 alpha_map[0] = 1.;
2014 }
2015
2016 if (color < 0) {
2017 table = _palette_expansion_table(bitmap_color_depth(bmp));
2018
2019 for(i = 1; i < 255; i++) {
2020 split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
2021 red_map[i] = r / 255.;
2022 green_map[i] = g / 255.;
2023 blue_map[i] = b / 255.;
2024 alpha_map[i] = 1.;
2025 }
2026 }
2027 else {
2028 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2029
2030 for(i = 1; i < 255; i++) {
2031 red_map[i] = r / 255.;
2032 green_map[i] = g / 255.;
2033 blue_map[i] = b / 255.;
2034 alpha_map[i] = 1.;
2035 }
2036 }
2037
2038 glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
2039 glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
2040 glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
2041 glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
2042
2043 glRasterPos2i(x, y);
2044 glPushAttrib(GL_PIXEL_MODE_BIT);
2045 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
2046
2047 glPixelZoom(1.0, flip ? -1.0 : 1.0);
2048 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2049 glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
2050 glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
2051
2052 glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
2053 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
2054 glPopAttrib();
2055 if (bg < 0) {
2056 glDisable(GL_ALPHA_TEST);
2057 }
2058
2059 return;
2060 }
2061
2062
2063
allegro_gl_screen_draw_color_glyph(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg)2064 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
2065 struct BITMAP *sprite, int x, int y, int color, int bg) {
2066 allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1);
2067 }
2068
2069
2070
allegro_gl_screen_draw_character(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y,int color,int bg)2071 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
2072 struct BITMAP *sprite, int x, int y, int color, int bg)
2073 {
2074 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
2075 allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
2076 }
2077
2078
2079
allegro_gl_screen_draw_256_sprite(struct BITMAP * bmp,struct BITMAP * sprite,int x,int y)2080 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
2081 struct BITMAP *sprite, int x, int y)
2082 {
2083 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
2084 allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1);
2085 }
2086
2087
2088
allegro_gl_screen_clear_to_color(struct BITMAP * bmp,int color)2089 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
2090 {
2091 if (__agl_drawing_pattern_tex || bmp->clip) {
2092 allegro_gl_screen_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
2093 }
2094 else {
2095 GLubyte r, g, b, a;
2096 GLfloat old_col[4];
2097
2098 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2099
2100 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
2101 glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
2102 ((float) a / 255));
2103
2104 glClear(GL_COLOR_BUFFER_BIT);
2105 glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
2106 }
2107
2108 return;
2109 }
2110
2111
2112
2113 /* TODO: Handle concave and self-intersecting. */
allegro_gl_screen_polygon(struct BITMAP * bmp,int vertices,AL_CONST int * points,int color)2114 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
2115 AL_CONST int *points, int color) {
2116 GLubyte r, g, b, a;
2117 int i;
2118
2119 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2120 glColor4ub(r, g, b, a);
2121
2122 glPushAttrib(GL_SCISSOR_BIT);
2123
2124 if (bmp->clip) {
2125 glEnable(GL_SCISSOR_TEST);
2126 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2127 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2128 }
2129 else {
2130 glScissor(0, 0, bmp->w, bmp->h);
2131 }
2132
2133 glBegin(GL_POLYGON);
2134 for (i = 0; i < vertices*2-1; i+=2) {
2135 SET_TEX_COORDS(points[i], points[i+1]);
2136 if (is_sub_bitmap(bmp)) {
2137 glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
2138 }
2139 else {
2140 glVertex2f(points[i], points[i+1]);
2141 }
2142 }
2143 glEnd();
2144
2145 glPopAttrib();
2146 }
2147
2148
2149
allegro_gl_screen_rect(struct BITMAP * bmp,int x1,int y1,int x2,int y2,int color)2150 static void allegro_gl_screen_rect(struct BITMAP *bmp,
2151 int x1, int y1, int x2, int y2, int color) {
2152 GLubyte r, g, b, a;
2153
2154 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
2155 glColor4ub(r, g, b, a);
2156
2157 glPushAttrib(GL_SCISSOR_BIT);
2158
2159 if (bmp->clip) {
2160 glEnable(GL_SCISSOR_TEST);
2161 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2162 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2163 }
2164 else {
2165 glScissor(0, 0, bmp->w, bmp->h);
2166 }
2167 if (is_sub_bitmap(bmp)) {
2168 x1 += bmp->x_ofs;
2169 x2 += bmp->x_ofs;
2170 y1 += bmp->y_ofs;
2171 y2 += bmp->y_ofs;
2172 }
2173
2174 glBegin(GL_LINE_STRIP);
2175 glVertex2f(x1, y1);
2176 glVertex2f(x2, y1);
2177 glVertex2f(x2, y2);
2178 glVertex2f(x1, y2);
2179 glVertex2f(x1, y1);
2180 glEnd();
2181
2182 glPopAttrib();
2183 }
2184
2185
2186
allegro_gl_screen_polygon3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,int vc,V3D_f * vtx[])2187 void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
2188 struct BITMAP *texture, int vc,
2189 V3D_f *vtx[]) {
2190 int i;
2191 int use_z = FALSE;
2192
2193 if (type & POLYTYPE_ZBUF) {
2194 use_z = TRUE;
2195 type &= ~POLYTYPE_ZBUF;
2196 }
2197
2198 if (type == POLYTYPE_PTEX || type == POLYTYPE_PTEX_TRANS)
2199 use_z = TRUE;
2200
2201 if (bmp->clip) {
2202 glPushAttrib(GL_SCISSOR_BIT);
2203 glEnable(GL_SCISSOR_TEST);
2204 glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
2205 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
2206 }
2207 if (is_sub_bitmap(bmp)) {
2208 for (i = 0; i < vc*2-1; i+=2) {
2209 vtx[i] += bmp->x_ofs;
2210 vtx[i+1] += bmp->y_ofs;
2211 }
2212 }
2213
2214 if (use_z) {
2215 glEnable(GL_DEPTH_TEST);
2216 glDepthFunc(GL_LESS);
2217 glDepthMask(GL_TRUE);
2218 }
2219
2220 glColor4ub(255, 255, 255, 255);
2221
2222 if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2223 || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2224 drawing_mode(DRAW_MODE_COPY_PATTERN, texture, 0, 0);
2225 }
2226
2227 if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2228 glEnable(GL_BLEND);
2229 }
2230
2231 glBegin(GL_POLYGON);
2232 for (i = 0; i < vc; i++) {
2233 if (type == POLYTYPE_FLAT)
2234 glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
2235 else if (type == POLYTYPE_GRGB)
2236 glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
2237 else if (type == POLYTYPE_GCOL)
2238 glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
2239 else if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2240 || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2241 SET_TEX_COORDS(vtx[i]->u, vtx[i]->v);
2242 }
2243
2244 if (use_z)
2245 glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
2246 else
2247 glVertex2f(vtx[i]->x, vtx[i]->y);
2248 }
2249 glEnd();
2250
2251 if (bmp->clip)
2252 glPopAttrib();
2253
2254 if (use_z) {
2255 glDisable(GL_DEPTH_TEST);
2256 glDepthMask(GL_FALSE);
2257 }
2258
2259 if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
2260 || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
2261 solid_mode();
2262 }
2263
2264 if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS)
2265 glDisable(GL_BLEND);
2266 }
2267
2268
2269
allegro_gl_screen_polygon3d(struct BITMAP * bmp,int type,struct BITMAP * texture,int vc,V3D * vtx[])2270 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
2271 struct BITMAP *texture, int vc,
2272 V3D *vtx[]) {
2273 int i;
2274 V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
2275 if (!vtx_f)
2276 return;
2277
2278 for (i = 0; i < vc; i++) {
2279 vtx_f[i] = malloc(sizeof(struct V3D_f));
2280 if (!vtx_f[i]) {
2281 int k;
2282 for (k = 0; k < i; k++)
2283 free(vtx_f[k]);
2284 free(vtx_f);
2285 return;
2286 }
2287 vtx_f[i]->c = vtx[i]->c;
2288 vtx_f[i]->u = fixtof(vtx[i]->u);
2289 vtx_f[i]->v = fixtof(vtx[i]->v);
2290 vtx_f[i]->x = fixtof(vtx[i]->x);
2291 vtx_f[i]->y = fixtof(vtx[i]->y);
2292 vtx_f[i]->z = fixtof(vtx[i]->z);
2293 }
2294
2295 allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
2296 for (i = 0; i < vc; i++)
2297 free(vtx_f[i]);
2298 free(vtx_f);
2299 }
2300
2301
allegro_gl_screen_quad3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3,V3D_f * v4)2302 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
2303 struct BITMAP *texture,
2304 V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
2305
2306 V3D_f *vtx_f[4];
2307 vtx_f[0] = v1;
2308 vtx_f[1] = v2;
2309 vtx_f[2] = v3;
2310 vtx_f[3] = v4;
2311
2312 allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
2313 }
2314
2315
2316
allegro_gl_screen_quad3d(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D * v1,V3D * v2,V3D * v3,V3D * v4)2317 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
2318 struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
2319
2320 V3D *vtx[4];
2321 vtx[0] = v1;
2322 vtx[1] = v2;
2323 vtx[2] = v3;
2324 vtx[3] = v4;
2325
2326 allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
2327 }
2328
2329
2330
allegro_gl_screen_triangle3d(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D * v1,V3D * v2,V3D * v3)2331 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
2332 struct BITMAP *texture,
2333 V3D *v1, V3D *v2, V3D *v3) {
2334 V3D *vtx[3];
2335 vtx[0] = v1;
2336 vtx[1] = v2;
2337 vtx[2] = v3;
2338
2339 allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
2340 }
2341
2342
2343
allegro_gl_screen_triangle3d_f(struct BITMAP * bmp,int type,struct BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3)2344 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
2345 struct BITMAP *texture,
2346 V3D_f *v1, V3D_f *v2, V3D_f *v3) {
2347 V3D_f *vtx_f[3];
2348 vtx_f[0] = v1;
2349 vtx_f[1] = v2;
2350 vtx_f[2] = v3;
2351
2352 allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
2353 }
2354
2355
2356
__allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)2357 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
2358 {
2359 int maskcolor = (*vtable)->mask_color;
2360 int depth = (*vtable)->color_depth;
2361
2362 AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
2363 allegro_gl_screen_vtable.color_depth = depth;
2364 /* makecol_depth is used below instead of the MASK_COLOR_x constants
2365 * because we may have changed the RGB shift values in order to
2366 * use the packed pixels extension
2367 */
2368 allegro_gl_screen_vtable.mask_color =
2369 makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
2370
2371 *vtable = &allegro_gl_screen_vtable;
2372
2373 __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
2374 if (allegro_gl_extensions_GL.NV_register_combiners) {
2375 __allegro_gl_driver->screen_masked_blit
2376 = screen_masked_blit_nv_register;
2377 }
2378 else if (allegro_gl_info.num_texture_units >= 3) {
2379 __allegro_gl_driver->screen_masked_blit =
2380 screen_masked_blit_combine_tex;
2381 }
2382 }
2383
2384
2385
2386 /* Saved projection matrix */
2387 static double allegro_gl_projection_matrix[16];
2388 static double allegro_gl_modelview_matrix[16];
2389
2390
2391
2392 /** \ingroup allegro
2393 * Prepares for Allegro drawing to the screen.
2394 *
2395 * Since AllegroGL actually calls OpenGL commands to perform Allegro functions
2396 * for 2D drawing, some OpenGL capabilities may interfer with those operations
2397 * In order to obtain the expected results, allegro_gl_set_allegro_mode() must
2398 * be called to disable the depth test, texturing, fog and lighting and set
2399 * the view matrices to an appropriate state. Call
2400 * allegro_gl_unset_allegro_mode() to restore OpenGL in its previous state.
2401 *
2402 * You should encapsulate all Allegro code dealing with the screen in
2403 * between allegro_gl_set_allegro_mode() and allegro_gl_unset_allegro_mode().
2404 *
2405 * If you need to use regular OpenGL commands in between, you may do so,
2406 * but you can get unexpected results. This is generally not recommended.
2407 * You should first call allegro_gl_unset_allegro_mode() to restore the
2408 * original OpenGL matrices. After that, you may freely call any OpenGL
2409 * command. Don't forget to call back allegro_gl_set_allegro_mode() to switch
2410 * back to Allegro commands.
2411 *
2412 * AllegroGL saves the current OpenGL state with glPushAttrib so you should
2413 * make sure that at least one level is available in the attribute stack
2414 * otherwise the next call to allegro_gl_unset_allegro_mode() may fail.
2415 *
2416 * Also note that allegro_gl_set_allegro_mode() implicitely calls
2417 * allegro_gl_set_projection() so you do not need to do it yourself.
2418 *
2419 * \sa allegro_gl_unset_allegro_mode() allegro_gl_set_projection()
2420 * \sa allegro_gl_unset_projection()
2421 */
allegro_gl_set_allegro_mode(void)2422 void allegro_gl_set_allegro_mode(void)
2423 {
2424 AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
2425
2426 /* Save the OpenGL state then set it up */
2427 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
2428 | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2429 glDisable(GL_DEPTH_TEST);
2430 glDisable(GL_CULL_FACE);
2431 glDisable(GL_FOG);
2432 glDisable(GL_LIGHTING);
2433 glDisable(GL_BLEND);
2434 glDisable(GL_ALPHA_TEST);
2435 glDepthMask(GL_FALSE);
2436 glEnable(GL_TEXTURE_2D);
2437 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2438 glPointSize(1.);
2439
2440 /* Create pool texture */
2441 if (!__allegro_gl_pool_texture) {
2442 glGenTextures(1, &__allegro_gl_pool_texture);
2443 }
2444
2445 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
2446 /* Create a texture without defining the data */
2447 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
2448 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2451
2452 glBindTexture(GL_TEXTURE_2D, 0);
2453 allegro_gl_set_projection();
2454
2455 /* For some reason, ATI Rage Pro isn't able to draw correctly without a
2456 * texture bound. So we bind a dummy 1x1 texture to work around the issue.
2457 */
2458 if (allegro_gl_info.is_ati_rage_pro) {
2459 if (!__allegro_gl_dummy_texture) {
2460 GLubyte tex[4] = {255, 255, 255, 255};
2461 glGenTextures(1, &__allegro_gl_dummy_texture);
2462 glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
2463 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
2464 GL_RGBA, GL_UNSIGNED_BYTE, tex);
2465 }
2466 glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
2467 }
2468 #ifdef ALLEGRO_MACOSX
2469 /* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in
2470 *'blit'). This stops it happening.
2471 */
2472 glBegin(GL_POINTS);
2473 glEnd();
2474 #endif
2475 }
2476
2477
2478
2479 /** \ingroup allegro
2480 * Restores previous OpenGL settings.
2481 *
2482 * Restores the OpenGL state that have saved during the last call of
2483 * allegro_gl_set_allegro_mode().
2484 *
2485 * Note that allegro_gl_unset_allegro_mode implicitely calls
2486 * allegro_gl_unset_projection() so you do not need to do it yourself.
2487 *
2488 * \sa allegro_gl_set_allegro_mode() allegro_gl_set_projection()
2489 * \sa allegro_gl_unset_projection()
2490 */
allegro_gl_unset_allegro_mode(void)2491 void allegro_gl_unset_allegro_mode(void)
2492 {
2493 AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
2494
2495 switch(allegro_gl_display_info.vidmem_policy) {
2496 case AGL_KEEP:
2497 break;
2498 case AGL_RELEASE:
2499 if (__allegro_gl_pool_texture) {
2500 glDeleteTextures(1, &__allegro_gl_pool_texture);
2501 __allegro_gl_pool_texture = 0;
2502 }
2503 break;
2504 }
2505 allegro_gl_unset_projection();
2506 glPopAttrib();
2507 }
2508
2509
2510
2511 /** \ingroup allegro
2512 * Prepares for Allegro drawing to the screen.
2513 *
2514 * This function sets the OpenGL projection and modelview matrices so
2515 * that 2D OpenGL coordinates match the usual Allegro coordinate system.
2516 *
2517 * OpenGL uses a completely different coordinate system than Allegro. So
2518 * to be able to use Allegro operations on the screen, you first need
2519 * to properly set up the OpenGL projection and modelview matrices.
2520 * AllegroGL provides this set of functions to allow proper alignment of
2521 * OpenGL coordinates with their Allegro counterparts.
2522 *
2523 * Since AllegroGL actually calls OpenGL commands to perform Allegro functions
2524 * for 2D drawing, some OpenGL capabilities such as texturing or depth testing
2525 * may interfer with those operations. In order to prevent such inconveniences,
2526 * you should call allegro_gl_set_allegro_mode() instead of
2527 * allegro_gl_set_projection()
2528 *
2529 * allegro_gl_set_projection() and allegro_gl_unset_projection() are not
2530 * nestable, which means that you should not call allegro_gl_set_projection()
2531 * inside another allegro_gl_set_projection() block. Similarly for
2532 * allegro_gl_unset_projection().
2533 *
2534 * Have a look at examp/exalleg.c for an example of
2535 * combining Allegro drawing commands and OpenGL.
2536 *
2537 * \sa allegro_gl_unset_projection() allegro_gl_set_allegro_mode()
2538 * \sa allegro_gl_unset_allegro_mode()
2539 */
allegro_gl_set_projection(void)2540 void allegro_gl_set_projection(void)
2541 {
2542 GLint v[4];
2543 AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
2544
2545 /* Setup OpenGL matrices */
2546 glGetIntegerv(GL_VIEWPORT, &v[0]);
2547 glMatrixMode(GL_MODELVIEW);
2548 glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
2549 glLoadIdentity();
2550 glMatrixMode(GL_PROJECTION);
2551 glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
2552 glLoadIdentity();
2553 gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
2554 }
2555
2556
2557
2558 /** \ingroup allegro
2559 * Restores previously saved projection.
2560 *
2561 * This function returns the projection and modelview matrices to their
2562 * state before the last allegro_gl_set_projection() was called.
2563 *
2564 * \sa allegro_gl_set_projection() allegro_gl_set_allegro_mode()
2565 * \sa allegro_gl_unset_allegro_mode()
2566 */
allegro_gl_unset_projection(void)2567 void allegro_gl_unset_projection(void)
2568 {
2569 AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
2570 glMatrixMode(GL_PROJECTION);
2571 glLoadMatrixd(allegro_gl_projection_matrix);
2572 glMatrixMode(GL_MODELVIEW);
2573 glLoadMatrixd(allegro_gl_modelview_matrix);
2574 }
2575
2576
2577
allegro_gl_memory_blit_between_formats(struct BITMAP * src,struct BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)2578 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
2579 struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
2580 int width, int height)
2581 {
2582 AGL_LOG(2, "AGL::blit_between_formats\n");
2583
2584 /* screen -> memory */
2585 if (is_screen_bitmap(src)) {
2586 allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
2587 dest_x, dest_y, width, height);
2588 return;
2589 }
2590
2591 /* video -> memory */
2592 if (is_video_bitmap(src)) {
2593 allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
2594 dest_x, dest_y, width, height);
2595 return;
2596 }
2597
2598 /* memory -> screen */
2599 if (is_screen_bitmap(dest)) {
2600 allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
2601 dest_x, dest_y, width, height);
2602 return;
2603 }
2604
2605 /* memory -> video */
2606 if (is_video_bitmap(dest)) {
2607 allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
2608 dest_x, dest_y, width, height);
2609 return;
2610 }
2611
2612 switch(bitmap_color_depth(dest)) {
2613 #ifdef ALLEGRO_COLOR8
2614 case 8:
2615 __blit_between_formats8(src, dest, source_x, source_y,
2616 dest_x, dest_y, width, height);
2617 return;
2618 #endif
2619 #ifdef ALLEGRO_COLOR16
2620 case 15:
2621 __blit_between_formats15(src, dest, source_x, source_y,
2622 dest_x, dest_y, width, height);
2623 return;
2624 case 16:
2625 __blit_between_formats16(src, dest, source_x, source_y,
2626 dest_x, dest_y, width, height);
2627 return;
2628 #endif
2629 #ifdef ALLEGRO_COLOR24
2630 case 24:
2631 __blit_between_formats24(src, dest, source_x, source_y,
2632 dest_x, dest_y, width, height);
2633 return;
2634 #endif
2635 #ifdef ALLEGRO_COLOR32
2636 case 32:
2637 __blit_between_formats32(src, dest, source_x, source_y,
2638 dest_x, dest_y, width, height);
2639 return;
2640 #endif
2641 default:
2642 TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
2643 bitmap_color_depth(src), bitmap_color_depth(dest));
2644 return;
2645 }
2646 }
2647
2648
2649
dummy_unwrite_bank(void)2650 static void dummy_unwrite_bank(void)
2651 {
2652 }
2653
2654
2655
2656 static GFX_VTABLE allegro_gl_screen_vtable = {
2657 0,
2658 0,
2659 dummy_unwrite_bank, //void *unwrite_bank;
2660 NULL, //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
2661 allegro_gl_screen_acquire,
2662 allegro_gl_screen_release,
2663 NULL, //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
2664 NULL, //AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent));
2665 allegro_gl_screen_getpixel,
2666 allegro_gl_screen_putpixel,
2667 allegro_gl_screen_vline,
2668 allegro_gl_screen_hline,
2669 allegro_gl_screen_hline,
2670 allegro_gl_screen_line,
2671 allegro_gl_screen_line,
2672 allegro_gl_screen_rectfill,
2673 allegro_gl_screen_triangle,
2674 allegro_gl_screen_draw_sprite,
2675 allegro_gl_screen_draw_256_sprite,
2676 allegro_gl_screen_draw_sprite_v_flip,
2677 allegro_gl_screen_draw_sprite_h_flip,
2678 allegro_gl_screen_draw_sprite_vh_flip,
2679 allegro_gl_screen_draw_trans_rgba_sprite,
2680 allegro_gl_screen_draw_trans_rgba_sprite,
2681 NULL, //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
2682 allegro_gl_screen_draw_rle_sprite,
2683 allegro_gl_screen_draw_trans_rgba_rle_sprite,
2684 allegro_gl_screen_draw_trans_rgba_rle_sprite,
2685 NULL, //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
2686 allegro_gl_screen_draw_character,
2687 allegro_gl_screen_draw_glyph,
2688 allegro_gl_screen_blit_from_memory,
2689 allegro_gl_screen_blit_to_memory,
2690 NULL, //AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
2691 NULL, //AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
2692 allegro_gl_screen_blit_to_self,
2693 allegro_gl_screen_blit_to_self, /* ..._forward */
2694 allegro_gl_screen_blit_to_self, /* ..._backward */
2695 allegro_gl_memory_blit_between_formats,
2696 allegro_gl_screen_masked_blit,
2697 allegro_gl_screen_clear_to_color,
2698 allegro_gl_screen_pivot_scaled_sprite_flip,
2699 NULL, //AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked));
2700 NULL, //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4));
2701 NULL, //AL_METHOD(void, draw_sprite_end, (void));
2702 NULL, //AL_METHOD(void, blit_end, (void));
2703 allegro_gl_screen_polygon,
2704 allegro_gl_screen_rect,
2705 _soft_circle, //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
2706 _soft_circlefill, //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
2707 _soft_ellipse, //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
2708 _soft_ellipsefill, //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
2709 _soft_arc, //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
2710 _soft_spline, //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
2711 _soft_floodfill, //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
2712 allegro_gl_screen_polygon3d,
2713 allegro_gl_screen_polygon3d_f,
2714 allegro_gl_screen_triangle3d,
2715 allegro_gl_screen_triangle3d_f,
2716 allegro_gl_screen_quad3d,
2717 allegro_gl_screen_quad3d_f,
2718 allegro_gl_screen_draw_sprite_ex
2719 };
2720
2721 /** \} */
2722