AllegroGL  0.4.4
glvtable.c
Go to the documentation of this file.
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  */
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 
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  */
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  */
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 
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  */
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) */
160 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
161 
162 
163 
164 /* static void allegro_gl_screen_release(struct BITMAP *bmp) */
170 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
171 
172 
173 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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. */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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);
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 
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  }
2506  glPopAttrib();
2507 }
2508 
2509 
2510 
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 
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 
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 
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));
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 
#define AGL_KEEP
Keep internal texture in video memory.
Definition: alleggl.h:399
void allegro_gl_unset_projection(void)
Restores previously saved projection.
Definition: glvtable.c:2567
#define AGL_TEXTURE_MASKED
Generate an alpha channel for this texture, based on the Allegro mask color.
Definition: alleggl.h:537
void allegro_gl_unset_allegro_mode(void)
Restores previous OpenGL settings.
Definition: glvtable.c:2491
static void allegro_gl_screen_acquire(struct BITMAP *bmp)
acquire_bitmap(screen) overload.
Definition: glvtable.c:160
void allegro_gl_set_projection(void)
Prepares for Allegro drawing to the screen.
Definition: glvtable.c:2540
struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
List of OpenGL extensions supported by AllegroGL.
Definition: glext.c:55
Main header file for AllegroGL.
void allegro_gl_set_allegro_mode(void)
Prepares for Allegro drawing to the screen.
Definition: glvtable.c:2422
GLuint allegro_gl_make_texture(BITMAP *bmp)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1383
#define AGL_TEXTURE_HAS_ALPHA
Tell AllegroGL that the bitmap had an alpha channel, so it should be preserved when generating the te...
Definition: alleggl.h:526
#define AGL_RELEASE
Release video memory occupied by internal texture.
Definition: alleggl.h:400
static void allegro_gl_screen_release(struct BITMAP *bmp)
release_bitmap(screen) overload.
Definition: glvtable.c:170