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 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
01828                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01829                                   int color, int bg, int flip)
01830 {
01831     GLubyte r, g, b, a;
01832     int x_offs = 0;
01833     int i;
01834 
01835     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n");
01836     
01837     if (bmp->clip) {
01838         glPushAttrib(GL_SCISSOR_BIT);
01839         glEnable(GL_SCISSOR_TEST);
01840         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
01841                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
01842 
01843         if (x < bmp->cl) {
01844             x_offs -= x - bmp->cl;
01845             x = bmp->cl;
01846         }
01847     }
01848     if (is_sub_bitmap(bmp)) {
01849         x += bmp->x_ofs;
01850         y += bmp->y_ofs;
01851     }
01852     
01853     if (bg != -1) {
01854         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01855         glColor4ub(r, g, b, a);
01856         glRecti(x, y, x + glyph->w, y + glyph->h);              
01857     }
01858 
01859     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01860     glColor4ub(r, g, b, a);
01861     glRasterPos2i(x, y);
01862     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01863     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01864 
01865     if (flip) {
01866         for (i = 0; i < glyph->h; i++) {
01867             glBitmap(glyph->w, 1, x_offs, i, 0, 2,
01868                                          glyph->dat + i * ((glyph->w + 7) / 8));
01869         }
01870     }
01871     else {
01872         for (i = 0; i < glyph->h; i++) {
01873             glBitmap(glyph->w, 1, x_offs, i, 0, 0,
01874                                          glyph->dat + i * ((glyph->w + 7) / 8));
01875         }
01876     }
01877     
01878     if (bmp->clip) {
01879         glPopAttrib();
01880     }
01881 
01882     return;
01883 }
01884 
01885 
01886 
01887 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
01888                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01889                                   int color, int bg) {
01890     allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0);
01891 }
01892 
01893 
01894 
01895 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
01896     struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
01897 {
01898 
01899     /* Implementation note: we should try building textures and see how well
01900      * those work instead of of DrawPixels with a weird I_TO_RGBA mapping.
01901      */
01902     static GLfloat red_map[256];
01903     static GLfloat green_map[256];
01904     static GLfloat blue_map[256];
01905     static GLfloat alpha_map[256];
01906     GLubyte r, g, b, a;
01907     int i;
01908     GLint saved_row_length;
01909     GLint width, height;
01910     int sprite_x = 0, sprite_y = 0;
01911     void *data;
01912     int *table;
01913 
01914     width = sprite->w;
01915     height = sprite->h;
01916 
01917     if (bmp->clip) {
01918         if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
01919          || (y + height < bmp->ct)) {
01920             return;
01921         }
01922         if (x < bmp->cl) {
01923             width += x - bmp->cl;
01924             sprite_x -= (x - bmp->cl);
01925             x = bmp->cl;
01926         }
01927         if (y < bmp->ct) {
01928             height += y - bmp->ct;
01929             sprite_y -= (y - bmp->ct);
01930             y = bmp->ct;
01931         }
01932         if (x + width > bmp->cr) {
01933             width = bmp->cr - x;
01934         }
01935         if (y + height > bmp->cb) {
01936             height = bmp->cb - y;
01937         }
01938     }
01939     if (is_sub_bitmap(bmp)) {
01940         x += bmp->x_ofs;
01941         y += bmp->y_ofs;
01942     }
01943 
01944     data = sprite->line[sprite_y]
01945          + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
01946 
01947     if (bg < 0) {
01948         glAlphaFunc(GL_GREATER, 0.0f);
01949         glEnable(GL_ALPHA_TEST);
01950         alpha_map[0] = 0.;
01951     }
01952     else {
01953         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01954         red_map[0] = r / 255.;
01955         green_map[0] = g / 255.;
01956         blue_map[0] = b / 255.;
01957         alpha_map[0] = 1.;
01958     }
01959 
01960     if (color < 0) {
01961         table = _palette_expansion_table(bitmap_color_depth(bmp));
01962 
01963         for(i = 1; i < 255; i++) {
01964             split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
01965             red_map[i] = r / 255.;
01966             green_map[i] = g / 255.;
01967             blue_map[i] = b / 255.;
01968             alpha_map[i] = 1.;
01969         }
01970     }
01971     else {
01972         split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01973 
01974         for(i = 1; i < 255; i++) {
01975             red_map[i] = r / 255.;
01976             green_map[i] = g / 255.;
01977             blue_map[i] = b / 255.;
01978             alpha_map[i] = 1.;
01979         }
01980     }
01981     
01982     glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
01983     glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
01984     glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
01985     glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
01986     
01987     glRasterPos2i(x, y);
01988     glPushAttrib(GL_PIXEL_MODE_BIT);
01989     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01990     
01991     glPixelZoom(1.0, flip ? -1.0 : 1.0);
01992     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01993     glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
01994     glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
01995 
01996     glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
01997     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01998     glPopAttrib();
01999     if (bg < 0) {
02000         glDisable(GL_ALPHA_TEST);
02001     }
02002 
02003     return;
02004 }
02005 
02006 
02007 
02008 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
02009     struct BITMAP *sprite, int x, int y, int color, int bg) {
02010     allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1);
02011 }
02012 
02013 
02014 
02015 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
02016                          struct BITMAP *sprite, int x, int y, int color, int bg)
02017 {
02018     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
02019     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
02020 }
02021 
02022 
02023 
02024 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
02025                                             struct BITMAP *sprite, int x, int y)
02026 {
02027     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
02028     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1);
02029 }
02030 
02031 
02032 
02033 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
02034 {
02035     if (__agl_drawing_pattern_tex || bmp->clip) {
02036         allegro_gl_screen_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
02037     }
02038     else {
02039         GLubyte r, g, b, a;
02040         GLfloat old_col[4];
02041     
02042         split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02043         
02044         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
02045         glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
02046                      ((float) a / 255));
02047 
02048         glClear(GL_COLOR_BUFFER_BIT);
02049         glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
02050     }
02051 
02052     return;
02053 }
02054 
02055 
02056 
02057 /* TODO: Handle concave and self-intersecting. */
02058 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
02059                                       AL_CONST int *points, int color) {
02060     GLubyte r, g, b, a;
02061     int i;
02062 
02063     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02064     glColor4ub(r, g, b, a);
02065     
02066     glPushAttrib(GL_SCISSOR_BIT);
02067 
02068     if (bmp->clip) {
02069         glEnable(GL_SCISSOR_TEST);
02070         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02071                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02072     }
02073     else {
02074         glScissor(0, 0, bmp->w, bmp->h);
02075     }
02076 
02077     glBegin(GL_POLYGON);
02078         for (i = 0; i < vertices*2-1; i+=2) {
02079             SET_TEX_COORDS(points[i], points[i+1]);
02080             if (is_sub_bitmap(bmp)) {
02081                 glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
02082             }
02083             else {
02084                 glVertex2f(points[i], points[i+1]);
02085             }
02086         }
02087     glEnd();
02088 
02089     glPopAttrib();
02090 }
02091 
02092 
02093 
02094 static void allegro_gl_screen_rect(struct BITMAP *bmp,
02095                                    int x1, int y1, int x2, int y2, int color) {
02096     GLubyte r, g, b, a;
02097 
02098     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02099     glColor4ub(r, g, b, a);
02100     
02101     glPushAttrib(GL_SCISSOR_BIT);
02102 
02103     if (bmp->clip) {
02104         glEnable(GL_SCISSOR_TEST);
02105         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02106                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02107     }
02108     else {
02109         glScissor(0, 0, bmp->w, bmp->h);
02110     }
02111     if (is_sub_bitmap(bmp)) {
02112         x1 += bmp->x_ofs;
02113         x2 += bmp->x_ofs;
02114         y1 += bmp->y_ofs;
02115         y2 += bmp->y_ofs;
02116     }
02117 
02118     glBegin(GL_LINE_STRIP);
02119         glVertex2f(x1, y1);
02120         glVertex2f(x2, y1);
02121         glVertex2f(x2, y2);
02122         glVertex2f(x1, y2);
02123         glVertex2f(x1, y1);
02124     glEnd();
02125 
02126     glPopAttrib();
02127 }
02128 
02129 
02130 
02131 void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
02132                                    struct BITMAP *texture, int vc,
02133                                    V3D_f *vtx[]) {
02134     int i;
02135     int use_z = FALSE;
02136 
02137     if (type & POLYTYPE_ZBUF) {
02138         use_z = TRUE;
02139         type &= ~POLYTYPE_ZBUF;
02140     }
02141 
02142     if (type == POLYTYPE_PTEX || type == POLYTYPE_PTEX_TRANS)
02143         use_z = TRUE;
02144 
02145     if (bmp->clip) {
02146         glPushAttrib(GL_SCISSOR_BIT);
02147         glEnable(GL_SCISSOR_TEST);
02148         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02149                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02150     }
02151     if (is_sub_bitmap(bmp)) {
02152         for (i = 0; i < vc*2-1; i+=2) {
02153             vtx[i] += bmp->x_ofs;
02154             vtx[i+1] += bmp->y_ofs;
02155         }
02156     }
02157 
02158     if (use_z) {
02159         glEnable(GL_DEPTH_TEST);
02160         glDepthFunc(GL_LESS);
02161         glDepthMask(GL_TRUE);
02162     }
02163 
02164     glColor4ub(255, 255, 255, 255);
02165 
02166     if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02167      || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02168         drawing_mode(DRAW_MODE_COPY_PATTERN, texture, 0, 0);
02169     }
02170 
02171     if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02172         glEnable(GL_BLEND);
02173     }
02174 
02175     glBegin(GL_POLYGON);
02176         for (i = 0; i < vc; i++) {
02177             if (type == POLYTYPE_FLAT)
02178                 glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
02179             else if (type == POLYTYPE_GRGB)
02180                 glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
02181             else if (type == POLYTYPE_GCOL)
02182                 glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
02183             else if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02184                   || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02185                     SET_TEX_COORDS(vtx[i]->u, vtx[i]->v);
02186             }
02187 
02188             if (use_z)
02189                 glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
02190             else
02191                 glVertex2f(vtx[i]->x, vtx[i]->y);
02192         }
02193     glEnd();
02194 
02195     if (bmp->clip)
02196         glPopAttrib();
02197 
02198     if (use_z) {
02199         glDisable(GL_DEPTH_TEST);
02200         glDepthMask(GL_FALSE);
02201     }
02202 
02203     if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02204      || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02205         solid_mode();
02206     }
02207 
02208     if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS)
02209         glDisable(GL_BLEND);
02210 }
02211 
02212 
02213 
02214 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
02215                                         struct BITMAP *texture, int vc,
02216                                         V3D *vtx[]) {
02217     int i;
02218     V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
02219     if (!vtx_f)
02220         return;
02221 
02222     for (i = 0; i < vc; i++) {
02223         vtx_f[i] = malloc(sizeof(struct V3D_f));
02224         if (!vtx_f[i]) {
02225             int k;
02226             for (k = 0; k < i; k++)
02227                 free(vtx_f[k]);
02228             free(vtx_f);
02229             return;
02230         }
02231         vtx_f[i]->c = vtx[i]->c;
02232         vtx_f[i]->u = fixtof(vtx[i]->u);
02233         vtx_f[i]->v = fixtof(vtx[i]->v);
02234         vtx_f[i]->x = fixtof(vtx[i]->x);
02235         vtx_f[i]->y = fixtof(vtx[i]->y);
02236         vtx_f[i]->z = fixtof(vtx[i]->z);
02237     }
02238 
02239     allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
02240     for (i = 0; i < vc; i++)
02241         free(vtx_f[i]);
02242     free(vtx_f);
02243 }
02244 
02245 
02246 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
02247                                        struct BITMAP *texture,
02248                                        V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
02249 
02250     V3D_f *vtx_f[4];
02251     vtx_f[0] = v1;
02252     vtx_f[1] = v2;
02253     vtx_f[2] = v3;
02254     vtx_f[3] = v4;
02255 
02256     allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
02257 }
02258 
02259 
02260 
02261 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
02262             struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
02263 
02264     V3D *vtx[4];
02265     vtx[0] = v1;
02266     vtx[1] = v2;
02267     vtx[2] = v3;
02268     vtx[3] = v4;
02269 
02270     allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
02271 }
02272 
02273 
02274 
02275 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
02276                                          struct BITMAP *texture,
02277                                          V3D *v1, V3D *v2, V3D *v3) {
02278     V3D *vtx[3];
02279     vtx[0] = v1;
02280     vtx[1] = v2;
02281     vtx[2] = v3;
02282 
02283     allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
02284 }
02285 
02286 
02287 
02288 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
02289                                            struct BITMAP *texture,
02290                                            V3D_f *v1, V3D_f *v2, V3D_f *v3) {
02291     V3D_f *vtx_f[3];
02292     vtx_f[0] = v1;
02293     vtx_f[1] = v2;
02294     vtx_f[2] = v3;
02295 
02296     allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
02297 }
02298 
02299 
02300 
02301 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
02302 {
02303     int maskcolor = (*vtable)->mask_color;
02304     int depth = (*vtable)->color_depth;
02305 
02306     AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
02307     allegro_gl_screen_vtable.color_depth = depth;
02308     /* makecol_depth is used below instead of the MASK_COLOR_x constants
02309      * because we may have changed the RGB shift values in order to
02310      * use the packed pixels extension
02311      */
02312     allegro_gl_screen_vtable.mask_color =
02313         makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
02314     
02315     *vtable = &allegro_gl_screen_vtable;
02316 
02317     __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
02318     if (allegro_gl_extensions_GL.NV_register_combiners) {
02319         __allegro_gl_driver->screen_masked_blit
02320                                                = screen_masked_blit_nv_register;
02321     }
02322     else if (allegro_gl_info.num_texture_units >= 3) {
02323         __allegro_gl_driver->screen_masked_blit =
02324                                                  screen_masked_blit_combine_tex;
02325     }
02326 }
02327 
02328 
02329 
02330 /* Saved projection matrix */
02331 static double allegro_gl_projection_matrix[16];
02332 static double allegro_gl_modelview_matrix[16];
02333 
02334 
02335 
02366 void allegro_gl_set_allegro_mode(void)
02367 {
02368     AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
02369 
02370     /* Save the OpenGL state  then set it up */
02371     glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
02372                | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02373     glDisable(GL_DEPTH_TEST);
02374     glDisable(GL_CULL_FACE);
02375     glDisable(GL_FOG);
02376     glDisable(GL_LIGHTING);
02377     glDisable(GL_BLEND);
02378     glDisable(GL_ALPHA_TEST);
02379     glDepthMask(GL_FALSE);
02380     glEnable(GL_TEXTURE_2D);
02381     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02382     glPointSize(1.);
02383 
02384     /* Create pool texture */
02385     if (!__allegro_gl_pool_texture) {
02386         glGenTextures(1, &__allegro_gl_pool_texture);
02387     }
02388 
02389     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
02390         /* Create a texture without defining the data */
02391     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
02392                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
02393     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02394     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02395 
02396     glBindTexture(GL_TEXTURE_2D, 0);
02397     allegro_gl_set_projection();
02398 
02399     /* For some reason, ATI Rage Pro isn't able to draw correctly without a
02400      * texture bound. So we bind a dummy 1x1 texture to work around the issue.
02401      */
02402     if (allegro_gl_info.is_ati_rage_pro) {
02403         if (!__allegro_gl_dummy_texture) {
02404             GLubyte tex[4] = {255, 255, 255, 255};
02405             glGenTextures(1, &__allegro_gl_dummy_texture);
02406             glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02407             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
02408                          GL_RGBA, GL_UNSIGNED_BYTE, tex);
02409         }
02410         glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02411     }
02412 #ifdef ALLEGRO_MACOSX
02413     /* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in
02414      *'blit'). This stops it happening.
02415      */
02416     glBegin(GL_POINTS);
02417     glEnd();
02418 #endif
02419 }
02420 
02421 
02422 
02435 void allegro_gl_unset_allegro_mode(void)
02436 {
02437     AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
02438 
02439     switch(allegro_gl_display_info.vidmem_policy) {
02440         case AGL_KEEP:
02441             break;
02442         case AGL_RELEASE:
02443             if (__allegro_gl_pool_texture) {
02444                 glDeleteTextures(1, &__allegro_gl_pool_texture);
02445                 __allegro_gl_pool_texture = 0;
02446             }
02447             break;
02448     }
02449     allegro_gl_unset_projection();
02450     glPopAttrib();
02451 }
02452 
02453 
02454 
02484 void allegro_gl_set_projection(void)
02485 {
02486     GLint v[4];
02487     AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
02488     
02489     /* Setup OpenGL matrices */
02490     glGetIntegerv(GL_VIEWPORT, &v[0]);
02491     glMatrixMode(GL_MODELVIEW);
02492     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
02493     glLoadIdentity();
02494     glMatrixMode(GL_PROJECTION);
02495     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
02496     glLoadIdentity();
02497     gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
02498 }
02499 
02500 
02501 
02511 void allegro_gl_unset_projection(void)
02512 {
02513     AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
02514     glMatrixMode(GL_PROJECTION);
02515     glLoadMatrixd(allegro_gl_projection_matrix);
02516     glMatrixMode(GL_MODELVIEW);
02517     glLoadMatrixd(allegro_gl_modelview_matrix);
02518 }
02519 
02520 
02521 
02522 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
02523     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
02524     int width, int height)
02525 {
02526     AGL_LOG(2, "AGL::blit_between_formats\n");
02527 
02528     /* screen -> memory */
02529     if (is_screen_bitmap(src)) {
02530         allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
02531                                          dest_x, dest_y, width, height);
02532         return;
02533     }
02534 
02535     /* video -> memory */
02536     if (is_video_bitmap(src)) {
02537         allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
02538                                         dest_x, dest_y, width, height);
02539         return;
02540     }
02541     
02542     /* memory -> screen */
02543     if (is_screen_bitmap(dest)) {
02544         allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
02545                                            dest_x, dest_y, width, height);
02546         return;
02547     }
02548 
02549     /* memory -> video */
02550     if (is_video_bitmap(dest)) {
02551         allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
02552                                           dest_x, dest_y, width, height);
02553         return;
02554     }
02555 
02556     switch(bitmap_color_depth(dest)) {
02557         #ifdef ALLEGRO_COLOR8
02558         case 8:
02559             __blit_between_formats8(src, dest, source_x, source_y,
02560                                     dest_x, dest_y, width, height);
02561             return;
02562         #endif
02563         #ifdef ALLEGRO_COLOR16
02564         case 15:
02565             __blit_between_formats15(src, dest, source_x, source_y,
02566                                      dest_x, dest_y, width, height);
02567             return;
02568         case 16:
02569             __blit_between_formats16(src, dest, source_x, source_y,
02570                                      dest_x, dest_y, width, height);
02571             return;
02572         #endif
02573         #ifdef ALLEGRO_COLOR24
02574         case 24:
02575             __blit_between_formats24(src, dest, source_x, source_y,
02576                                      dest_x, dest_y, width, height);
02577             return;
02578         #endif
02579         #ifdef ALLEGRO_COLOR32
02580         case 32:
02581             __blit_between_formats32(src, dest, source_x, source_y,
02582                                      dest_x, dest_y, width, height);
02583             return;
02584         #endif
02585         default:
02586             TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
02587                   bitmap_color_depth(src), bitmap_color_depth(dest));
02588             return;
02589     }
02590 }
02591 
02592 
02593 
02594 static void dummy_unwrite_bank(void)
02595 {
02596 }
02597 
02598 
02599 
02600 static GFX_VTABLE allegro_gl_screen_vtable = {
02601     0,
02602     0,
02603     dummy_unwrite_bank,         //void *unwrite_bank;
02604     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
02605     allegro_gl_screen_acquire,
02606     allegro_gl_screen_release,
02607     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
02608     NULL,                       //AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent));
02609     allegro_gl_screen_getpixel,
02610     allegro_gl_screen_putpixel,
02611     allegro_gl_screen_vline,
02612     allegro_gl_screen_hline,
02613     allegro_gl_screen_hline,
02614     allegro_gl_screen_line,
02615     allegro_gl_screen_line,
02616     allegro_gl_screen_rectfill,
02617     allegro_gl_screen_triangle,
02618     allegro_gl_screen_draw_sprite,
02619     allegro_gl_screen_draw_256_sprite,
02620     allegro_gl_screen_draw_sprite_v_flip,
02621     allegro_gl_screen_draw_sprite_h_flip,
02622     allegro_gl_screen_draw_sprite_vh_flip,
02623     allegro_gl_screen_draw_trans_rgba_sprite,
02624     allegro_gl_screen_draw_trans_rgba_sprite,
02625     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
02626     allegro_gl_screen_draw_rle_sprite,
02627     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02628     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02629     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
02630     allegro_gl_screen_draw_character,
02631     allegro_gl_screen_draw_glyph,
02632     allegro_gl_screen_blit_from_memory,
02633     allegro_gl_screen_blit_to_memory,
02634     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));
02635     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));
02636     allegro_gl_screen_blit_to_self,
02637     allegro_gl_screen_blit_to_self, /* ..._forward */
02638     allegro_gl_screen_blit_to_self, /* ..._backward */
02639     allegro_gl_memory_blit_between_formats,
02640     allegro_gl_screen_masked_blit,
02641     allegro_gl_screen_clear_to_color,
02642     allegro_gl_screen_pivot_scaled_sprite_flip,
02643     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));
02644     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));
02645     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
02646     NULL,                       //AL_METHOD(void, blit_end, (void));
02647     allegro_gl_screen_polygon,
02648     allegro_gl_screen_rect,
02649     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
02650     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
02651     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02652     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02653     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
02654     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
02655     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
02656     allegro_gl_screen_polygon3d,
02657     allegro_gl_screen_polygon3d_f,
02658     allegro_gl_screen_triangle3d,
02659     allegro_gl_screen_triangle3d_f,
02660     allegro_gl_screen_quad3d,
02661     allegro_gl_screen_quad3d_f
02662 };
02663 

Generated on Mon Nov 12 11:05:31 2007 for AllegroGL by  doxygen 1.5.2