AllegroGL: glvtable.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

# glvtable.c

Go to the documentation of this file.

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