Main Page | Modules | File List | Globals | Related Pages

glvtable.c

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

Generated on Wed Jun 30 23:59:52 2004 for AllegroGL by doxygen 1.3.5