AllegroGL: glvtable.c Source File

- Main Page
- Related Pages
- Modules
- Files

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