glvtable.c

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

Generated on Mon Apr 3 18:20:13 2006 for AllegroGL by  doxygen 1.4.6