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

Generated on Sun Nov 11 15:52:55 2007 for AllegroGL by  doxygen 1.5.2