AllegroGL 0.4.4

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