glvtable.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00012 #include <string.h>
00013 
00014 #include <allegro.h>
00015 
00016 #ifdef ALLEGRO_WINDOWS
00017 #include <winalleg.h>
00018 #endif
00019 
00020 #include "alleggl.h"
00021 #include "allglint.h"
00022 #include "glvtable.h"
00023 #include <allegro/internal/aintern.h>
00024 #ifdef ALLEGRO_MACOSX
00025 #include <OpenGL/glu.h>
00026 #else
00027 #include <GL/glu.h>
00028 #endif
00029 
00030 
00031 static GFX_VTABLE allegro_gl_screen_vtable;
00032 static GLuint __allegro_gl_pool_texture = 0;
00033 
00034 static GLuint __allegro_gl_dummy_texture = 0; /* For ATI Rage Pro */
00035 
00036 
00045 /* Computes the next power of two if the number wasn't a power of two to start
00046  * with. Ref: http://bob.allegronetwork.com/prog/tricks.html#roundtonextpowerof2
00047  */
00048 int __allegro_gl_make_power_of_2(int x) {
00049     x--;
00050     x |= (x >> 1);
00051     x |= (x >> 2);
00052     x |= (x >> 4);
00053     x |= (x >> 8);
00054     x |= (x >> 16);
00055     x++;
00056     return x;
00057 }
00058 
00059 
00060 
00061 static void __allegro_gl_set_drawing_mode(void) {
00062     switch (_drawing_mode) {
00063         case DRAW_MODE_SOLID:
00064             glDisable(GL_BLEND);
00065             glDisable(GL_COLOR_LOGIC_OP);
00066             break;
00067 
00068         case DRAW_MODE_TRANS:
00069             glEnable(GL_BLEND);
00070             break;
00071 
00072         case DRAW_MODE_XOR:
00073             glEnable(GL_COLOR_LOGIC_OP);
00074             glLogicOp(GL_XOR);
00075             break;
00076     }
00077 }
00078 
00079 
00080 
00081 static void __allegro_gl_unset_drawing_mode(void) {
00082     switch (_drawing_mode) {
00083         case DRAW_MODE_TRANS:
00084             glDisable(GL_BLEND);
00085             break;
00086 
00087         case DRAW_MODE_XOR:
00088             glDisable(GL_LOGIC_OP);
00089             break;
00090     }
00091 }
00092 
00093 
00094 
00095 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
00096                         int color_depth)
00097 {
00098     AGL_LOG(2, "glvtable.c:split_color\n");
00099     *r = getr_depth(color_depth, color);
00100     *g = getg_depth(color_depth, color);
00101     *b = getb_depth(color_depth, color);
00102     if (color_depth == 32)
00103         *a = geta_depth(color_depth, color);
00104     else
00105         *a = 255;
00106 }
00107 
00108 
00109 /* allegro_gl_created_sub_bitmap:
00110  */
00111 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
00112 {
00113    bmp->extra = parent;
00114 }
00115 
00116 
00117 /* static void allegro_gl_screen_acquire(struct BITMAP *bmp) */
00123 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
00124 
00125 
00126 
00127 /* static void allegro_gl_screen_release(struct BITMAP *bmp) */
00133 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
00134 
00135 
00136 
00137 static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y)
00138 {
00139     GLubyte pixel[3];
00140     AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
00141     if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00142                                               || y < bmp->ct || y >= bmp->cb)) {
00143         return -1;
00144     }
00145     if (is_sub_bitmap(bmp)) {
00146         x += bmp->x_ofs;
00147         y += bmp->y_ofs;
00148     }
00149     glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
00150 
00151     return makecol_depth(bitmap_color_depth(screen),
00152                                                   pixel[0], pixel[1], pixel[2]);
00153 }
00154 
00155 
00156 
00157 static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y,
00158                                                                       int color)
00159 {
00160     GLubyte r, g, b, a;
00161     AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n");
00162     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00163     if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00164                                               || y < bmp->ct || y >= bmp->cb)) {
00165         return;
00166     }
00167 
00168     if (is_sub_bitmap(bmp)) {
00169         x += bmp->x_ofs;
00170         y += bmp->y_ofs;
00171     }
00172 
00173     glColor4ub(r, g, b, a);
00174     __allegro_gl_set_drawing_mode();
00175     glBegin(GL_POINTS);
00176         glVertex2f(x, y);
00177     glEnd();
00178     __allegro_gl_unset_drawing_mode();
00179 }
00180 
00181 
00182 
00183 static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2,
00184                                                                       int color)
00185 {
00186     GLubyte r, g, b, a;
00187     AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n");
00188 
00189     if (y1 > y2) {
00190         int temp = y1;
00191         y1 = y2;
00192         y2 = temp;
00193     }
00194 
00195     if (bmp->clip) {
00196         if ((x < bmp->cl) || (x >= bmp->cr)) {
00197             return;
00198         }
00199         if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
00200             return;
00201         }
00202         if (y1 < bmp->ct) {
00203             y1 = bmp->ct;
00204         }
00205         if (y2 >= bmp->cb) {
00206             y2 = bmp->cb - 1;
00207         }
00208     }
00209     
00210     if (is_sub_bitmap(bmp)) {
00211         x += bmp->x_ofs;
00212         y1 += bmp->y_ofs;
00213         y2 += bmp->y_ofs;
00214     }
00215 
00216     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00217 
00218     glColor4ub(r, g, b, a);
00219     __allegro_gl_set_drawing_mode();
00220     glBegin(GL_LINES);
00221         glVertex2f(x, y1);
00222         glVertex2f(x, y2 + 0.325 * 3);
00223     glEnd();
00224     __allegro_gl_unset_drawing_mode();
00225 
00226     return;
00227 }
00228 
00229 
00230 
00231 static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2,
00232                                                                       int color)
00233 {
00234     GLubyte r, g, b, a;
00235     AGL_LOG(2, "glvtable.c:allegro_gl_hline\n");
00236     
00237     if (x1 > x2) {
00238         int temp = x1;
00239         x1 = x2;
00240         x2 = temp;
00241     }
00242     if (bmp->clip) {
00243         if ((y < bmp->ct) || (y >= bmp->cb)) {
00244             return;
00245         }
00246         if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
00247             return;
00248         }
00249         if (x1 < bmp->cl) {
00250             x1 = bmp->cl;
00251         }
00252         if (x2 >= bmp->cr) {
00253             x2 = bmp->cr - 1;
00254         }
00255     }
00256     if (is_sub_bitmap(bmp)) {
00257         x1 += bmp->x_ofs;
00258         x2 += bmp->x_ofs;
00259         y += bmp->y_ofs;
00260     }
00261     
00262     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00263     
00264     glColor4ub(r, g, b, a);
00265     __allegro_gl_set_drawing_mode();
00266     glBegin(GL_LINES);
00267         glVertex2f(x1 - 0.325, y);
00268         glVertex2f(x2 + 0.325 * 2, y);
00269     glEnd();
00270     __allegro_gl_unset_drawing_mode();
00271 
00272     return;
00273 }
00274 
00275 
00276 
00277 static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2,
00278                                                               int y2, int color)
00279 {
00280     GLubyte r, g, b, a;
00281     AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n");
00282 
00283     if (bmp->clip) {
00284         glPushAttrib(GL_SCISSOR_BIT);
00285         glEnable(GL_SCISSOR_TEST);
00286         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
00287                                           bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00288     }
00289     if (is_sub_bitmap(bmp)) {
00290         x1 += bmp->x_ofs;
00291         x2 += bmp->x_ofs;
00292         y1 += bmp->y_ofs;
00293         y2 += bmp->y_ofs;
00294     }
00295     
00296     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00297         
00298     glColor4ub(r, g, b, a);
00299     __allegro_gl_set_drawing_mode();
00300     glBegin(GL_LINES);
00301         glVertex2f(x1 + 0.1625, y1 + 0.1625);
00302         glVertex2f(x2 + 0.1625, y2 + 0.1625);
00303     glEnd();
00304 
00305     /* OpenGL skips the endpoint when drawing lines */
00306     glBegin(GL_POINTS);
00307         glVertex2f(x2 + 0.1625, y2 + 0.1625);
00308     glEnd();
00309     __allegro_gl_unset_drawing_mode();
00310     
00311     if (bmp->clip) {
00312         glPopAttrib();
00313     }
00314 
00315     return;
00316 }
00317 
00318 
00319 
00320 static void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1,
00321                                                       int x2, int y2, int color)
00322 {
00323     GLubyte r, g, b, a;
00324     AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n");
00325     
00326     if (x1 > x2) {
00327         int temp = x1;
00328         x1 = x2;
00329         x2 = temp;
00330     }
00331     
00332     if (y1 > y2) {
00333         int temp = y1;
00334         y1 = y2;
00335         y2 = temp;
00336     }
00337     
00338     if (bmp->clip) {
00339         if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
00340             return;
00341         }
00342         if (x1 < bmp->cl) {
00343             x1 = bmp->cl;
00344         }
00345         if (x2 >= bmp->cr) {
00346             x2 = bmp->cr - 1;
00347         }
00348         if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
00349             return;
00350         }
00351         if (y1 < bmp->ct) {
00352             y1 = bmp->ct;
00353         }
00354         if (y2 >= bmp->cb) {
00355             y2 = bmp->cb - 1;
00356         }
00357     }
00358     if (is_sub_bitmap(bmp)) {
00359         x1 += bmp->x_ofs;
00360         x2 += bmp->x_ofs;
00361         y1 += bmp->y_ofs;
00362         y2 += bmp->y_ofs;
00363     }
00364     
00365     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00366     glColor4ub(r, g, b, a);
00367     __allegro_gl_set_drawing_mode();
00368     glRecti(x1, y2, x2, y1);
00369     __allegro_gl_unset_drawing_mode();
00370 
00371     return;
00372 }
00373 
00374 
00375 
00376 static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1,
00377                                       int x2, int y2, int x3, int y3, int color)
00378 {
00379     GLubyte r, g, b, a;
00380     AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n");
00381     
00382     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00383     
00384     if (bmp->clip) {
00385         glPushAttrib(GL_SCISSOR_BIT);
00386         glEnable(GL_SCISSOR_TEST);
00387         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
00388                                           bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00389     }
00390     if (is_sub_bitmap(bmp)) {
00391         x1 += bmp->x_ofs;
00392         y1 += bmp->y_ofs;
00393         x2 += bmp->x_ofs;
00394         y2 += bmp->y_ofs;
00395         x3 += bmp->x_ofs;
00396         y3 += bmp->y_ofs;
00397     }
00398     
00399     glColor4ub(r, g, b, a);
00400     __allegro_gl_set_drawing_mode();
00401     glBegin(GL_TRIANGLES);
00402         glVertex2f(x1, y1);
00403         glVertex2f(x2, y2);
00404         glVertex2f(x3, y3);
00405     glEnd();
00406     __allegro_gl_unset_drawing_mode();
00407     
00408     if (bmp->clip) {
00409         glPopAttrib();
00410     }
00411 }
00412 
00413 
00414 
00415 #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \
00416                                                           width, height) { \
00417     if (dest->clip) {                                                      \
00418         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)                   \
00419          || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \
00420             width = 0;                                                     \
00421         }                                                                  \
00422         if (dest_x < dest->cl) {                                           \
00423             width += dest_x - dest->cl;                                    \
00424             source_x -= dest_x - dest->cl;                                 \
00425             dest_x = dest->cl;                                             \
00426         }                                                                  \
00427         if (dest_y < dest->ct) {                                           \
00428             height += dest_y - dest->ct;                                   \
00429             source_y -= dest_y - dest->ct;                                 \
00430             dest_y = dest->ct;                                             \
00431         }                                                                  \
00432         if (dest_x + width > dest->cr) {                                   \
00433             width = dest->cr - dest_x;                                     \
00434         }                                                                  \
00435         if (dest_y + height > dest->cb) {                                  \
00436             height = dest->cb - dest_y;                                    \
00437         }                                                                  \
00438     }                                                                      \
00439     if (source->clip) {                                                    \
00440         if ((source_x >= source->cr) || (source_y >= source->cb)           \
00441          || (source_x + width < source->cl)                                \
00442          || (source_y + height < source->ct)) {                            \
00443             width = 0;                                                     \
00444         }                                                                  \
00445         if (source_x < source->cl) {                                       \
00446             width += source_x - source->cl;                                \
00447             dest_x -= source_x - source->cl;                               \
00448             source_x = source->cl;                                         \
00449         }                                                                  \
00450         if (source_y < source->ct) {                                       \
00451             height += source_y - source->ct;                               \
00452             dest_y -= source_y - source->ct;                               \
00453             source_y = source->ct;                                         \
00454         }                                                                  \
00455         if (source_x + width > source->cr) {                               \
00456             width = source->cr - source_x;                                 \
00457         }                                                                  \
00458         if (source_y + height > source->cb) {                              \
00459             height = source->cb - source_y;                                \
00460         }                                                                  \
00461     }                                                                      \
00462 }
00463     
00464 
00465 
00466 
00467 static void allegro_gl_screen_blit_from_memory(
00468     struct BITMAP *source, struct BITMAP *dest,
00469     int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00470 {
00471     GLfloat saved_zoom_x, saved_zoom_y;
00472     GLint saved_row_length;
00473     BITMAP *temp = NULL;
00474     void *data;
00475     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n");
00476 
00477     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00478                                                                  width, height);
00479 
00480     if (width <= 0 || height <= 0) {
00481         return;
00482     }
00483     
00484 
00485     if (is_sub_bitmap(dest)) {
00486         dest_x += dest->x_ofs;
00487         dest_y += dest->y_ofs;
00488     }
00489 
00490     /* Note: We don't need to offset the source bitmap coordinates
00491      * because we use source->line[] directly, which is already offsetted for
00492      * us.
00493      */
00494     data = source->line[source_y]
00495          + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source));
00496 
00497     /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
00498      * the bitmap into something GL can understand - 24-bpp should do it.
00499      */
00500     if (!allegro_gl_extensions_GL.EXT_packed_pixels
00501                                            && bitmap_color_depth(source) < 24) {
00502         temp = create_bitmap_ex(24, width, height);
00503 
00504         if (temp) {
00505             blit(source, temp, source_x, source_y, 0, 0, width, height);
00506             source_x = 0;
00507             source_y = 0;
00508             data = temp->line[0];
00509         }
00510         else {
00511             /* XXX <rohannessian> Report error? */
00512             return;
00513         }
00514         source = temp;
00515     }
00516         
00517 
00518     /* Save state */
00519     glGetFloatv(GL_ZOOM_X, &saved_zoom_x);
00520     glGetFloatv(GL_ZOOM_Y, &saved_zoom_y);
00521     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00522 
00523     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00524 
00525     glRasterPos2i(dest_x, dest_y);
00526 
00527     /* XXX <rohannessian> I wonder if it would be faster to use glDrawPixels()
00528      * one line at a time instead of playing with the Zoom factor.
00529      */
00530     glPixelZoom (1.0, -1.0);
00531     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00532                     (source->line[1] - source->line[0])
00533                     / BYTES_PER_PIXEL(source->vtable->color_depth));
00534 
00535     glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0),
00536         __allegro_gl_get_bitmap_type(source, 0), data);
00537 
00538     /* Restore state */
00539     glPixelZoom(saved_zoom_x, saved_zoom_y);
00540     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00541 
00542     if (temp) {
00543         destroy_bitmap(temp);
00544     }
00545     return;
00546 }
00547 
00548 
00549 
00550 static void allegro_gl_screen_blit_to_memory(
00551       struct BITMAP *source, struct BITMAP *dest,
00552       int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00553 {
00554     GLint saved_row_length;
00555     GLint saved_alignment;
00556     GLint saved_pack_invert;
00557 
00558     BITMAP *bmp = NULL;
00559 
00560     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n");
00561 
00562     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00563                                                                  width, height);
00564     
00565     if (is_sub_bitmap(source)) {
00566         source_x += source->x_ofs;
00567         source_y += source->y_ofs;
00568     }
00569     if (is_sub_bitmap(dest)) {
00570         dest_x += dest->x_ofs;
00571         dest_y += dest->y_ofs;
00572     }
00573 
00574     if (width <= 0 || height <= 0) {
00575         return;
00576     }
00577     
00578     /* Note that glPixelZoom doesn't affect reads -- so we have to do a flip.
00579      * We can do this by reading into a temporary bitmap then flipping that to
00580      * the destination, -OR- use the GL_MESA_pack_invert extension to do it
00581      * for us.
00582      *
00583      * If GL_EXT_packed_pixels isn't supported, then we can't use
00584      * MESA_pack_invert on 16-bpp bitmaps or less.
00585      */
00586     
00587     if ( !allegro_gl_extensions_GL.MESA_pack_invert
00588      || (!allegro_gl_extensions_GL.EXT_packed_pixels
00589        && bitmap_color_depth(dest) < 24)) {
00590     
00591         /* XXX <rohannessian> Bitmap format should be the same as the source
00592          * dest bitmap!
00593          */
00594         if ((!allegro_gl_extensions_GL.EXT_packed_pixels
00595            && bitmap_color_depth(dest) < 24)) {
00596             bmp = create_bitmap_ex(24, width, height);
00597         }
00598         else {
00599             bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height);
00600         }
00601         if (!bmp)
00602             return;
00603     }
00604 
00605     glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length);
00606     glGetIntegerv(GL_PACK_ALIGNMENT,  &saved_alignment);
00607     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
00608     glPixelStorei(GL_PACK_ALIGNMENT,  1);
00609 
00610     if (!allegro_gl_extensions_GL.MESA_pack_invert) {
00611 
00612         glReadPixels(source_x, source->h - source_y - height, width, height,
00613             __allegro_gl_get_bitmap_color_format(bmp, 0),
00614             __allegro_gl_get_bitmap_type(bmp, 0), bmp->dat);
00615     }
00616     else {
00617         glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert);
00618         glPixelStorei(GL_PACK_INVERT_MESA, TRUE);
00619         glPixelStorei(GL_PACK_ROW_LENGTH,
00620                       (dest->line[1] - dest->line[0])
00621                        / BYTES_PER_PIXEL(dest->vtable->color_depth));
00622         
00623         glReadPixels(source_x, source->h - source_y - height, width, height,
00624             __allegro_gl_get_bitmap_color_format(dest, 0),
00625             __allegro_gl_get_bitmap_type(dest, 0), dest->line[0]);
00626         
00627         glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert);
00628     }
00629 
00630     glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length);
00631     glPixelStorei(GL_PACK_ALIGNMENT,  saved_alignment);
00632 
00633     /* Flip image if needed (glPixelZoom doesn't affect reads) */
00634     if (bmp) {
00635         
00636         int y, dy;
00637         
00638         for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) {
00639             blit(bmp, dest, 0, y, dest_x, dy, width, 1);
00640         }
00641 
00642         destroy_bitmap(bmp);
00643     }
00644 
00645     return;
00646 }
00647 
00648 
00649 
00650 
00651 void allegro_gl_screen_blit_to_self (
00652      struct BITMAP *source, struct BITMAP *dest,
00653      int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00654 {
00655     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n");
00656 
00657     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00658                                                                  width, height);
00659 
00660     if (is_sub_bitmap(source)) {
00661         source_x += source->x_ofs;
00662         source_y += source->y_ofs;
00663     }
00664     if (is_sub_bitmap(dest)) {
00665         dest_x += dest->x_ofs;
00666         dest_y += dest->y_ofs;
00667     }
00668 
00669     if (width <= 0 || height <= 0) {
00670         return;
00671     }
00672 
00673     /* screen -> screen */
00674     if (is_screen_bitmap(source) && is_screen_bitmap(dest)) {
00675         glRasterPos2i(dest_x, dest_y + height - 1);
00676         glCopyPixels(source_x, SCREEN_H - source_y - height, width, height,
00677                                                                       GL_COLOR);
00678     }
00679     /* video -> screen */
00680     else if (is_screen_bitmap(dest) && is_video_bitmap(source)) {
00681         AGL_VIDEO_BITMAP *vid;
00682         BITMAP *source_parent = source;
00683         GLfloat current_color[4];
00684 
00685         while (source_parent->id & BMP_ID_SUB) {
00686             source_parent = (BITMAP *)source_parent->extra;
00687         }
00688         vid = source_parent->extra;
00689 
00690         glGetFloatv(GL_CURRENT_COLOR, current_color);
00691         glColor4ub(255, 255, 255, 255);
00692 
00693         while (vid) {
00694             int sx, sy;           /* source coordinates */
00695             int dx, dy;           /* destination coordinates */
00696             int w, h;
00697 
00698             if (source_x >= vid->x_ofs + vid->memory_copy->w ||
00699                 source_y >= vid->y_ofs + vid->memory_copy->h ||
00700                 vid->x_ofs >= source_x + width ||
00701                 vid->y_ofs >= source_y + height) {
00702                 vid = vid->next;
00703                 continue;
00704             }
00705 
00706             sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;
00707             w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)
00708               - vid->x_ofs - sx;
00709             sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;
00710             h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height)
00711               - vid->y_ofs - sy;
00712     
00713             dx = dest_x + vid->x_ofs + sx - source_x;
00714             dy = dest_y + vid->y_ofs + sy - source_y;
00715 
00716             glEnable(vid->target);
00717             glBindTexture(vid->target, vid->tex);
00718 
00719             if (vid->target == GL_TEXTURE_2D) {
00720                 float tx = sx / (float)vid->memory_copy->w;
00721                 float ty = sy / (float)vid->memory_copy->h;
00722                 float tw = w / (float)vid->memory_copy->w;
00723                 float th = h / (float)vid->memory_copy->h;
00724 
00725                 glBegin(GL_QUADS);
00726                     glTexCoord2f(tx, ty);
00727                     glVertex2f(dx, dy);
00728                     glTexCoord2f(tx, ty + th);
00729                     glVertex2f(dx, dy + h);
00730                     glTexCoord2f(tx + tw, ty + th);
00731                     glVertex2f(dx + w, dy + h);
00732                     glTexCoord2f(tx + tw, ty);
00733                     glVertex2f(dx + w, dy);
00734                 glEnd();
00735             }
00736             else {
00737                 glBegin(GL_QUADS);
00738                     glTexCoord2i(sx, sy);
00739                     glVertex2f(dx, dy);
00740                     glTexCoord2i(sx, sy + h);
00741                     glVertex2f(dx, dy + h);
00742                     glTexCoord2i(sx + w, sy + h);
00743                     glVertex2f(dx + w, dy + h);
00744                     glTexCoord2i(sx + w, sy);
00745                     glVertex2f(dx + w, dy);
00746                 glEnd();
00747             }
00748 
00749             glBindTexture(vid->target, 0);
00750             glDisable(vid->target);
00751 
00752             vid = vid->next;
00753         }
00754         
00755         glColor4fv(current_color);
00756     }
00757     /* screen -> video */
00758     else if (is_screen_bitmap(source) && is_video_bitmap(dest)) {
00759     
00760         AGL_VIDEO_BITMAP *vid;
00761         BITMAP *source_parent = source;
00762 
00763         while (source_parent->id & BMP_ID_SUB) {
00764             source_parent = (BITMAP *)source_parent->extra;
00765         }
00766 
00767         vid = dest->extra;
00768 
00769         while (vid) {
00770             int sx, sy;           /* source coordinates */
00771             int dx, dy;           /* destination coordinates */
00772             int w, h;
00773 
00774             if (dest_x >= vid->x_ofs + vid->memory_copy->w ||
00775                 dest_y >= vid->y_ofs + vid->memory_copy->h ||
00776                 vid->x_ofs >= dest_x + width ||
00777                 vid->y_ofs >= dest_y + height) {
00778                 vid = vid->next;
00779                 continue;
00780             }
00781 
00782             dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;
00783             w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)
00784               - vid->x_ofs - dx;
00785             dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;
00786             h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)
00787               - vid->y_ofs - dy;
00788     
00789             sx = source_x + vid->x_ofs + dx - dest_x;
00790             sy = source_y + vid->y_ofs + dy - dest_y;
00791 
00792             /* We cannot use glCopyTexSubImage2D() here because it will flip the image. */
00793             allegro_gl_screen_blit_to_memory(source, vid->memory_copy,
00794                                              sx, sy, dx, dy, w, h);
00795 
00796             allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0,
00797                 vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h);
00798 
00799             vid = vid->next;
00800         }
00801     }
00802     else if (is_video_bitmap(source) && is_video_bitmap(dest)) {
00803         allegro_gl_video_blit_to_self(source, dest, source_x, source_y,
00804                                       dest_x, dest_y, width, height);
00805     }
00806 }
00807 
00808 
00809 
00810 void allegro_gl_upload_and_display_texture(struct BITMAP *source,
00811      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00812      int flip_dir, GLint format, GLint type)
00813 {
00814     float tx, ty;
00815     GLint saved_row_length;
00816     int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
00817     int i, j;
00818     
00819     glEnable(GL_ALPHA_TEST);
00820     glAlphaFunc(GL_GREATER, 0.0f);
00821 
00822     glEnable(GL_TEXTURE_2D);
00823     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
00824 
00825     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00826     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00827 
00828     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00829                          (source->line[1] - source->line[0]) / bytes_per_pixel);
00830     
00831     for (i = 0; i <= abs(width) / 256; i++) {
00832         for (j = 0; j <= abs(height) / 256; j++) {
00833 
00834             void *data = source->line[source_y + j * 256]
00835                                        + (source_x + i * 256) * bytes_per_pixel;
00836             int w = abs(width)  - i * 256;
00837             int h = abs(height) - j * 256;
00838             int dx = dest_x + i * 256;
00839             int dy = dest_y + j * 256;
00840 
00841             w = (w & -256) ? 256 : w;
00842             h = (h & -256) ? 256 : h;
00843 
00844             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
00845 
00846             tx = (float)w / 256.;
00847             ty = (float)h / 256.;
00848 
00849             if (flip_dir & AGL_H_FLIP) {
00850                 dx = 2*dest_x + width - dx;
00851                 w = -w;
00852             }
00853 
00854             if (flip_dir & AGL_V_FLIP) {
00855                 dy = 2*dest_y + height - dy;
00856                 h = -h;
00857             }
00858 
00859             if (width < 0)  w = -w;
00860             if (height < 0) h = -h;
00861 
00862             glBegin(GL_QUADS);
00863                 glTexCoord2f(0., 0.);
00864                 glVertex2i(dx, dy);
00865                 glTexCoord2f(0., ty);
00866                 glVertex2i(dx, dy + h);
00867                 glTexCoord2f(tx, ty);
00868                 glVertex2i(dx + w, dy + h);
00869                 glTexCoord2f(tx, 0.);
00870                 glVertex2i(dx + w, dy);
00871             glEnd();
00872         }
00873     }
00874 
00875     /* Restore state */
00876     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00877     glBindTexture(GL_TEXTURE_2D, 0);
00878     glDisable(GL_TEXTURE_2D);
00879     glDisable(GL_ALPHA_TEST);
00880 
00881     return;
00882 }
00883 
00884 
00885 
00886 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)
00887 {
00888     glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
00889 
00890     if (blit_type & AGL_NO_ROTATION) {
00891         GLint saved_row_length;
00892         float dx = dest_x, dy = dest_y;
00893         GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y;
00894 
00895         glEnable(GL_ALPHA_TEST);
00896         glAlphaFunc(GL_GREATER, 0.0f);
00897 
00898         glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00899         glGetFloatv(GL_ZOOM_X, &old_zoom_x);
00900         glGetFloatv(GL_ZOOM_Y, &old_zoom_y);
00901 
00902         if (flip_dir & AGL_H_FLIP) {
00903             zoom_x = -1.0f;   
00904             /* Without the -0.5 below, we get an invalid position,
00905              * and the operation is ignored by OpenGL. */
00906             dx += abs(width) - 0.5;
00907         }
00908         else {
00909             zoom_x = (float) width / abs(width);
00910         }
00911 
00912         if (flip_dir & AGL_V_FLIP) {
00913             zoom_y = 1.0f;
00914             dy += abs(height) - 0.5;
00915         }
00916         else {
00917             zoom_y = -1.0f * width / abs(width);
00918         }
00919 
00920         glRasterPos2f(dx, dy);
00921         glPixelZoom(zoom_x, zoom_y);
00922         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00923         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00924                 (temp->line[1] - temp->line[0])
00925                 / BYTES_PER_PIXEL(bitmap_color_depth(temp)));
00926 
00927         glDrawPixels(abs(width), abs(height), format, type, temp->line[0]);
00928         
00929         glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00930         glPixelZoom(old_zoom_x, old_zoom_y);
00931     }
00932     else {
00933         allegro_gl_upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height,
00934                                    flip_dir, format, type);
00935     }
00936 
00937     glPopAttrib();
00938 }
00939 
00940 
00941 
00942 static void screen_masked_blit_standard(struct BITMAP *source,
00943     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00944     int flip_dir, int blit_type)
00945 {
00946     BITMAP *temp = NULL;
00947 
00948     GLint format, type;
00949     
00950     format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED);
00951     type   = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED);
00952 
00953     temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source,
00954                             source_x, source_y, abs(width), abs(height),
00955                             &type, &format);
00956 
00957     if (temp) {
00958         source = temp;
00959     }
00960 
00961     do_screen_masked_blit_standard(format, type, source, source_x, source_y,
00962         dest_x, dest_y, width, height, flip_dir, blit_type);
00963 
00964     if (temp) {
00965         destroy_bitmap(temp);
00966     }
00967 
00968     return;
00969 }
00970 
00971 
00972 
00973 static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp)
00974 {
00975     GLfloat mask_color[4];
00976     int depth = bitmap_color_depth(bmp);
00977     int color = bitmap_mask_color(bmp);
00978 
00979     mask_color[0] = getr_depth(depth, color) / 255.;
00980     mask_color[1] = getg_depth(depth, color) / 255.;
00981     mask_color[2] = getb_depth(depth, color) / 255.;
00982     mask_color[3] = 0.;
00983 
00984     glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color);
00985     glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
00986     glEnable(GL_REGISTER_COMBINERS_NV);
00987 
00988     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
00989         GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
00990     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
00991         GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
00992     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
00993         GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
00994     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
00995         GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB);
00996     glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV,
00997         GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE,
00998         GL_FALSE, GL_FALSE, GL_FALSE);
00999 
01000     glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
01001         GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01002     glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
01003         GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01004     glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV,
01005         GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE,
01006         GL_TRUE, GL_FALSE, GL_FALSE);
01007 
01008     glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
01009         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01010     glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO,
01011         GL_UNSIGNED_INVERT_NV, GL_RGB);
01012     glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO,
01013         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01014     glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO,
01015         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01016     glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV,
01017         GL_UNSIGNED_IDENTITY_NV, GL_BLUE);
01018 
01019     return;
01020 }
01021 
01022 
01023 
01024 static void screen_masked_blit_nv_register(struct BITMAP *source,
01025     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01026     int flip_dir, int blit_type)
01027 {
01028     BITMAP *temp = NULL;
01029     GLint type   = __allegro_gl_get_bitmap_type(source, 0);
01030     GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01031 
01032     if (type == -1) {
01033         temp = create_bitmap_ex(24, width, height);
01034         if (!temp) {
01035             return;
01036         }
01037         blit(source, temp, source_x, source_y, 0, 0, width, height);
01038         source = temp;
01039         source_x = 0;
01040         source_y = 0;
01041 
01042         type   = __allegro_gl_get_bitmap_type(source, 0);
01043         format = __allegro_gl_get_bitmap_color_format(source, 0);
01044     }
01045 
01046     glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01047     __allegro_gl_init_nv_register_combiners(source);
01048 
01049     allegro_gl_upload_and_display_texture(source, source_x, source_y, dest_x, dest_y,
01050                                width, height, flip_dir, format, type);
01051 
01052     glPopAttrib();
01053 
01054     if (temp) {
01055         destroy_bitmap(temp);
01056     }
01057     return;
01058 }
01059 
01060 
01061 
01062 static void __allegro_gl_init_combine_textures(BITMAP *bmp)
01063 {
01064     GLubyte mask_color[4];
01065 
01066     split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1],
01067         &mask_color[2], &mask_color[3], bitmap_color_depth(bmp));
01068     glColor4ubv(mask_color);
01069 
01070     glActiveTexture(GL_TEXTURE0);
01071     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01072     glEnable(GL_TEXTURE_2D);
01073     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
01074     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01075     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
01076     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
01077 
01078     /* Dot the result of the subtract with itself. Store it in the alpha 
01079      * component. The alpha should then be 0 if the color fragment was equal to 
01080      * the mask color, or >0 otherwise.
01081      */
01082     glActiveTexture(GL_TEXTURE1);
01083     glEnable(GL_TEXTURE_2D);
01084     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01085     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
01086     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
01087     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
01088 
01089     /* Put the original RGB value in its place */
01090 
01091     glActiveTexture(GL_TEXTURE2);
01092     glEnable(GL_TEXTURE_2D);
01093     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01094     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
01095     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01096     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
01097     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
01098 
01099     glActiveTexture(GL_TEXTURE0);
01100 
01101     return;
01102 }
01103 
01104 
01105 
01106 static void screen_masked_blit_combine_tex(struct BITMAP *source,
01107     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01108     int flip_dir, int blit_type)
01109 {
01110     float tx, ty;
01111     BITMAP *temp = NULL;
01112     GLint saved_row_length;
01113     GLint type   = __allegro_gl_get_bitmap_type(source, 0);
01114     GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01115     int bytes_per_pixel;
01116     int i, j;
01117     GLfloat current_color[4];
01118 
01119     if (type == -1) {
01120         temp = create_bitmap_ex(24, width, height);
01121         if (!temp)
01122             return;
01123         blit(source, temp, source_x, source_y, 0, 0, width, height);
01124         source = temp;
01125         source_x = 0;
01126         source_y = 0;
01127 
01128         type   = __allegro_gl_get_bitmap_type(source, 0);
01129         format = __allegro_gl_get_bitmap_color_format(source, 0);
01130     }
01131 
01132     glEnable(GL_TEXTURE_2D);
01133     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01134     
01135     glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01136     glGetFloatv(GL_CURRENT_COLOR, current_color);
01137     __allegro_gl_init_combine_textures(source);
01138     
01139     glActiveTexture(GL_TEXTURE0);
01140     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01141     glActiveTexture(GL_TEXTURE1);
01142     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01143     glActiveTexture(GL_TEXTURE2);
01144     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01145     glActiveTexture(GL_TEXTURE0);
01146     
01147     bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
01148 
01149     glEnable(GL_ALPHA_TEST);
01150     glAlphaFunc(GL_GREATER, 0.0f);
01151 
01152     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01153     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01154 
01155     glPixelStorei(GL_UNPACK_ROW_LENGTH,
01156                          (source->line[1] - source->line[0]) / bytes_per_pixel);
01157 
01158     for (i = 0; i <= width / 256; i++) {
01159         for (j = 0; j <= height / 256; j++) {
01160                 
01161             void *data = source->line[source_y + j * 256]
01162                                        + (source_x + i * 256) * bytes_per_pixel;
01163             int w = width - i * 256;
01164             int h = height - j * 256;
01165             int dx = dest_x + i * 256;
01166             int dy = dest_y + j * 256;
01167 
01168             w = (w & -256) ? 256 : w;
01169             h = (h & -256) ? 256 : h;
01170 
01171             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
01172 
01173             tx = (float)w / 256.;
01174             ty = (float)h / 256.;
01175 
01176             if (flip_dir & AGL_H_FLIP) {
01177                 dx = 2*dest_x + width - dx;
01178                 w = -w;
01179             }
01180 
01181             if (flip_dir & AGL_V_FLIP) {
01182                 dy = 2*dest_y + height - dy;
01183                 h = -h;
01184             }
01185 
01186             glBegin(GL_QUADS);
01187                 glMultiTexCoord2f(GL_TEXTURE0, 0., 0.);
01188                 glMultiTexCoord2f(GL_TEXTURE1, 0., 0.);
01189                 glMultiTexCoord2f(GL_TEXTURE2, 0., 0.);
01190                 glVertex2f(dx, dy);
01191                 glMultiTexCoord2f(GL_TEXTURE0, 0., ty);
01192                 glMultiTexCoord2f(GL_TEXTURE1, 0., ty);
01193                 glMultiTexCoord2f(GL_TEXTURE2, 0., ty);
01194                 glVertex2f(dx, dy + h);
01195                 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01196                 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01197                 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01198                 glVertex2f(dx + w, dy + h);
01199                 glMultiTexCoord2f(GL_TEXTURE0, tx, 0.);
01200                 glMultiTexCoord2f(GL_TEXTURE1, tx, 0.);
01201                 glMultiTexCoord2f(GL_TEXTURE2, tx, 0.);
01202                 glVertex2f(dx + w, dy);
01203             glEnd();
01204         }
01205     }
01206 
01207     /* Restore state */
01208     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01209     glBindTexture(GL_TEXTURE_2D, 0);
01210     glDisable(GL_TEXTURE_2D);
01211     glPopAttrib();
01212     glColor4fv(current_color);
01213 
01214     if (temp) {
01215         destroy_bitmap(temp);
01216     }
01217 
01218     return;
01219 }
01220 
01221 
01222 
01223 void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
01224      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01225      int flip_dir, int blit_type)
01226 {
01227     
01228     /* XXX <rohannessian> We should merge this clip code with the
01229      * BITMAP_BLIT_CLIP macro
01230      */
01231 
01232     /* Clipping of destination bitmap */
01233     if (dest->clip && (blit_type & AGL_NO_ROTATION)) {
01234         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
01235          || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) {
01236             return;
01237         }
01238         if (flip_dir & AGL_H_FLIP) {
01239             if (dest_x < dest->cl) {
01240                 width += dest_x - dest->cl;
01241                 dest_x = dest->cl;
01242             }
01243             if (dest_x + width > dest->cr) {
01244                 source_x += dest_x + width - dest->cr;
01245                 width = dest->cr - dest_x;
01246             }
01247         }
01248         else {
01249             if (dest_x < dest->cl) {
01250                 width += dest_x - dest->cl;
01251                 source_x -= dest_x - dest->cl;
01252                 dest_x = dest->cl;
01253             }
01254             if (dest_x + width > dest->cr) {
01255                 width = dest->cr - dest_x;
01256             }
01257         }
01258         if (flip_dir & AGL_V_FLIP) {
01259             if (dest_y < dest->ct) {
01260                 height += dest_y - dest->ct;
01261                 dest_y = dest->ct;
01262             }
01263             if (dest_y + height > dest->cb) {
01264                 source_y += dest_y + height - dest->cb;
01265                 height = dest->cb - dest_y;
01266             }
01267         }
01268         else {
01269             if (dest_y < dest->ct) {
01270                 height += dest_y - dest->ct;
01271                 source_y -= dest_y - dest->ct;
01272                 dest_y = dest->ct;
01273             }
01274             if (dest_y + height > dest->cb) {
01275                 height = dest->cb - dest_y;
01276             }
01277         }
01278     }
01279 
01280     /* Clipping of source bitmap */
01281     if (source->clip && (blit_type & AGL_REGULAR_BMP)) {
01282         if ((source_x >= source->cr) || (source_y >= source->cb)
01283          || (source_x + width < source->cl)
01284          || (source_y + height < source->ct)) {
01285             return;
01286         }
01287         if (source_x < source->cl) {
01288             width += source_x - source->cl;
01289             dest_x -= source_x - source->cl;
01290             source_x = source->cl;
01291         }
01292         if (source_y < source->ct) {
01293             height += source_y - source->ct;
01294             dest_y -= source_y - source->ct;
01295             source_y = source->ct;
01296         }
01297         if (source_x + width > source->cr) {
01298             width = source->cr - source_x;
01299         }
01300         if (source_y + height > source->cb) {
01301             height = source->cb - source_y;
01302         }
01303     }
01304     if (is_sub_bitmap(dest)) {
01305         dest_x += dest->x_ofs;
01306         dest_y += dest->y_ofs;
01307     }
01308     if (width <= 0 || height <= 0)
01309         return;
01310 
01311     /* memory -> screen */
01312     if (!is_video_bitmap(source) && !is_screen_bitmap(source)) {
01313 
01314         __allegro_gl_driver->screen_masked_blit(source, source_x, source_y,
01315                             dest_x, dest_y, width, height, flip_dir, blit_type);
01316     }
01317     /* video -> screen */
01318     else if (is_video_bitmap(source)) {
01319         AGL_VIDEO_BITMAP *vid;
01320         BITMAP *source_parent = source;
01321 
01322         int use_combiners = 0;
01323 
01324         /* Special combiner paths */
01325         if (allegro_gl_extensions_GL.NV_register_combiners
01326          || allegro_gl_info.num_texture_units >= 3) {
01327 
01328             use_combiners = 1;
01329 
01330             glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
01331 
01332             if (allegro_gl_extensions_GL.NV_register_combiners) {
01333                 __allegro_gl_init_nv_register_combiners(source);
01334             }
01335             else {
01336                 __allegro_gl_init_combine_textures(source);
01337             }
01338 
01339             glEnable(GL_ALPHA_TEST);
01340             glAlphaFunc(GL_GREATER, 0.0f);
01341         }
01342 
01343         while (source_parent->id & BMP_ID_SUB) {
01344             source_parent = (BITMAP *)source_parent->extra;
01345         }
01346         vid = source_parent->extra;
01347 
01348         while (vid) {
01349             int sx, sy;           /* source coordinates */
01350             int dx, dy;           /* destination coordinates */
01351             int w, h;
01352 
01353             if (source_x >= vid->x_ofs + vid->memory_copy->w ||
01354                 source_y >= vid->y_ofs + vid->memory_copy->h ||
01355                 vid->x_ofs >= source_x + width ||
01356                 vid->y_ofs >= source_y + height) {
01357                 vid = vid->next;
01358                 continue;
01359             }
01360 
01361             sx = MAX (vid->x_ofs, source_x) - vid->x_ofs;
01362             w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width)
01363               - vid->x_ofs - sx;
01364             sy = MAX (vid->y_ofs, source_y) - vid->y_ofs;
01365             h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height)
01366               - vid->y_ofs - sy;
01367 
01368             dx = dest_x + vid->x_ofs + sx - source_x;
01369             dy = dest_y + vid->y_ofs + sy - source_y;
01370 
01371             if (flip_dir & AGL_H_FLIP) {
01372                 dx = 2*dest_x + width - dx;
01373                 w = -w;
01374             }
01375 
01376             if (flip_dir & AGL_V_FLIP) {
01377                 dy = 2*dest_y + height - dy;
01378                 h = -h;
01379             }
01380 
01381             if (use_combiners) {
01382                 if (allegro_gl_extensions_GL.NV_register_combiners) {
01383                     glEnable(vid->target);
01384                     glBindTexture(vid->target, vid->tex);
01385                     glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01386                     glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01387 
01388                     if (vid->target == GL_TEXTURE_2D) {
01389                         float tx = sx / (float)vid->memory_copy->w;
01390                         float ty = sy / (float)vid->memory_copy->h;
01391                         float tw = abs(w) / (float)vid->memory_copy->w;
01392                         float th = abs(h) / (float)vid->memory_copy->h;
01393 
01394                         glBegin(GL_QUADS);
01395                             glTexCoord2f(tx, ty);
01396                             glVertex2f(dx, dy);
01397                             glTexCoord2f(tx, ty + th);
01398                             glVertex2f(dx, dy + h);
01399                             glTexCoord2f(tx + tw, ty + th);
01400                             glVertex2f(dx + w, dy + h);
01401                             glTexCoord2f(tx + tw, ty);
01402                             glVertex2f(dx + w, dy);
01403                         glEnd();
01404                     }
01405                     else {
01406                         glBegin(GL_QUADS);
01407                             glTexCoord2i(sx, sy);
01408                             glVertex2f(dx, dy);
01409                             glTexCoord2i(sx, sy + h);
01410                             glVertex2f(dx, dy + h);
01411                             glTexCoord2i(sx + w, sy + h);
01412                             glVertex2f(dx + w, dy + h);
01413                             glTexCoord2i(sx + w, sy);
01414                             glVertex2f(dx + w, dy);
01415                         glEnd();
01416                     }
01417 
01418                     glBindTexture(vid->target, 0);
01419                     glDisable(vid->target);
01420                 }
01421                 else {
01422                     glEnable(vid->target);
01423                     glActiveTexture(GL_TEXTURE0);
01424                     glBindTexture(vid->target, vid->tex);
01425                     glActiveTexture(GL_TEXTURE1);
01426                     glBindTexture(vid->target, vid->tex);
01427                     glActiveTexture(GL_TEXTURE2);
01428                     glBindTexture(vid->target, vid->tex);
01429                     glActiveTexture(GL_TEXTURE0);
01430                     glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01431                     glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01432 
01433                     if (vid->target == GL_TEXTURE_2D) {
01434                         float tx, ty, tw, th; /* texture coordinates */
01435                         tx = sx / (float)vid->memory_copy->w;
01436                         ty = sy / (float)vid->memory_copy->h;
01437                         tw = abs(w) / (float)vid->memory_copy->w;
01438                         th = abs(h) / (float)vid->memory_copy->h;
01439 
01440                         glBegin(GL_QUADS);
01441                             glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01442                             glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01443                             glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01444                             glVertex2f(dx, dy);
01445                             glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th);
01446                             glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th);
01447                             glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th);
01448                             glVertex2f(dx, dy + h);
01449                             glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th);
01450                             glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th);
01451                             glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th);
01452                             glVertex2f(dx + w, dy + h);
01453                             glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty);
01454                             glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty);
01455                             glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty);
01456                             glVertex2f(dx + w, dy);
01457                         glEnd();
01458                     }
01459                     else {
01460                         glBegin(GL_QUADS);
01461                             glMultiTexCoord2i(GL_TEXTURE0, dx, dy);
01462                             glMultiTexCoord2i(GL_TEXTURE1, dx, dy);
01463                             glMultiTexCoord2i(GL_TEXTURE2, dx, dy);
01464                             glVertex2f(dx, dy);
01465                             glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h);
01466                             glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h);
01467                             glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h);
01468                             glVertex2f(dx, dy + h);
01469                             glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h);
01470                             glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h);
01471                             glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h);
01472                             glVertex2f(dx + w, dy + h);
01473                             glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy);
01474                             glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy);
01475                             glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy);
01476                             glVertex2f(dx + w, dy);
01477                         glEnd();
01478                     }
01479 
01480                     glBindTexture(vid->target, 0);
01481                     glDisable(vid->target);
01482                 }
01483             }
01484             else {
01485                 screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy,
01486                                             w, h, FALSE, blit_type);
01487             }
01488 
01489             vid = vid->next;
01490         }
01491 
01492         if (use_combiners) {
01493             glPopAttrib();
01494         }
01495     }
01496     return;
01497 }
01498 
01499 
01500 
01501 static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans)
01502 {
01503     BITMAP *temp = NULL;
01504     int y, x, src_depth;
01505     signed long src_mask;
01506 
01507     #define DRAW_RLE_8888(bits)                 \
01508     {                               \
01509         for (y = 0; y < sprite->h; y++) {           \
01510             signed long c = *s++;               \
01511             for (x = 0; x < sprite->w;) {           \
01512                 if (c == src_mask)          \
01513                     break;              \
01514                 if (c > 0) {                \
01515                     /* Run of solid pixels */   \
01516                     for (c--; c>=0; c--) {      \
01517                         unsigned long col = *s++;       \
01518                         if (bits == 32 && trans)        \
01519                             _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
01520                         else            \
01521                             _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
01522                     }               \
01523                 }                   \
01524                 else {                  \
01525                     /* Run of transparent pixels */ \
01526                     hline(temp, x, y, x-c+1, 0);    \
01527                     x -= c;             \
01528                 }                   \
01529                 c = *s++;               \
01530             }                       \
01531         }                           \
01532     }
01533 
01534     src_depth = sprite->color_depth;
01535     if (src_depth == 8)
01536         src_mask = 0;
01537     else
01538         src_mask = makecol_depth(src_depth, 255, 0, 255);
01539 
01540     temp = create_bitmap_ex(32, sprite->w, sprite->h);
01541     if (!temp) return NULL;
01542 
01543     /* RGBA 8888 */
01544     switch(src_depth) {
01545         case 8:
01546         {
01547             signed char *s = (signed char*)sprite->dat;
01548             DRAW_RLE_8888(8);
01549             break;
01550         }
01551         case 15:
01552         {
01553             int16_t *s = (int16_t*)sprite->dat;
01554             DRAW_RLE_8888(15);
01555             break;
01556         }
01557         case 16:
01558         {
01559             int16_t *s = (int16_t*)sprite->dat;
01560             DRAW_RLE_8888(16);
01561             break;
01562         }
01563         case 24:
01564         {
01565             int32_t *s = (int32_t*)sprite->dat;
01566             DRAW_RLE_8888(24);
01567             break;
01568         }
01569         case 32:
01570         {
01571             int32_t *s = (int32_t*)sprite->dat;
01572             DRAW_RLE_8888(32);
01573             break;
01574         }
01575     }
01576 
01577     return temp;
01578 }
01579 
01580 
01581 
01582 void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
01583 {
01584     BITMAP *temp = NULL, *temp2 = NULL;
01585     int source_x = 0, source_y = 0;
01586     int width = sprite->w, height = sprite->h;
01587 
01588     temp = __allegro_gl_convert_rle_sprite(sprite, FALSE);
01589     if (!temp)
01590         return;
01591 
01592     BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01593     
01594     if (is_sub_bitmap(bmp)) {
01595         x += bmp->x_ofs;
01596         y += bmp->y_ofs;
01597     }
01598 
01599     if (width <= 0 || height <= 0) {
01600         destroy_bitmap(temp);
01601         return;
01602     }
01603 
01604     temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01605     if (!temp2) {
01606         destroy_bitmap(temp);
01607         return;
01608     }
01609 
01610     do_screen_masked_blit_standard(GL_RGBA, 
01611         __allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2,
01612         0, 0, x, y, width, height, FALSE, AGL_NO_ROTATION);
01613 
01614     destroy_bitmap(temp2);
01615     destroy_bitmap(temp);
01616 }
01617 
01618 
01619 static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp,
01620                             AL_CONST struct RLE_SPRITE *sprite, int x, int y) {
01621     BITMAP *temp = NULL, *temp2 = NULL;
01622     int source_x = 0, source_y = 0;
01623     int width = sprite->w, height = sprite->h;
01624 
01625     temp = __allegro_gl_convert_rle_sprite(sprite, TRUE);
01626     if (!temp)
01627         return;
01628 
01629     BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01630     
01631     if (is_sub_bitmap(bmp)) {
01632         x += bmp->x_ofs;
01633         y += bmp->y_ofs;
01634     }
01635 
01636     if (width <= 0 || height <= 0) {
01637         destroy_bitmap(temp);
01638         return;
01639     }
01640 
01641     temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01642     if (!temp2) {
01643         destroy_bitmap(temp);
01644         return;
01645     }
01646     
01647     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01648         glEnable(GL_COLOR_LOGIC_OP);
01649     else
01650         glEnable(GL_BLEND);
01651 
01652     allegro_gl_upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE);
01653     
01654     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01655         glDisable(GL_COLOR_LOGIC_OP);
01656     else
01657         glDisable(GL_BLEND);
01658 
01659     destroy_bitmap(temp2);
01660     destroy_bitmap(temp);
01661 }
01662 
01663 
01664 
01665 static void allegro_gl_screen_masked_blit(struct BITMAP *source,
01666     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
01667     int width, int height)
01668 {
01669     AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n");
01670     do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y,
01671                           width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
01672 }
01673 
01674 
01675 
01676 static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp,
01677     struct BITMAP *sprite, int x, int y)
01678 {
01679     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n");
01680     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01681                           FALSE, AGL_NO_ROTATION);
01682 }
01683 
01684 
01685 
01686 static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp,
01687     struct BITMAP *sprite, int x, int y)
01688 {
01689     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n");
01690     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01691                           AGL_V_FLIP, AGL_NO_ROTATION);
01692 }
01693 
01694 
01695 
01696 static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp,
01697     struct BITMAP *sprite, int x, int y)
01698 {
01699     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n");
01700     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01701                           AGL_H_FLIP, AGL_NO_ROTATION);
01702 }
01703 
01704 
01705 
01706 static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp,
01707     struct BITMAP *sprite, int x, int y)
01708 {
01709     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n");
01710     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01711                           AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
01712 }
01713 
01714 
01715 
01716 static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp,
01717     struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle,
01718     fixed scale, int v_flip)
01719 {
01720     double dscale = fixtof(scale);
01721     GLint matrix_mode;
01722     AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n");
01723     
01724 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
01725     
01726     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01727     glMatrixMode(GL_MODELVIEW);
01728     glPushMatrix();
01729     glTranslated(fixtof(x), fixtof(y), 0.);
01730     glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
01731     glScaled(dscale, dscale, dscale);
01732     glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
01733     
01734     do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
01735                           sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
01736     glPopMatrix();
01737     glMatrixMode(matrix_mode);
01738 
01739 #undef BIN_2_DEG
01740 
01741     return;
01742 }
01743 
01744 
01745 
01746 static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp,
01747     struct BITMAP *sprite, int x, int y) {
01748 
01749     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01750         glEnable(GL_COLOR_LOGIC_OP);
01751     else
01752         glEnable(GL_BLEND);
01753 
01754     /* video -> screen */
01755     if (is_video_bitmap(sprite)) {
01756         allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h);
01757     }
01758     /* memory -> screen */
01759     else if (is_memory_bitmap(sprite)) {
01760         GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
01761         GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
01762         allegro_gl_upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, format, type);
01763     }
01764     
01765     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01766         glDisable(GL_COLOR_LOGIC_OP);
01767     else
01768         glDisable(GL_BLEND);
01769     
01770     return;
01771 }
01772 
01773 
01774 
01775 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
01776                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01777                                   int color, int bg, int flip)
01778 {
01779     GLubyte r, g, b, a;
01780     int x_offs = 0;
01781     int i;
01782 
01783     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n");
01784     
01785     if (bmp->clip) {
01786         glPushAttrib(GL_SCISSOR_BIT);
01787         glEnable(GL_SCISSOR_TEST);
01788         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
01789                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
01790 
01791         if (x < bmp->cl) {
01792             x_offs -= x - bmp->cl;
01793             x = bmp->cl;
01794         }
01795     }
01796     if (is_sub_bitmap(bmp)) {
01797         x += bmp->x_ofs;
01798         y += bmp->y_ofs;
01799     }
01800     
01801     if (bg != -1) {
01802         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01803         glColor4ub(r, g, b, a);
01804         glRecti(x, y, x + glyph->w, y + glyph->h);              
01805     }
01806 
01807     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01808     glColor4ub(r, g, b, a);
01809     glRasterPos2i(x, y);
01810     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01811     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01812 
01813     if (flip) {
01814         for (i = 0; i < glyph->h; i++) {
01815             glBitmap(glyph->w, 1, x_offs, i, 0, 2,
01816                                          glyph->dat + i * ((glyph->w + 7) / 8));
01817         }
01818     }
01819     else {
01820         for (i = 0; i < glyph->h; i++) {
01821             glBitmap(glyph->w, 1, x_offs, i, 0, 0,
01822                                          glyph->dat + i * ((glyph->w + 7) / 8));
01823         }
01824     }
01825     
01826     if (bmp->clip) {
01827         glPopAttrib();
01828     }
01829 
01830     return;
01831 }
01832 
01833 
01834 
01835 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
01836                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01837                                   int color, int bg) {
01838     allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0);
01839 }
01840 
01841 
01842 
01843 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
01844     struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
01845 {
01846 
01847     /* Implementation note: we should try building textures and see how well
01848      * those work instead of of DrawPixels with a weird I_TO_RGBA mapping.
01849      */
01850     static GLfloat red_map[256];
01851     static GLfloat green_map[256];
01852     static GLfloat blue_map[256];
01853     static GLfloat alpha_map[256];
01854     GLubyte r, g, b, a;
01855     int i;
01856     GLint saved_row_length;
01857     GLint width, height;
01858     int sprite_x = 0, sprite_y = 0;
01859     void *data;
01860     int *table;
01861 
01862     width = sprite->w;
01863     height = sprite->h;
01864 
01865     if (bmp->clip) {
01866         if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
01867          || (y + height < bmp->ct)) {
01868             return;
01869         }
01870         if (x < bmp->cl) {
01871             width += x - bmp->cl;
01872             sprite_x -= (x - bmp->cl);
01873             x = bmp->cl;
01874         }
01875         if (y < bmp->ct) {
01876             height += y - bmp->ct;
01877             sprite_y -= (y - bmp->ct);
01878             y = bmp->ct;
01879         }
01880         if (x + width > bmp->cr) {
01881             width = bmp->cr - x;
01882         }
01883         if (y + height > bmp->cb) {
01884             height = bmp->cb - y;
01885         }
01886     }
01887     if (is_sub_bitmap(bmp)) {
01888         x += bmp->x_ofs;
01889         y += bmp->y_ofs;
01890     }
01891 
01892     data = sprite->line[sprite_y]
01893          + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
01894 
01895     if (bg < 0) {
01896         glAlphaFunc(GL_GREATER, 0.0f);
01897         glEnable(GL_ALPHA_TEST);
01898         alpha_map[0] = 0.;
01899     }
01900     else {
01901         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01902         red_map[0] = r / 255.;
01903         green_map[0] = g / 255.;
01904         blue_map[0] = b / 255.;
01905         alpha_map[0] = 1.;
01906     }
01907 
01908     if (color < 0) {
01909         table = _palette_expansion_table(bitmap_color_depth(bmp));
01910 
01911         for(i = 1; i < 255; i++) {
01912             split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
01913             red_map[i] = r / 255.;
01914             green_map[i] = g / 255.;
01915             blue_map[i] = b / 255.;
01916             alpha_map[i] = 1.;
01917         }
01918     }
01919     else {
01920         split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01921 
01922         for(i = 1; i < 255; i++) {
01923             red_map[i] = r / 255.;
01924             green_map[i] = g / 255.;
01925             blue_map[i] = b / 255.;
01926             alpha_map[i] = 1.;
01927         }
01928     }
01929     
01930     glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
01931     glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
01932     glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
01933     glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
01934     
01935     glRasterPos2i(x, y);
01936     glPushAttrib(GL_PIXEL_MODE_BIT);
01937     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01938     
01939     glPixelZoom(1.0, flip ? -1.0 : 1.0);
01940     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01941     glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
01942     glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
01943 
01944     glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
01945     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01946     glPopAttrib();
01947     if (bg < 0) {
01948         glDisable(GL_ALPHA_TEST);
01949     }
01950 
01951     return;
01952 }
01953 
01954 
01955 
01956 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
01957     struct BITMAP *sprite, int x, int y, int color, int bg) {
01958     allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1);
01959 }
01960 
01961 
01962 
01963 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
01964                          struct BITMAP *sprite, int x, int y, int color, int bg)
01965 {
01966     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
01967     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
01968 }
01969 
01970 
01971 
01972 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
01973                                             struct BITMAP *sprite, int x, int y)
01974 {
01975     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
01976     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1);
01977 }
01978 
01979 
01980 
01981 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
01982 {
01983     GLubyte r, g, b, a;
01984     GLfloat old_col[4];
01985 
01986     AGL_LOG(2, "glvtable.c:allegro_gl_screen_clear_to_color\n");
01987     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01988     
01989     glPushAttrib(GL_SCISSOR_BIT);
01990 
01991     glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
01992     glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
01993                  ((float) a / 255));
01994 
01995     if (bmp->clip) {
01996         glEnable(GL_SCISSOR_TEST);
01997         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
01998                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
01999     }
02000     else {
02001         glScissor(0, 0, SCREEN_W, SCREEN_H);
02002     }
02003 
02004     __allegro_gl_set_drawing_mode();
02005     glClear(GL_COLOR_BUFFER_BIT);
02006     __allegro_gl_unset_drawing_mode();
02007 
02008     glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
02009 
02010     glPopAttrib();
02011 
02012     return;
02013 }
02014 
02015 
02016 
02017 /* TODO: Handle concave and self-intersecting. */
02018 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
02019                                       AL_CONST int *points, int color) {
02020     GLubyte r, g, b, a;
02021     int i;
02022 
02023     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02024     glColor4ub(r, g, b, a);
02025     
02026     glPushAttrib(GL_SCISSOR_BIT);
02027 
02028     if (bmp->clip) {
02029         glEnable(GL_SCISSOR_TEST);
02030         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02031                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02032     }
02033     else {
02034         glScissor(0, 0, SCREEN_W, SCREEN_H);
02035     }
02036 
02037     __allegro_gl_set_drawing_mode();
02038     glBegin(GL_POLYGON);
02039         for (i = 0; i < vertices*2-1; i+=2) {
02040             if (is_sub_bitmap(bmp)) {
02041                 glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
02042             }
02043             else {
02044                 glVertex2f(points[i], points[i+1]);
02045             }
02046         }
02047     glEnd();
02048     __allegro_gl_unset_drawing_mode();
02049 
02050     glPopAttrib();
02051 }
02052 
02053 
02054 
02055 static void allegro_gl_screen_rect(struct BITMAP *bmp,
02056                                    int x1, int y1, int x2, int y2, int color) {
02057     GLubyte r, g, b, a;
02058 
02059     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02060     glColor4ub(r, g, b, a);
02061     
02062     glPushAttrib(GL_SCISSOR_BIT);
02063 
02064     if (bmp->clip) {
02065         glEnable(GL_SCISSOR_TEST);
02066         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02067                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02068     }
02069     else {
02070         glScissor(0, 0, SCREEN_W, SCREEN_H);
02071     }
02072     if (is_sub_bitmap(bmp)) {
02073         x1 += bmp->x_ofs;
02074         x2 += bmp->x_ofs;
02075         y1 += bmp->y_ofs;
02076         y2 += bmp->y_ofs;
02077     }
02078 
02079     __allegro_gl_set_drawing_mode();
02080     glBegin(GL_LINE_STRIP);
02081         glVertex2f(x1, y1);
02082         glVertex2f(x2, y1);
02083         glVertex2f(x2, y2);
02084         glVertex2f(x1, y2);
02085         glVertex2f(x1, y1);
02086     glEnd();
02087     __allegro_gl_unset_drawing_mode();
02088 
02089     glPopAttrib();
02090 }
02091 
02092 
02093 
02094 static void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
02095                                           struct BITMAP *texture, int vc,
02096                                           V3D_f *vtx[]) {
02097     int i;
02098     int use_z = FALSE;
02099 
02100     if (type & POLYTYPE_ZBUF) {
02101         use_z = TRUE;
02102         type &= ~POLYTYPE_ZBUF;
02103     }
02104 
02105     /* Other rendering types are not implemented yet. */
02106     if ((type != POLYTYPE_FLAT) && (type != POLYTYPE_GRGB)
02107       && (type != POLYTYPE_GCOL)) {
02108         if (texture && !is_video_bitmap(texture))
02109             _soft_polygon3d_f(bmp, type, texture, vc, vtx);
02110         return;
02111     }
02112 
02113     if (bmp->clip) {
02114         glEnable(GL_SCISSOR_TEST);
02115         glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02116                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02117     }
02118     else {
02119         glScissor(0, 0, SCREEN_W, SCREEN_H);
02120     }
02121     if (is_sub_bitmap(bmp)) {
02122         for (i = 0; i < vc*2-1; i+=2) {
02123             vtx[i] += bmp->x_ofs;
02124             vtx[i+1] += bmp->y_ofs;
02125         }
02126     }
02127 
02128     if (use_z) {
02129         glEnable(GL_DEPTH_TEST);
02130         glDepthFunc(GL_LESS);
02131         glDepthMask(GL_TRUE);
02132     }
02133     else
02134         __allegro_gl_set_drawing_mode();
02135 
02136     glBegin(GL_POLYGON);
02137         for (i = 0; i < vc; i++) {
02138             if (type == POLYTYPE_FLAT)
02139                 glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
02140             else if (type == POLYTYPE_GRGB)
02141                 glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
02142             else if (type == POLYTYPE_GCOL)
02143                 glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
02144 
02145             if (use_z)
02146                 glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
02147             else
02148                 glVertex2f(vtx[i]->x, vtx[i]->y);
02149         }
02150         if (use_z)
02151             glVertex3f(vtx[0]->x, vtx[0]->y, 1.f / vtx[0]->z);
02152         else
02153             glVertex2f(vtx[0]->x, vtx[0]->y);
02154 
02155     glEnd();
02156 
02157     if (use_z) {
02158         glDisable(GL_DEPTH_TEST);
02159         glDepthMask(GL_FALSE);
02160     }
02161     else
02162         __allegro_gl_unset_drawing_mode();
02163 }
02164 
02165 
02166 
02167 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
02168                                         struct BITMAP *texture, int vc,
02169                                         V3D *vtx[]) {
02170     int i;
02171     V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
02172     if (!vtx_f)
02173         return;
02174 
02175     for (i = 0; i < vc; i++) {
02176         vtx_f[i] = malloc(sizeof(struct V3D_f));
02177         if (!vtx_f[i]) {
02178             int k;
02179             for (k = 0; k < i; k++)
02180                 free(vtx_f[k]);
02181             free(vtx_f);
02182             return;
02183         }
02184         vtx_f[i]->c = vtx[i]->c;
02185         vtx_f[i]->u = fixtof(vtx[i]->u);
02186         vtx_f[i]->v = fixtof(vtx[i]->v);
02187         vtx_f[i]->x = fixtof(vtx[i]->x);
02188         vtx_f[i]->y = fixtof(vtx[i]->y);
02189         vtx_f[i]->z = fixtof(vtx[i]->z);
02190     }
02191 
02192     allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
02193     for (i = 0; i < vc; i++)
02194         free(vtx_f[i]);
02195     free(vtx_f);
02196 }
02197 
02198 
02199 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
02200                                        struct BITMAP *texture,
02201                                        V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
02202 
02203     V3D_f *vtx_f[4];
02204     vtx_f[0] = v1;
02205     vtx_f[1] = v2;
02206     vtx_f[2] = v3;
02207     vtx_f[3] = v4;
02208 
02209     allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
02210 }
02211 
02212 
02213 
02214 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
02215             struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
02216 
02217     V3D *vtx[4];
02218     vtx[0] = v1;
02219     vtx[1] = v2;
02220     vtx[2] = v3;
02221     vtx[3] = v4;
02222 
02223     allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
02224 }
02225 
02226 
02227 
02228 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
02229                                          struct BITMAP *texture,
02230                                          V3D *v1, V3D *v2, V3D *v3) {
02231     V3D *vtx[3];
02232     vtx[0] = v1;
02233     vtx[1] = v2;
02234     vtx[2] = v3;
02235 
02236     allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
02237 }
02238 
02239 
02240 
02241 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
02242                                            struct BITMAP *texture,
02243                                            V3D_f *v1, V3D_f *v2, V3D_f *v3) {
02244     V3D_f *vtx_f[3];
02245     vtx_f[0] = v1;
02246     vtx_f[1] = v2;
02247     vtx_f[2] = v3;
02248 
02249     allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
02250 }
02251 
02252 
02253 
02254 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
02255 {
02256     int maskcolor = (*vtable)->mask_color;
02257     int depth = (*vtable)->color_depth;
02258 
02259     AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
02260     allegro_gl_screen_vtable.color_depth = depth;
02261     /* makecol_depth is used below instead of the MASK_COLOR_x constants
02262      * because we may have changed the RGB shift values in order to
02263      * use the packed pixels extension
02264      */
02265     allegro_gl_screen_vtable.mask_color =
02266         makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
02267     
02268     *vtable = &allegro_gl_screen_vtable;
02269 
02270     __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
02271     if (allegro_gl_extensions_GL.NV_register_combiners) {
02272         __allegro_gl_driver->screen_masked_blit
02273                                                = screen_masked_blit_nv_register;
02274     }
02275     else if (allegro_gl_info.num_texture_units >= 3) {
02276         __allegro_gl_driver->screen_masked_blit =
02277                                                  screen_masked_blit_combine_tex;
02278     }
02279 }
02280 
02281 
02282 
02283 /* Saved projection matrix */
02284 static double allegro_gl_projection_matrix[16];
02285 static double allegro_gl_modelview_matrix[16];
02286 
02287 
02288 
02319 void allegro_gl_set_allegro_mode(void)
02320 {
02321     AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
02322 
02323     /* Save the OpenGL state  then set it up */
02324     glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
02325                | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02326     glDisable(GL_DEPTH_TEST);
02327     glDisable(GL_CULL_FACE);
02328     glDisable(GL_FOG);
02329     glDisable(GL_LIGHTING);
02330     glDisable(GL_BLEND);
02331     glDisable(GL_ALPHA_TEST);
02332     glDepthMask(GL_FALSE);
02333     glEnable(GL_TEXTURE_2D);
02334     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02335     glPointSize(1.);
02336 
02337     /* Create pool texture */
02338     if (!__allegro_gl_pool_texture) {
02339         glGenTextures(1, &__allegro_gl_pool_texture);
02340     }
02341 
02342     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
02343         /* Create a texture without defining the data */
02344     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
02345                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
02346     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02347     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02348 
02349     glBindTexture(GL_TEXTURE_2D, 0);
02350     allegro_gl_set_projection();
02351 
02352     /* For some reason, ATI Rage Pro isn't able to draw correctly without a
02353      * texture bound. So we bind a dummy 1x1 texture to work around the issue.
02354      */
02355     if (allegro_gl_info.is_ati_rage_pro) {
02356         if (!__allegro_gl_dummy_texture) {
02357             GLubyte tex[4] = {255, 255, 255, 255};
02358             glGenTextures(1, &__allegro_gl_dummy_texture);
02359             glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02360             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
02361                          GL_RGBA, GL_UNSIGNED_BYTE, tex);
02362         }
02363         glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02364     }
02365 #ifdef ALLEGRO_MACOSX
02366     /* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in
02367      *'blit'). This stops it happening.
02368      */
02369     glBegin(GL_POINTS);
02370     glEnd();
02371 #endif
02372 }
02373 
02374 
02375 
02388 void allegro_gl_unset_allegro_mode(void)
02389 {
02390     AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
02391 
02392     switch(allegro_gl_display_info.vidmem_policy) {
02393         case AGL_KEEP:
02394             break;
02395         case AGL_RELEASE:
02396             if (__allegro_gl_pool_texture) {
02397                 glDeleteTextures(1, &__allegro_gl_pool_texture);
02398                 __allegro_gl_pool_texture = 0;
02399             }
02400             break;
02401     }
02402     allegro_gl_unset_projection();
02403     glPopAttrib();
02404 }
02405 
02406 
02407 
02437 void allegro_gl_set_projection(void)
02438 {
02439     GLint v[4];
02440     AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
02441     
02442     /* Setup OpenGL matrices */
02443     glGetIntegerv(GL_VIEWPORT, &v[0]);
02444     glMatrixMode(GL_MODELVIEW);
02445     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
02446     glLoadIdentity();
02447     glMatrixMode(GL_PROJECTION);
02448     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
02449     glLoadIdentity();
02450     gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
02451 }
02452 
02453 
02454 
02464 void allegro_gl_unset_projection(void)
02465 {
02466     AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
02467     glMatrixMode(GL_PROJECTION);
02468     glLoadMatrixd(allegro_gl_projection_matrix);
02469     glMatrixMode(GL_MODELVIEW);
02470     glLoadMatrixd(allegro_gl_modelview_matrix);
02471 }
02472 
02473 
02474 
02475 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
02476     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
02477     int width, int height)
02478 {
02479     AGL_LOG(2, "AGL::blit_between_formats\n");
02480 
02481     /* screen -> memory */
02482     if (is_screen_bitmap(src)) {
02483         allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
02484                                          dest_x, dest_y, width, height);
02485         return;
02486     }
02487 
02488     /* video -> memory */
02489     if (is_video_bitmap(src)) {
02490         allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
02491                                         dest_x, dest_y, width, height);
02492         return;
02493     }
02494     
02495     /* memory -> screen */
02496     if (is_screen_bitmap(dest)) {
02497         allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
02498                                            dest_x, dest_y, width, height);
02499         return;
02500     }
02501 
02502     /* memory -> video */
02503     if (is_video_bitmap(dest)) {
02504         allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
02505                                           dest_x, dest_y, width, height);
02506         return;
02507     }
02508 
02509     switch(bitmap_color_depth(dest)) {
02510         #ifdef ALLEGRO_COLOR8
02511         case 8:
02512             __blit_between_formats8(src, dest, source_x, source_y,
02513                                     dest_x, dest_y, width, height);
02514             return;
02515         #endif
02516         #ifdef ALLEGRO_COLOR16
02517         case 15:
02518             __blit_between_formats15(src, dest, source_x, source_y,
02519                                      dest_x, dest_y, width, height);
02520             return;
02521         case 16:
02522             __blit_between_formats16(src, dest, source_x, source_y,
02523                                      dest_x, dest_y, width, height);
02524             return;
02525         #endif
02526         #ifdef ALLEGRO_COLOR24
02527         case 24:
02528             __blit_between_formats24(src, dest, source_x, source_y,
02529                                      dest_x, dest_y, width, height);
02530             return;
02531         #endif
02532         #ifdef ALLEGRO_COLOR32
02533         case 32:
02534             __blit_between_formats32(src, dest, source_x, source_y,
02535                                      dest_x, dest_y, width, height);
02536             return;
02537         #endif
02538         default:
02539             TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
02540                   bitmap_color_depth(src), bitmap_color_depth(dest));
02541             return;
02542     }
02543 }
02544 
02545 
02546 
02547 static void dummy_unwrite_bank(void)
02548 {
02549 }
02550 
02551 
02552 
02553 static GFX_VTABLE allegro_gl_screen_vtable = {
02554     0,
02555     0,
02556     dummy_unwrite_bank,         //void *unwrite_bank;
02557     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
02558     allegro_gl_screen_acquire,
02559     allegro_gl_screen_release,
02560     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
02561     NULL,                       //AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent));
02562     allegro_gl_screen_getpixel,
02563     allegro_gl_screen_putpixel,
02564     allegro_gl_screen_vline,
02565     allegro_gl_screen_hline,
02566     allegro_gl_screen_hline,
02567     allegro_gl_screen_line,
02568     allegro_gl_screen_line,
02569     allegro_gl_screen_rectfill,
02570     allegro_gl_screen_triangle,
02571     allegro_gl_screen_draw_sprite,
02572     allegro_gl_screen_draw_256_sprite,
02573     allegro_gl_screen_draw_sprite_v_flip,
02574     allegro_gl_screen_draw_sprite_h_flip,
02575     allegro_gl_screen_draw_sprite_vh_flip,
02576     allegro_gl_screen_draw_trans_rgba_sprite,
02577     allegro_gl_screen_draw_trans_rgba_sprite,
02578     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
02579     allegro_gl_screen_draw_rle_sprite,
02580     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02581     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02582     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
02583     allegro_gl_screen_draw_character,
02584     allegro_gl_screen_draw_glyph,
02585     allegro_gl_screen_blit_from_memory,
02586     allegro_gl_screen_blit_to_memory,
02587     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));
02588     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));
02589     allegro_gl_screen_blit_to_self,
02590     allegro_gl_screen_blit_to_self, /* ..._forward */
02591     allegro_gl_screen_blit_to_self, /* ..._backward */
02592     allegro_gl_memory_blit_between_formats,
02593     allegro_gl_screen_masked_blit,
02594     allegro_gl_screen_clear_to_color,
02595     allegro_gl_screen_pivot_scaled_sprite_flip,
02596     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));
02597     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));
02598     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
02599     NULL,                       //AL_METHOD(void, blit_end, (void));
02600     allegro_gl_screen_polygon,
02601     allegro_gl_screen_rect,
02602     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
02603     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
02604     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02605     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02606     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
02607     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
02608     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
02609     allegro_gl_screen_polygon3d,
02610     allegro_gl_screen_polygon3d_f,
02611     allegro_gl_screen_triangle3d,
02612     allegro_gl_screen_triangle3d_f,
02613     allegro_gl_screen_quad3d,
02614     allegro_gl_screen_quad3d_f
02615 };
02616 

Generated on Tue Aug 21 22:43:39 2007 for AllegroGL by  doxygen 1.5.2