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

Generated on Tue May 15 16:27:15 2007 for AllegroGL by  doxygen 1.4.7