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

Generated on Sun Dec 3 18:06:49 2006 for AllegroGL by  doxygen 1.5.1