- Main Page
- Related Pages
- Modules
- Files

- File List
- Globals

# videovtb.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  */
    00009 #include <string.h>
    00010 #include <limits.h>
    00011
    00012 #include <allegro.h>
    00013
    00014 #ifdef ALLEGRO_WINDOWS
    00015 #include <winalleg.h>
    00016 #endif
    00017
    00018 #include "alleggl.h"
    00019 #include "allglint.h"
    00020 #include "glvtable.h"
    00021 #include <allegro/internal/aintern.h>
    00022 #ifdef ALLEGRO_MACOSX
    00023 #include <OpenGL/glu.h>
    00024 #else
    00025 #include <GL/glu.h>
    00026 #endif
    00027
    00028
    00029 #define MASKED_BLIT 1
    00030 #define BLIT        2
    00031 #define TRANS       3
    00032
    00033
    00034 static GFX_VTABLE allegro_gl_video_vtable;
    00035
    00036 /* Counter for video bitmaps. screen = 1 */
    00037 static int video_bitmap_count = 2;
    00038
    00039 static int __allegro_gl_video_bitmap_bpp = -1;
    00040
    00041 extern BITMAP *__agl_drawing_pattern_bmp;
    00042 BITMAP *old_pattern = NULL;
    00043
    00044 void allegro_gl_destroy_video_bitmap(BITMAP *bmp);
    00045
    00046
    00047
    00048 static int allegro_gl_make_video_bitmap_helper1(int w, int h, int x, int y,
    00049                                    GLint target, AGL_VIDEO_BITMAP **pvid) {
    00050
    00051     int internal_format;
    00052     int bpp;
    00053
    00054     if (__allegro_gl_video_bitmap_bpp == -1) {
    00055         bpp = bitmap_color_depth(screen);
    00056     }
    00057     else {
    00058         bpp = __allegro_gl_video_bitmap_bpp;
    00059     }
    00060
    00061     (*pvid) = malloc(sizeof(AGL_VIDEO_BITMAP));
    00062
    00063     if (!(*pvid))
    00064         return -1;
    00065
    00066     memset(*pvid, 0, sizeof(AGL_VIDEO_BITMAP));
    00067
    00068     /* Create associated bitmap */
    00069     (*pvid)->memory_copy = create_bitmap_ex(bpp, w, h);
    00070     if (!(*pvid)->memory_copy)
    00071         return -1;
    00072
    00073     (*pvid)->format = __allegro_gl_get_bitmap_color_format((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
    00074     (*pvid)->type = __allegro_gl_get_bitmap_type((*pvid)->memory_copy, 0);
    00075     internal_format = __allegro_gl_get_texture_format_ex((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
    00076
    00077     (*pvid)->target = target;
    00078
    00079     /* Fill in some values in the bitmap to make it act as a subbitmap
    00080      */
    00081     (*pvid)->width  = w;
    00082     (*pvid)->height = h;
    00083     (*pvid)->x_ofs = x;
    00084     (*pvid)->y_ofs = y;
    00085
    00086     /* Make a texture out of it */
    00087     glGenTextures(1, &((*pvid)->tex));
    00088     if (!((*pvid)->tex))
    00089         return -1;
    00090
    00091     glEnable((*pvid)->target);
    00092     glBindTexture((*pvid)->target, ((*pvid)->tex));
    00093
    00094     glTexImage2D((*pvid)->target, 0, internal_format, w, h,
    00095                  0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    00096
    00097     /* By default, use the Allegro filtering mode - ie: Nearest */
    00098     glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    00099     glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    00100
    00101     /* <mmimica>
    00102        Clamping removed because we want video bitmaps that are set for
    00103        patterned drawing to be GL_REPEAT (default wrapping mode). Doesn't
    00104        seem to break anything.
    00105     */
    00106 #if 0
    00107     /* Clamp to edge */
    00108     {
    00109         GLenum clamp = GL_CLAMP_TO_EDGE;
    00110         if (!allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
    00111             clamp = GL_CLAMP;
    00112         }
    00113         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_S, clamp);
    00114         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_T, clamp);
    00115     }
    00116 #endif
    00117
    00118     glDisable((*pvid)->target);
    00119
    00120     if (allegro_gl_extensions_GL.EXT_framebuffer_object) {
    00121         glGenFramebuffersEXT(1, &((*pvid)->fbo));
    00122         if (!(*pvid)->fbo) {
    00123             glDeleteTextures(1, &((*pvid)->tex));
    00124             return -1;
    00125         }
    00126
    00127         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (*pvid)->fbo);
    00128         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, (*pvid)->target, (*pvid)->tex, 0);
    00129         if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
    00130             /* Some FBO implementation limitation was hit, will use normal textures. */
    00131             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    00132             glDeleteFramebuffersEXT(1, &((*pvid)->fbo));
    00133             (*pvid)->fbo = 0;
    00134             return 0;
    00135         }
    00136
    00137         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    00138     }
    00139     else {
    00140         (*pvid)->fbo = 0;
    00141     }
    00142
    00143     return 0;
    00144 }
    00145
    00146
    00147
    00148 static int allegro_gl_make_video_bitmap_helper0(int w, int h, int x, int y,
    00149                                                 AGL_VIDEO_BITMAP **pvid) {
    00150
    00151     int is_power_of_2 = (!(w & (w - 1)) && !(h & (h - 1)));
    00152     int texture_rect_available = allegro_gl_extensions_GL.ARB_texture_rectangle
    00153 #ifdef ALLEGRO_MACOSX
    00154                              || allegro_gl_extensions_GL.EXT_texture_rectangle
    00155 #endif
    00156                              || allegro_gl_extensions_GL.NV_texture_rectangle;
    00157     GLint max_rect_texture_size = 0;
    00158
    00159     if (texture_rect_available) {
    00160         glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_rect_texture_size);
    00161     }
    00162
    00163     if (w <= allegro_gl_info.max_texture_size &&
    00164         h <= allegro_gl_info.max_texture_size) {
    00165         if (allegro_gl_extensions_GL.ARB_texture_non_power_of_two ||
    00166             is_power_of_2) {
    00167             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
    00168                                             GL_TEXTURE_2D, pvid)) {
    00169                 return -1;
    00170             }
    00171         }
    00172         else if (texture_rect_available &&
    00173                  w <= max_rect_texture_size &&
    00174                  h <= max_rect_texture_size) {
    00175             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
    00176                                             GL_TEXTURE_RECTANGLE_ARB, pvid)) {
    00177                 return -1;
    00178             }
    00179         }
    00180         else {
    00181             /* NPO2 textures are not suppored by the driver in any way.
    00182              * Split the bitmap into smaller POT bitmaps. */
    00183             const unsigned int BITS = sizeof(int) * CHAR_BIT;
    00184             unsigned int i, j;
    00185             unsigned int w1, h1;
    00186             unsigned int x1, y1;
    00187             unsigned int p1, p2;
    00188
    00189             /* Find the POTs using bits. */
    00190             y1 = 0;
    00191             for (i = 0; i < BITS; i++) {
    00192                 p1 = 1 << i;
    00193                 if (h & p1)
    00194                     h1 = p1;
    00195                 else
    00196                     continue;
    00197
    00198                 x1 = 0;
    00199                 for (j = 0; j < BITS; j++) {
    00200                     p2 = 1 << j;
    00201                     if (w & p2)
    00202                         w1 = p2;
    00203                     else
    00204                         continue;
    00205
    00206                     if (allegro_gl_make_video_bitmap_helper0(w1, h1, x + x1,
    00207                                                         y + y1, pvid)) {
    00208                         return -1;
    00209                     }
    00210                     do {
    00211                         pvid = &((*pvid)->next);
    00212                     } while (*pvid);
    00213
    00214                     x1 += w1;
    00215                 }
    00216
    00217                 y1 += h1;
    00218             }
    00219         }
    00220     }
    00221     else {
    00222         /* Texture is too big to fit. Split it in 4 and try again. */
    00223         int w1, w2, h1, h2;
    00224
    00225         w2 = w / 2;
    00226         w1 = w - w2;
    00227
    00228         h2 = h / 2;
    00229         h1 = h - h2;
    00230
    00231         /* Even a 1x1 texture didn't work? Bail*/
    00232         if (!w2 && !h2) {
    00233             return -1;
    00234         }
    00235
    00236         /* Top-left corner */
    00237         if (allegro_gl_make_video_bitmap_helper0(w1, h1, x, y, pvid)) {
    00238             return -1;
    00239         }
    00240         do {
    00241             pvid = &((*pvid)->next);
    00242         } while (*pvid);
    00243
    00244         /* Top-right corner */
    00245         if (w2) {
    00246             if (allegro_gl_make_video_bitmap_helper0(w2, h1, x + w1, y, pvid)) {
    00247                 return -1;
    00248             }
    00249             do {
    00250                 pvid = &((*pvid)->next);
    00251             } while (*pvid);
    00252         }
    00253         /* Bottom-left corner */
    00254         if (h2) {
    00255             if (allegro_gl_make_video_bitmap_helper0(w1, h2, x, y + h1, pvid)) {
    00256                 return -1;
    00257             }
    00258             do {
    00259                 pvid = &((*pvid)->next);
    00260             } while (*pvid);
    00261         }
    00262         /* Bottom-right corner */
    00263         if (w2 && h2) {
    00264             if (allegro_gl_make_video_bitmap_helper0(w2, h2, x + w1, y + h1, pvid)) {
    00265                 return -1;
    00266             }
    00267             do {
    00268                 pvid = &((*pvid)->next);
    00269             } while (*pvid);
    00270         }
    00271     }
    00272
    00273     return 0;
    00274 }
    00275
    00276
    00277
    00278 /* Will make a (potentially piece-wise) texture out of the specified bitmap
    00279  * Source -must- be a memory bitmap or memory subbitmap (created by Allegro
    00280  * only).
    00281  *
    00282  */
    00283 static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) {
    00284
    00285     /* Grab a pointer to the bitmap data to patch */
    00286     void *ptr = &bmp->extra;
    00287     AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)ptr;
    00288
    00289     /* Convert bitmap to texture */
    00290     if (allegro_gl_make_video_bitmap_helper0(bmp->w, bmp->h, 0, 0, pvid)) {
    00291         goto agl_error;
    00292     }
    00293
    00294     return bmp;
    00295
    00296 agl_error:
    00297     allegro_gl_destroy_video_bitmap(bmp);
    00298     return NULL;
    00299 }
    00300
    00301
    00302
    00303 /* void allegro_gl_destroy_video_bitmap(BITMAP *bmp) */
    00308 void allegro_gl_destroy_video_bitmap(BITMAP *bmp) {
    00309
    00310     AGL_VIDEO_BITMAP *vid = bmp ? bmp->extra : NULL, *next;
    00311
    00312     if (!bmp)
    00313         return;
    00314
    00315     while (vid) {
    00316         if (vid->memory_copy)
    00317             destroy_bitmap(vid->memory_copy);
    00318
    00319         if (vid->tex)
    00320             glDeleteTextures(1, &vid->tex);
    00321
    00322         if (vid->fbo)
    00323             glDeleteFramebuffersEXT(1, &vid->fbo);
    00324
    00325         next = vid->next;
    00326         free(vid);
    00327         vid = next;
    00328     }
    00329
    00330     free(bmp->vtable);
    00331     free(bmp);
    00332
    00333     return;
    00334 }
    00335
    00336
    00337
    00338 /* BITMAP *allegro_gl_create_video_bitmap(int w, int h) */
    00344 BITMAP *allegro_gl_create_video_bitmap(int w, int h) {
    00345     GFX_VTABLE *vtable;
    00346     BITMAP *bitmap;
    00347
    00348     bitmap = malloc(sizeof(BITMAP) + sizeof(char *));
    00349
    00350     if (!bitmap)
    00351         return NULL;
    00352
    00353     bitmap->dat = NULL;
    00354     bitmap->w = bitmap->cr = w;
    00355     bitmap->h = bitmap->cb = h;
    00356     bitmap->clip = TRUE;
    00357     bitmap->cl = bitmap->ct = 0;
    00358     bitmap->write_bank = bitmap->read_bank = NULL;
    00359     /* We should keep tracks of allocated bitmaps for the ref counter */
    00360     bitmap->id = BMP_ID_VIDEO | video_bitmap_count;
    00361     bitmap->extra = NULL;
    00362     bitmap->x_ofs = 0;
    00363     bitmap->y_ofs = 0;
    00364     bitmap->seg = _default_ds();
    00365     bitmap->line[0] = NULL;
    00366     bitmap->vtable = NULL;
    00367
    00368     if (!allegro_gl_make_video_bitmap(bitmap)) {
    00369         return NULL;
    00370     }
    00371     video_bitmap_count++;
    00372
    00373     /* XXX <rohannessian> We ought to leave the Allegro values intact
    00374      * Avoids bad interaction with correct Allegro programs.
    00375      */
    00376     vtable = malloc(sizeof(struct GFX_VTABLE));
    00377     *vtable = allegro_gl_video_vtable;
    00378     if (__allegro_gl_video_bitmap_bpp == -1) {
    00379         vtable->color_depth = bitmap_color_depth(screen);
    00380     }
    00381     else {
    00382         vtable->color_depth = __allegro_gl_video_bitmap_bpp;
    00383     }
    00384     switch (vtable->color_depth) {
    00385         case 8:
    00386             vtable->mask_color = MASK_COLOR_8;
    00387         break;
    00388         case 15:
    00389             vtable->mask_color = MASK_COLOR_15;
    00390         break;
    00391         case 16:
    00392             vtable->mask_color = MASK_COLOR_16;
    00393         break;
    00394         case 24:
    00395             vtable->mask_color = MASK_COLOR_24;
    00396         break;
    00397         case 32:
    00398             vtable->mask_color = MASK_COLOR_32;
    00399         break;
    00400     }
    00401     bitmap->vtable = vtable;
    00402
    00403     return bitmap;
    00404 }
    00405
    00406
    00407
    00408 /* allegro_gl_set_video_bitmap_color_depth(int bpp) */
    00423 GLint allegro_gl_set_video_bitmap_color_depth(int bpp) {
    00424     GLint old_val = __allegro_gl_video_bitmap_bpp;
    00425     __allegro_gl_video_bitmap_bpp = bpp;
    00426     return old_val;
    00427 }
    00428
    00429
    00430 /* static void allegro_gl_video_acquire(struct BITMAP *bmp) */
    00437 static void allegro_gl_video_acquire(struct BITMAP *bmp) {}
    00438
    00439
    00440
    00441 /* static void allegro_gl_video_release(struct BITMAP *bmp) */
    00448 static void allegro_gl_video_release(struct BITMAP *bmp) {}
    00449
    00450
    00451
    00452 static void set_drawing_pattern(void)
    00453 {
    00454     if (_drawing_pattern && !is_memory_bitmap(_drawing_pattern)) {
    00455         old_pattern = _drawing_pattern;
    00456         drawing_mode(_drawing_mode, __agl_drawing_pattern_bmp,
    00457                      _drawing_x_anchor, _drawing_y_anchor);
    00458     }
    00459 }
    00460
    00461
    00462
    00463 static void unset_drawing_pattern(void)
    00464 {
    00465     if (old_pattern) {
    00466         drawing_mode(_drawing_mode, old_pattern,
    00467                      _drawing_x_anchor, _drawing_y_anchor);
    00468         old_pattern = NULL;
    00469     }
    00470 }
    00471
    00472
    00473
    00474 static int allegro_gl_video_getpixel(struct BITMAP *bmp, int x, int y)
    00475 {
    00476     int pix = -1;
    00477     AGL_VIDEO_BITMAP *vid;
    00478     AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
    00479
    00480     if (is_sub_bitmap(bmp)) {
    00481         x += bmp->x_ofs;
    00482         y += bmp->y_ofs;
    00483     }
    00484     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
    00485         return -1;
    00486     }
    00487
    00488     vid = bmp->extra;
    00489
    00490     while (vid) {
    00491         if (vid->x_ofs <= x && vid->y_ofs <= y
    00492          && vid->x_ofs + vid->memory_copy->w > x
    00493          && vid->y_ofs + vid->memory_copy->h > y) {
    00494
    00495             pix = getpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs);
    00496             break;
    00497         }
    00498         vid = vid->next;
    00499     }
    00500
    00501     if (pix != -1) {
    00502         return pix;
    00503     }
    00504
    00505     return -1;
    00506 }
    00507
    00508
    00509
    00510 static void update_texture_memory(AGL_VIDEO_BITMAP *vid, int x1, int y1,
    00511                                   int x2, int y2) {
    00512     GLint saved_row_length;
    00513     GLint saved_alignment;
    00514     GLint type;
    00515     GLint format;
    00516     int bpp;
    00517     BITMAP *temp = NULL;
    00518     BITMAP *vbmp = vid->memory_copy;;
    00519
    00520     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
    00521     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
    00522
    00523     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
    00524     format = vid->format;
    00525     type = vid->type;
    00526
    00527     glColor4ub(255, 255, 255, 255);
    00528
    00529     /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
    00530      * the bitmap into something GL can understand - 24-bpp should do it.
    00531      */
    00532     if (!allegro_gl_extensions_GL.EXT_packed_pixels
    00533                                           && bitmap_color_depth(vbmp) < 24) {
    00534         temp = create_bitmap_ex(24, vbmp->w, vbmp->h);
    00535         if (!temp)
    00536             return;
    00537
    00538         blit(vbmp, temp, 0, 0, 0, 0, temp->w, temp->h);
    00539         vbmp = temp;
    00540         bpp = BYTES_PER_PIXEL(bitmap_color_depth(vbmp));
    00541         format = __allegro_gl_get_bitmap_color_format(vbmp, 0);
    00542         type = __allegro_gl_get_bitmap_type(vbmp, 0);
    00543     }
    00544
    00545     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    00546     glPixelStorei(GL_UNPACK_ROW_LENGTH,
    00547                   vbmp->h > 1
    00548                  ? (vbmp->line[1] - vbmp->line[0]) / bpp
    00549                  : vbmp->w);
    00550
    00551     glEnable(vid->target);
    00552     glBindTexture(vid->target, vid->tex);
    00553     glTexSubImage2D(vid->target, 0,
    00554         x1, y1, x2 - x1 + 1, y2 - y1 + 1, format,
    00555         type, vbmp->line[y1] + x1 * bpp);
    00556     glBindTexture(vid->target, 0);
    00557     glDisable(vid->target);
    00558
    00559     if (temp)
    00560         destroy_bitmap(temp);
    00561
    00562     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
    00563     glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment);
    00564 }
    00565
    00566
    00567
    00568 static void allegro_gl_video_putpixel(struct BITMAP *bmp, int x, int y,
    00569                                       int color) {
    00570     AGL_VIDEO_BITMAP *vid;
    00571
    00572     if (is_sub_bitmap(bmp)) {
    00573         x += bmp->x_ofs;
    00574         y += bmp->y_ofs;
    00575     }
    00576     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
    00577         return;
    00578     }
    00579
    00580     vid = bmp->extra;
    00581
    00582     while (vid) {
    00583         if (vid->x_ofs <= x && vid->y_ofs <= y
    00584          && vid->x_ofs + vid->memory_copy->w > x
    00585          && vid->y_ofs + vid->memory_copy->h > y) {
    00586
    00587             set_drawing_pattern();
    00588             putpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs, color);
    00589             unset_drawing_pattern();
    00590             update_texture_memory(vid, x - vid->x_ofs, y - vid->y_ofs, x - vid->x_ofs, y - vid->y_ofs);
    00591             break;
    00592         }
    00593         vid = vid->next;
    00594     }
    00595
    00596     return;
    00597 }
    00598
    00599
    00600
    00601 static void allegro_gl_video_vline(BITMAP *bmp, int x, int y1, int y2,
    00602                                    int color) {
    00603
    00604     AGL_VIDEO_BITMAP *vid;
    00605
    00606     AGL_LOG(2, "glvtable.c:allegro_gl_video_vline\n");
    00607     vid = bmp->extra;
    00608
    00609     if (is_sub_bitmap(bmp)) {
    00610         x  += bmp->x_ofs;
    00611         y1 += bmp->y_ofs;
    00612         y2 += bmp->y_ofs;
    00613     }
    00614     if (x < bmp->cl || x >= bmp->cr) {
    00615         return;
    00616     }
    00617
    00618     if (y1 > y2) {
    00619         int temp = y1;
    00620         y1 = y2;
    00621         y2 = temp;
    00622     }
    00623
    00624     if (y1 < bmp->ct) {
    00625         y1 = bmp->ct;
    00626     }
    00627     if (y2 >= bmp->cb) {
    00628         y2 = bmp->cb - 1;
    00629     }
    00630
    00631     while (vid) {
    00632         BITMAP *vbmp = vid->memory_copy;
    00633
    00634         int _y1, _y2, _x;
    00635         if (vid->x_ofs > x || vid->y_ofs > y2
    00636          || vid->x_ofs + vbmp->w <= x
    00637          || vid->y_ofs + vbmp->h <= y1) {
    00638
    00639             vid = vid->next;
    00640             continue;
    00641         }
    00642
    00643         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
    00644         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
    00645         _x = x - vid->x_ofs;
    00646
    00647         set_drawing_pattern();
    00648         vline(vbmp, _x, _y1, _y2, color);
    00649         unset_drawing_pattern();
    00650         update_texture_memory(vid, _x, _y1, _x, _y2);
    00651
    00652         vid = vid->next;
    00653     }
    00654
    00655     return;
    00656 }
    00657
    00658
    00659
    00660 static void allegro_gl_video_hline(BITMAP *bmp, int x1, int y, int x2,
    00661                                    int color) {
    00662
    00663     AGL_VIDEO_BITMAP *vid;
    00664
    00665     AGL_LOG(2, "glvtable.c:allegro_gl_video_hline\n");
    00666     vid = bmp->extra;
    00667
    00668     if (is_sub_bitmap(bmp)) {
    00669         x1 += bmp->x_ofs;
    00670         x2 += bmp->x_ofs;
    00671         y  += bmp->y_ofs;
    00672     }
    00673
    00674     if (y < bmp->ct || y >= bmp->cb) {
    00675         return;
    00676     }
    00677
    00678     if (x1 > x2) {
    00679         int temp = x1;
    00680         x1 = x2;
    00681         x2 = temp;
    00682     }
    00683
    00684     if (x1 < bmp->cl) {
    00685         x1 = bmp->cl;
    00686     }
    00687     if (x2 >= bmp->cr) {
    00688         x2 = bmp->cr - 1;
    00689     }
    00690
    00691     while (vid) {
    00692         BITMAP *vbmp = vid->memory_copy;
    00693
    00694         int _x1, _x2, _y;
    00695         if (vid->y_ofs > y || vid->x_ofs > x2
    00696          || vid->x_ofs + vbmp->w <= x1
    00697          || vid->y_ofs + vbmp->h <= y) {
    00698
    00699             vid = vid->next;
    00700             continue;
    00701         }
    00702
    00703         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
    00704         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
    00705         _y = y - vid->y_ofs;
    00706
    00707         set_drawing_pattern();
    00708         hline(vbmp, _x1, _y, _x2, color);
    00709         unset_drawing_pattern();
    00710         update_texture_memory(vid, _x1, _y, _x2, _y);
    00711
    00712         vid = vid->next;
    00713     }
    00714
    00715     return;
    00716 }
    00717
    00718
    00719
    00720 static void allegro_gl_video_line(struct BITMAP *bmp, int x1, int y1, int x2,
    00721                                   int y2, int color) {
    00722
    00723     /* Note: very very slow */
    00724     do_line(bmp, x1, y1, x2, y2, color, allegro_gl_video_putpixel);
    00725
    00726     return;
    00727 }
    00728
    00729
    00730
    00731 static void allegro_gl_video_rectfill(struct BITMAP *bmp, int x1, int y1,
    00732                                       int x2, int y2, int color) {
    00733
    00734     AGL_VIDEO_BITMAP *vid;
    00735
    00736     AGL_LOG(2, "glvtable.c:allegro_gl_video_rectfill\n");
    00737     vid = bmp->extra;
    00738
    00739     if (is_sub_bitmap(bmp)) {
    00740         x1 += bmp->x_ofs;
    00741         x2 += bmp->x_ofs;
    00742         y1 += bmp->y_ofs;
    00743         y2 += bmp->y_ofs;
    00744     }
    00745
    00746     if (y1 > y2) {
    00747         int temp = y1;
    00748         y1 = y2;
    00749         y2 = temp;
    00750     }
    00751
    00752     if (x1 > x2) {
    00753         int temp = x1;
    00754         x1 = x2;
    00755         x2 = temp;
    00756     }
    00757
    00758     if (x1 < bmp->cl) {
    00759         x1 = bmp->cl;
    00760     }
    00761     if (x2 > bmp->cr) {
    00762         x2 = bmp->cr;
    00763     }
    00764     if (y1 < bmp->ct) {
    00765         y1 = bmp->ct;
    00766     }
    00767     if (y1 > bmp->cb) {
    00768         y1 = bmp->cb;
    00769     }
    00770
    00771     while (vid) {
    00772         BITMAP *vbmp = vid->memory_copy;
    00773
    00774         int _y1, _y2, _x1, _x2;
    00775         if (vid->x_ofs > x2 || vid->y_ofs > y2
    00776          || vid->x_ofs + vbmp->w <= x1
    00777          || vid->y_ofs + vbmp->h <= y1) {
    00778
    00779             vid = vid->next;
    00780             continue;
    00781         }
    00782
    00783         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
    00784         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
    00785         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
    00786         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
    00787
    00788         set_drawing_pattern();
    00789         rectfill(vbmp, _x1, _y1, _x2, _y2, color);
    00790         unset_drawing_pattern();
    00791
    00792         update_texture_memory(vid, _x1, _y1, _x2, _y2);
    00793
    00794         vid = vid->next;
    00795     }
    00796
    00797     return;
    00798 }
    00799
    00800
    00801 static void allegro_gl_video_triangle(struct BITMAP *bmp, int x1, int y1,
    00802                                       int x2, int y2, int x3, int y3, int color)
    00803 {
    00804     AGL_VIDEO_BITMAP *vid;
    00805     int min_y, max_y, min_x, max_x;
    00806
    00807     AGL_LOG(2, "glvtable.c:allegro_gl_video_triangle\n");
    00808     vid = bmp->extra;
    00809
    00810     if (is_sub_bitmap(bmp)) {
    00811         x1 += bmp->x_ofs;
    00812         x2 += bmp->x_ofs;
    00813         x3 += bmp->x_ofs;
    00814         y1 += bmp->y_ofs;
    00815         y2 += bmp->y_ofs;
    00816         y3 += bmp->y_ofs;
    00817     }
    00818
    00819     min_y = MIN(y1, MIN(y2, y3));
    00820     min_x = MIN(x1, MIN(x2, x3));
    00821     max_y = MAX(y1, MAX(y2, y3));
    00822     max_x = MAX(x1, MAX(x2, x3));
    00823
    00824     while (vid) {
    00825         BITMAP *vbmp = vid->memory_copy;
    00826
    00827         int _y1, _y2, _x1, _x2, _x3, _y3;
    00828         if (vid->x_ofs > max_x || vid->y_ofs > max_y
    00829          || vid->x_ofs + vbmp->w <= min_x
    00830          || vid->y_ofs + vbmp->h <= min_y) {
    00831
    00832             vid = vid->next;
    00833             continue;
    00834         }
    00835
    00836         _y1 = y1 - vid->y_ofs;
    00837         _y2 = y2 - vid->y_ofs;
    00838         _y3 = y3 - vid->y_ofs;
    00839         _x1 = x1 - vid->x_ofs;
    00840         _x2 = x2 - vid->x_ofs;
    00841         _x3 = x3 - vid->x_ofs;
    00842
    00843         set_clip_rect(vbmp, bmp->cl - vid->x_ofs, bmp->ct - vid->y_ofs,
    00844                             bmp->cr - vid->x_ofs - 1, bmp->cb - vid->y_ofs - 1);
    00845
    00846         set_drawing_pattern();
    00847
    00848         triangle(vbmp, _x1, _y1, _x2, _y2, _x3, _y3, color);
    00849
    00850         unset_drawing_pattern();
    00851
    00852         set_clip_rect(vbmp, 0, 0, vbmp->w - 1, vbmp->h - 1);
    00853
    00854         /* Not quite the minimal rectangle occupied by the triangle, but
    00855         * pretty close */
    00856         _y1 = MAX(0, min_y - vid->y_ofs);
    00857         _y2 = MIN(vbmp->h - 1, max_y - vid->y_ofs);
    00858         _x1 = MAX(0, min_x - vid->x_ofs);
    00859         _x2 = MIN(vbmp->w - 1, max_x - vid->x_ofs);
    00860
    00861         update_texture_memory(vid, _x1, _y1, _x2, _y2);
    00862
    00863         vid = vid->next;
    00864     }
    00865 }
    00866
    00867
    00868
    00869 static void allegro_gl_video_blit_from_memory_ex(BITMAP *source, BITMAP *dest,
    00870                     int source_x, int source_y, int dest_x, int dest_y,
    00871                     int width, int height, int draw_type) {
    00872
    00873     AGL_VIDEO_BITMAP *vid;
    00874     BITMAP *dest_parent = dest;
    00875
    00876     if (is_sub_bitmap (dest)) {
    00877        dest_x += dest->x_ofs;
    00878        dest_y += dest->y_ofs;
    00879        while (dest_parent->id & BMP_ID_SUB)
    00880           dest_parent = (BITMAP *)dest_parent->extra;
    00881     }
    00882
    00883     if (dest_x < dest->cl) {
    00884         dest_x = dest->cl;
    00885     }
    00886     if (dest_y < dest->ct) {
    00887         dest_y = dest->ct;
    00888     }
    00889     if (dest_x + width >= dest->cr) {
    00890         width = dest->cr - dest_x;
    00891     }
    00892     if (dest_y + height >= dest->cb) {
    00893         height = dest->cb - dest_y;
    00894     }
    00895     if (width < 1 || height < 1) {
    00896         return;
    00897     }
    00898
    00899     vid = dest_parent->extra;
    00900
    00901     while (vid) {
    00902         BITMAP *vbmp = vid->memory_copy;
    00903
    00904         int _x, _y, _w, _h, _sx, _sy;
    00905         if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height
    00906          || vid->x_ofs + vbmp->w <= dest_x
    00907          || vid->y_ofs + vbmp->h <= dest_y) {
    00908
    00909             vid = vid->next;
    00910             continue;
    00911         }
    00912
    00913         _x = MAX (vid->x_ofs, dest_x) - vid->x_ofs;
    00914         _w = MIN (vid->x_ofs + vbmp->w, dest_x + width)
    00915            - vid->x_ofs - _x;
    00916         _y = MAX (vid->y_ofs, dest_y) - vid->y_ofs;
    00917         _h = MIN (vid->y_ofs + vbmp->h, dest_y + height)
    00918            - vid->y_ofs - _y;
    00919
    00920         _sx = source_x + vid->x_ofs + _x - dest_x;
    00921         _sy = source_y + vid->y_ofs + _y - dest_y;
    00922
    00923         if (draw_type == BLIT) {
    00924             blit(source, vbmp, _sx, _sy, _x, _y, _w, _h);
    00925         }
    00926         else if (draw_type == MASKED_BLIT) {
    00927             masked_blit(source, vbmp, _sx, _sy, _x, _y, _w, _h);
    00928         }
    00929         else if (draw_type == TRANS) {
    00930             BITMAP *clip = create_sub_bitmap(source, _sx, _sy, _w, _h);
    00931             if (!clip)
    00932                 return;
    00933             draw_trans_sprite(vbmp, clip, _x, _y);
    00934             destroy_bitmap(clip);
    00935         }
    00936
    00937         update_texture_memory(vid, _x, _y, _x + _w - 1, _y + _h - 1);
    00938
    00939         vid = vid->next;
    00940     }
    00941
    00942     return;
    00943 }
    00944
    00945
    00946 void allegro_gl_video_blit_from_memory(BITMAP *source, BITMAP *dest,
    00947                     int source_x, int source_y, int dest_x, int dest_y,
    00948                     int width, int height) {
    00949
    00950     allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y,
    00951                                          dest_x, dest_y, width, height, BLIT);
    00952     return;
    00953 }
    00954
    00955
    00956
    00957 void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest,
    00958                          int source_x, int source_y, int dest_x, int dest_y,
    00959                          int width, int height) {
    00960
    00961     AGL_VIDEO_BITMAP *vid;
    00962     BITMAP *source_parent = source;
    00963
    00964     AGL_LOG(2, "glvtable.c:allegro_gl_video_blit_to_memory\n");
    00965
    00966     if (is_sub_bitmap(source)) {
    00967        source_x += source->x_ofs;
    00968        source_y += source->y_ofs;
    00969        while (source_parent->id & BMP_ID_SUB)
    00970           source_parent = (BITMAP *)source_parent->extra;
    00971     }
    00972
    00973     vid = source_parent->extra;
    00974
    00975     while (vid) {
    00976         BITMAP *vbmp = vid->memory_copy;
    00977         int x, y, dx, dy, w, h;
    00978
    00979         x = MAX(source_x, vid->x_ofs) - vid->x_ofs;
    00980         y = MAX(source_y, vid->y_ofs) - vid->y_ofs;
    00981         w = MIN(vid->x_ofs + vbmp->w, source_x + width) - vid->x_ofs;
    00982         h = MIN(vid->y_ofs + vbmp->h, source_y + height) - vid->y_ofs;
    00983         dx = MAX(0, vid->x_ofs - source_x) + dest_x;
    00984         dy = MAX(0, vid->y_ofs - source_y) + dest_y;
    00985
    00986         blit(vbmp, dest, x, y, dx, dy, w, h);
    00987
    00988         vid = vid->next;
    00989     }
    00990
    00991     return;
    00992 }
    00993
    00994
    00995
    00996 /* Just like allegro_gl_video_blit_from_memory(), except that draws only to the
    00997  * memory copy.
    00998  */
    00999 static void __video_update_memory_copy(BITMAP *source, BITMAP *dest,
    01000                             int source_x, int source_y, int dest_x, int dest_y,
    01001                             int width, int height, int draw_type) {
    01002     AGL_VIDEO_BITMAP *vid;
    01003     BITMAP *dest_parent = dest;
    01004
    01005     if (is_sub_bitmap (dest)) {
    01006        dest_x += dest->x_ofs;
    01007        dest_y += dest->y_ofs;
    01008        while (dest_parent->id & BMP_ID_SUB)
    01009           dest_parent = (BITMAP *)dest_parent->extra;
    01010     }
    01011
    01012     if (dest_x < dest->cl) {
    01013         dest_x = dest->cl;
    01014     }
    01015     if (dest_y < dest->ct) {
    01016         dest_y = dest->ct;
    01017     }
    01018     if (dest_x + width >= dest->cr) {
    01019         width = dest->cr - dest_x;
    01020     }
    01021     if (dest_y + height >= dest->cb) {
    01022         height = dest->cb - dest_y;
    01023     }
    01024     if (width < 1 || height < 1) {
    01025         return;
    01026     }
    01027
    01028     vid = dest_parent->extra;
    01029
    01030     while (vid) {
    01031         int sx, sy;
    01032         BITMAP *vbmp = vid->memory_copy;
    01033
    01034         int dx, dy, w, h;
    01035         if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height
    01036          || vid->x_ofs + vbmp->w <= dest_x
    01037          || vid->y_ofs + vbmp->h <= dest_y) {
    01038
    01039             vid = vid->next;
    01040             continue;
    01041         }
    01042
    01043         dx = MAX (vid->x_ofs, dest_x) - vid->x_ofs;
    01044         w = MIN (vid->x_ofs + vbmp->w, dest_x + width)
    01045            - vid->x_ofs - dx;
    01046         dy = MAX (vid->y_ofs, dest_y) - vid->y_ofs;
    01047         h = MIN (vid->y_ofs + vbmp->h, dest_y + height)
    01048            - vid->y_ofs - dy;
    01049
    01050         sx = source_x + vid->x_ofs + dx - dest_x;
    01051         sy = source_y + vid->y_ofs + dy - dest_y;
    01052
    01053         if (draw_type == MASKED_BLIT) {
    01054             masked_blit(source, vbmp, sx, sy, dx, dy, w, h);
    01055         }
    01056         else if (draw_type == BLIT) {
    01057             blit(source, vbmp, sx, sy, dx, dy, w, h);
    01058         }
    01059         else if (draw_type == TRANS) {
    01060             BITMAP *clip = create_sub_bitmap(source, sx, sy, w, h);
    01061             if (!clip)
    01062                 return;
    01063             draw_trans_sprite(vbmp, clip, dx, dy);
    01064             destroy_bitmap(clip);
    01065         }
    01066
    01067         vid = vid->next;
    01068     }
    01069
    01070     return;
    01071 }
    01072
    01073
    01074 #define FOR_EACH_TEXTURE_FRAGMENT(  \
    01075     screen_blit_from_vid,           /* used when dest is FBO to blit to texture
    01076                                        memory from video bitmap */                \
    01077     screen_blit_from_mem,           /* used when dest is FBO to blit to texture
    01078                                        memory from memory bitmap */               \
    01079     mem_copy_blit_from_vid,         /* used to update the memory copy of the
    01080                                        dest from the source video bitmap */       \
    01081     mem_copy_blit_from_mem,         /* used to update the memory copy of the
    01082                                        dest from the source memory bitmap */      \
    01083     vid_and_mem_copy_blit_from_vid, /* used when dest is not FBO, draws to both
    01084                                        memory copy and texute memory of the dest,
    01085                                        from video bitmap source*/                 \
    01086     vid_and_mem_copy_blit_from_mem) /* used when dest is not FBO, draws to both
    01087                                        memory copy and texute memory of the dest,
    01088                                        from memory bitmap source */               \
    01089 {                                                          \
    01090     int used_fbo = FALSE;                                  \
    01091     AGL_VIDEO_BITMAP *vid;                                 \
    01092                                                            \
    01093     vid = dest->extra;                                     \
    01094     if (vid->fbo) {                                        \
    01095         int sx, sy;                                        \
    01096         int dx, dy;                                        \
    01097         int w, h;                                          \
    01098                                                            \
    01099         static GLint v[4];                                 \
    01100         static double allegro_gl_projection_matrix[16];    \
    01101         static double allegro_gl_modelview_matrix[16];     \
    01102                                                            \
    01103         glGetIntegerv(GL_VIEWPORT, &v[0]);                 \
    01104         glMatrixMode(GL_MODELVIEW);                        \
    01105         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);   \
    01106         glMatrixMode(GL_PROJECTION);                                      \
    01107         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); \
    01108                                                                           \
    01109         while (vid) {                                                     \
    01110             if (dest_x >= vid->x_ofs + vid->memory_copy->w ||             \
    01111                 dest_y >= vid->y_ofs + vid->memory_copy->h ||             \
    01112                 vid->x_ofs >= dest_x + width ||          \
    01113                 vid->y_ofs >= dest_y + height) {         \
    01114                 vid = vid->next;                         \
    01115                 continue;                                \
    01116             }                                            \
    01117                                                          \
    01118             dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;                  \
    01119             w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)   \
    01120               - vid->x_ofs - dx;                                        \
    01121             dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;                  \
    01122             h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)  \
    01123               - vid->y_ofs - dy;                                        \
    01124                                                                         \
    01125             sx = source_x + vid->x_ofs + dx - dest_x;                   \
    01126             sy = source_y + vid->y_ofs + dy - dest_y;                   \
    01127                                                                         \
    01128             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);         \
    01129                                                                         \
    01130             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); \
    01131             glMatrixMode(GL_PROJECTION);                                \
    01132             glLoadIdentity();                                           \
    01133             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); \
    01134             glMatrixMode(GL_MODELVIEW);                                 \
    01135                                              \
    01136             if (is_memory_bitmap(source)) {  \
    01137                 screen_blit_from_mem;        \
    01138             }                                \
    01139             else {                           \
    01140                 screen_blit_from_vid;        \
    01141             }                                \
    01142                                 \
    01143             vid = vid->next;    \
    01144         }                       \
    01145                                 \
    01146         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); \
    01147                                                      \
    01148         glViewport(v[0], v[1], v[2], v[3]);          \
    01149         glMatrixMode(GL_PROJECTION);                 \
    01150         glLoadMatrixd(allegro_gl_projection_matrix); \
    01151         glMatrixMode(GL_MODELVIEW);                  \
    01152         glLoadMatrixd(allegro_gl_modelview_matrix);  \
    01153                                           \
    01154         used_fbo = TRUE;                  \
    01155     }                                     \
    01156                                           \
    01157     if (is_video_bitmap(source)) {        \
    01158         int sx, sy;      \
    01159         int dx, dy;      \
    01160         int w, h;        \
    01161                          \
    01162         vid = source->extra;   \
    01163                                \
    01164         while (vid) {          \
    01165             if (source_x >= vid->x_ofs + vid->memory_copy->w ||  \
    01166                 source_y >= vid->y_ofs + vid->memory_copy->h ||  \
    01167                 vid->x_ofs >= source_x + width ||                \
    01168                 vid->y_ofs >= source_y + height) {               \
    01169                 vid = vid->next;                                 \
    01170                 continue;                                        \
    01171             }                                                    \
    01172                                                                  \
    01173             sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;         \
    01174             w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)  \
    01175               - vid->x_ofs - sx;                                         \
    01176             sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;                 \
    01177             h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height) \
    01178               - vid->y_ofs - sy;                                         \
    01179                                                                          \
    01180             dx = dest_x + vid->x_ofs + sx - source_x;  \
    01181             dy = dest_y + vid->y_ofs + sy - source_y;  \
    01182                                                        \
    01183             if (used_fbo) {                            \
    01184                 mem_copy_blit_from_vid;                \
    01185             }                                          \
    01186             else {                                     \
    01187                 vid_and_mem_copy_blit_from_vid;        \
    01188             }                                  \
    01189                                                \
    01190             vid = vid->next;                   \
    01191         }                                      \
    01192     }                                          \
    01193     else if (is_memory_bitmap(source)) {       \
    01194         if (used_fbo) {                        \
    01195             mem_copy_blit_from_mem;            \
    01196         }                                      \
    01197         else {                                 \
    01198             vid_and_mem_copy_blit_from_mem;    \
    01199         }                                      \
    01200     }                                          \
    01201 }
    01202
    01203
    01204 /* allegro_gl_video_blit_to_self:
    01205  * blit() overload for video -> video blits
    01206  */
    01207 void allegro_gl_video_blit_to_self(struct BITMAP *source, struct BITMAP *dest,
    01208     int source_x, int source_y, int dest_x, int dest_y, int width, int height) {
    01209
    01210     FOR_EACH_TEXTURE_FRAGMENT (
    01211         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
    01212         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
    01213         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, BLIT),
    01214         __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, BLIT),
    01215         allegro_gl_video_blit_from_memory(vid->memory_copy, dest, sx, sy, dx, dy, w, h),
    01216         allegro_gl_video_blit_from_memory(source, dest, source_x, source_y, dest_x, dest_y, width, height)
    01217     )
    01218 }
    01219
    01220
    01221 static void do_masked_blit_video(struct BITMAP *source, struct BITMAP *dest,
    01222             int source_x, int source_y, int dest_x, int dest_y,
    01223             int width, int height, int flip_dir, int blit_type) {
    01224
    01225     FOR_EACH_TEXTURE_FRAGMENT (
    01226         do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type),
    01227         do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type),
    01228         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT),
    01229         __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT),
    01230         allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT),
    01231         allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT)
    01232     )
    01233 }
    01234
    01235
    01236 /* allegro_gl_video_masked_blit:
    01237  * masked_blit() overload for video -> video masked blits
    01238  */
    01239 static void allegro_gl_video_masked_blit(struct BITMAP *source,
    01240                 struct BITMAP *dest, int source_x, int source_y,
    01241                 int dest_x, int dest_y, int width, int height) {
    01242     do_masked_blit_video(source, dest, source_x, source_y, dest_x, dest_y,
    01243                          width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
    01244
    01245     return;
    01246 }
    01247
    01248
    01249 /* allegro_gl_video_draw_sprite:
    01250  * draw_sprite() overload for video -> video sprite drawing
    01251  */
    01252 static void allegro_gl_video_draw_sprite(struct BITMAP *bmp,
    01253                         struct BITMAP *sprite, int x, int y) {
    01254
    01255     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
    01256                          FALSE, AGL_NO_ROTATION);
    01257
    01258     return;
    01259 }
    01260
    01261
    01262 /* allegro_gl_video_draw_sprite_v_flip:
    01263  * draw_sprite_v_flip() overload for video -> video blits
    01264  * FIXME: Broken if the bitmap was split into multiple textures.
    01265  * FIXME: Doesn't apply rotation and scale to the memory copy
    01266  */
    01267 static void allegro_gl_video_draw_sprite_v_flip(struct BITMAP *bmp,
    01268                         struct BITMAP *sprite, int x, int y) {
    01269
    01270     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
    01271                          AGL_V_FLIP, AGL_NO_ROTATION);
    01272
    01273     return;
    01274 }
    01275
    01276
    01277 /* allegro_gl_video_draw_sprite_h_flip:
    01278  * draw_sprite_v_flip() overload for video -> video blits
    01279  * FIXME: Broken if the bitmap was split into multiple textures.
    01280  * FIXME: Doesn't apply rotation and scale to the memory copy
    01281  */
    01282 static void allegro_gl_video_draw_sprite_h_flip(struct BITMAP *bmp,
    01283                         struct BITMAP *sprite, int x, int y) {
    01284
    01285     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
    01286                          AGL_H_FLIP, AGL_NO_ROTATION);
    01287
    01288     return;
    01289 }
    01290
    01291
    01292 /* allegro_gl_video_draw_sprite_vh_flip:
    01293  * draw_sprite_vh_flip() overload for video -> video blits
    01294  * FIXME: Broken if the bitmap was split into multiple textures.
    01295  * FIXME: Doesn't apply rotation and scale to the memory copy
    01296  */
    01297 static void allegro_gl_video_draw_sprite_vh_flip(struct BITMAP *bmp,
    01298                         struct BITMAP *sprite, int x, int y) {
    01299
    01300     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
    01301                          AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
    01302
    01303     return;
    01304 }
    01305
    01306
    01307 /* allegro_gl_video_pivot_scaled_sprite_flip:
    01308  * FIXME: Broken if the bitmap was split into multiple textures.
    01309  * FIXME: Doesn't apply rotation and scale to the memory copy
    01310  * FIXME: Doesn't work for when FBO is not available.
    01311  */
    01312 static void allegro_gl_video_pivot_scaled_sprite_flip(struct BITMAP *bmp,
    01313             struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy,
    01314             fixed angle, fixed scale, int v_flip) {
    01315     double dscale = fixtof(scale);
    01316     GLint matrix_mode;
    01317
    01318 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
    01319
    01320     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
    01321     glMatrixMode(GL_MODELVIEW);
    01322     glPushMatrix();
    01323     glTranslated(fixtof(x), fixtof(y), 0.);
    01324     glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
    01325     glScaled(dscale, dscale, dscale);
    01326     glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
    01327
    01328     do_masked_blit_video(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
    01329                           sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
    01330     glPopMatrix();
    01331     glMatrixMode(matrix_mode);
    01332
    01333 #undef BIN_2_DEG
    01334
    01335     return;
    01336 }
    01337
    01338
    01339 /* allegro_gl_video_do_stretch_blit:
    01340  * overload for all kind of video -> video and video -> screen stretchers
    01341  * FIXME: Doesn't apply scale to the memory copy
    01342  * FIXME: Doesn't work for video->video when FBO is not available.
    01343  */
    01344 static void allegro_gl_video_do_stretch_blit(BITMAP *source, BITMAP *dest,
    01345                int source_x, int source_y, int source_width, int source_height,
    01346                int dest_x, int dest_y, int dest_width, int dest_height,
    01347                int masked) {
    01348     /* note: src is a video bitmap, dest is not a memory bitmap */
    01349
    01350     double scalew = ((double)dest_width) / source_width;
    01351     double scaleh = ((double)dest_height) / source_height;
    01352
    01353     GLint matrix_mode;
    01354
    01355     /* BITMAP_BLIT_CLIP macro from glvtable.c is no good for scaled images. */
    01356     if (dest->clip) {
    01357         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
    01358          || (dest_x + dest_width < dest->cl) || (dest_y + dest_height < dest->ct)) {
    01359             return;
    01360         }
    01361         if (dest_x < dest->cl) {
    01362             source_x -= (dest_x - dest->cl) / scalew;
    01363             dest_x = dest->cl;
    01364         }
    01365         if (dest_y < dest->ct) {
    01366             source_y -= (dest_y - dest->ct) / scaleh;
    01367             dest_y = dest->ct;
    01368         }
    01369         if (dest_x + dest_width > dest->cr) {
    01370             source_width -= (dest_x + dest_width - dest->cr) / scalew;
    01371             dest_width = dest->cr - dest_x;
    01372         }
    01373         if (dest_y + dest_height > dest->cb) {
    01374             source_height -= (dest_y + dest_height - dest->cb) / scaleh;
    01375             dest_height = dest->cb - dest_y;
    01376         }
    01377     }
    01378
    01379     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
    01380     glMatrixMode(GL_MODELVIEW);
    01381     glPushMatrix();
    01382     glTranslated(dest_x, dest_y, 0.);
    01383     glScaled(scalew, scaleh, 1.);
    01384     glTranslated(-dest_x, -dest_y, 0.);
    01385
    01386     if (masked) {
    01387         if (is_screen_bitmap(dest)) {
    01388             do_masked_blit_screen(source, dest, source_x, source_y,
    01389                                   dest_x, dest_y, source_width, source_height,
    01390                                   FALSE, AGL_REGULAR_BMP);
    01391         }
    01392         else {
    01393             do_masked_blit_video(source, dest, source_x, source_y,
    01394                                  dest_x, dest_y, source_width, source_height,
    01395                                  FALSE, AGL_REGULAR_BMP);
    01396         }
    01397     }
    01398     else {
    01399         allegro_gl_screen_blit_to_self(source, dest, source_x, source_y,
    01400                            dest_x, dest_y, source_width, source_height);
    01401     }
    01402
    01403     glPopMatrix();
    01404     glMatrixMode(matrix_mode);
    01405
    01406     return;
    01407 }
    01408
    01409
    01410
    01411 /* allegro_gl_video_draw_trans_rgba_sprite:
    01412  * draw_trans_sprite() overload for video -> video drawing
    01413  */
    01414 static void allegro_gl_video_draw_trans_rgba_sprite(BITMAP *bmp,
    01415                                 BITMAP *sprite, int x, int y) {
    01416     /* Adapt variables for FOR_EACH_TEXTURE_FRAGMENT macro. */
    01417     BITMAP *source = sprite;
    01418     BITMAP *dest = bmp;
    01419     int dest_x = x;
    01420     int dest_y = y;
    01421     int source_x = 0;
    01422     int source_y = 0;
    01423     int width = sprite->w;
    01424     int height = sprite->h;
    01425     GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
    01426     GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
    01427
    01428     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
    01429         glEnable(GL_COLOR_LOGIC_OP);
    01430     else
    01431         glEnable(GL_BLEND);
    01432
    01433     FOR_EACH_TEXTURE_FRAGMENT (
    01434         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
    01435         allegro_gl_upload_and_display_texture(sprite, sx, sy, dx, dy, w, h, 0, format, type),
    01436         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS),
    01437         __video_update_memory_copy(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS),
    01438         allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS),
    01439         allegro_gl_video_blit_from_memory_ex(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS)
    01440     )
    01441
    01442     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
    01443         glDisable(GL_COLOR_LOGIC_OP);
    01444     else
    01445         glDisable(GL_BLEND);
    01446
    01447     return;
    01448 }
    01449
    01450
    01451
    01452 /* allegro_gl_video_draw_sprite_ex:
    01453  * draw_sprite_ex() overload for video -> video and memory -> video drawing
    01454  *
    01455  * When mode is DRAW_SPRITE_TRANS:
    01456  * FIXME: Broken if the bitmap was split into multiple textures.
    01457  * FIXME: Doesn't apply flipping to the memory copy
    01458  */
    01459 static void allegro_gl_video_draw_sprite_ex(BITMAP *bmp, BITMAP *sprite,
    01460                                             int x, int y, int mode, int flip) {
    01461     int matrix_mode;
    01462     int lflip = 0;
    01463
    01464     /* convert allegro's flipping flags to AGL's flags */
    01465     switch (flip) {
    01466         case DRAW_SPRITE_NO_FLIP:
    01467             lflip = FALSE;
    01468         break;
    01469         case DRAW_SPRITE_V_FLIP:
    01470             lflip = AGL_V_FLIP;
    01471         break;
    01472         case DRAW_SPRITE_H_FLIP:
    01473             lflip = AGL_H_FLIP;
    01474         break;
    01475         case DRAW_SPRITE_VH_FLIP:
    01476             lflip = AGL_V_FLIP | AGL_H_FLIP;
    01477         break;
    01478     }
    01479
    01480     switch (mode) {
    01481         case DRAW_SPRITE_NORMAL:
    01482             do_masked_blit_video(sprite, bmp, 0, 0, x, y,
    01483                                  sprite->w, sprite->h, lflip, FALSE);
    01484         break;
    01485         case DRAW_SPRITE_TRANS:
    01486             if (lflip) {
    01487                 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
    01488                 glMatrixMode(GL_MODELVIEW);
    01489                 glPushMatrix();
    01490
    01491                 glTranslatef(x, y, 0.f);
    01492                 glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1);
    01493                 glTranslatef(-x, -y, 0);
    01494                 glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0,
    01495                              (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0);
    01496             }
    01497
    01498             allegro_gl_video_draw_trans_rgba_sprite(bmp, sprite, x, y);
    01499
    01500             if (lflip) {
    01501                 glPopMatrix();
    01502                 glMatrixMode(matrix_mode);
    01503             }
    01504         break;
    01505         case DRAW_SPRITE_LIT:
    01506             /* not implemented */
    01507         break;
    01508     }
    01509 }
    01510
    01511
    01512
    01513 static void allegro_gl_video_clear_to_color(BITMAP *bmp, int color) {
    01514     AGL_VIDEO_BITMAP *vid = bmp->extra;
    01515
    01516     if (vid->fbo) {
    01517         static GLint v[4];
    01518         static double allegro_gl_projection_matrix[16];
    01519         static double allegro_gl_modelview_matrix[16];
    01520
    01521         glGetIntegerv(GL_VIEWPORT, &v[0]);
    01522         glMatrixMode(GL_MODELVIEW);
    01523         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
    01524         glMatrixMode(GL_PROJECTION);
    01525         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
    01526
    01527         while (vid) {
    01528             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
    01529
    01530             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
    01531             glMatrixMode(GL_PROJECTION);
    01532             glLoadIdentity();
    01533             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
    01534             glMatrixMode(GL_MODELVIEW);
    01535
    01536             allegro_gl_screen_clear_to_color(bmp, color);
    01537             clear_to_color(vid->memory_copy, color);
    01538             vid = vid->next;
    01539         }
    01540
    01541         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    01542
    01543         glViewport(v[0], v[1], v[2], v[3]);
    01544         glMatrixMode(GL_PROJECTION);
    01545         glLoadMatrixd(allegro_gl_projection_matrix);
    01546         glMatrixMode(GL_MODELVIEW);
    01547         glLoadMatrixd(allegro_gl_modelview_matrix);
    01548     }
    01549     else {
    01550         allegro_gl_video_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
    01551     }
    01552 }
    01553
    01554
    01555
    01556 /* FIXME: Doesn't work when FBO is not available.
    01557  * FIXME: Doesn't care for segmented video bitmaps.
    01558  */
    01559 static void allegro_gl_video_draw_color_glyph(struct BITMAP *bmp,
    01560     struct BITMAP *sprite, int x, int y, int color, int bg)
    01561 {
    01562     AGL_VIDEO_BITMAP *vid = bmp->extra;
    01563
    01564     static GLint v[4];
    01565     static double allegro_gl_projection_matrix[16];
    01566     static double allegro_gl_modelview_matrix[16];
    01567
    01568     if (!vid->fbo)
    01569         return;
    01570
    01571     glGetIntegerv(GL_VIEWPORT, &v[0]);
    01572     glMatrixMode(GL_MODELVIEW);
    01573     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
    01574     glMatrixMode(GL_PROJECTION);
    01575     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
    01576
    01577     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
    01578
    01579     glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
    01580     glMatrixMode(GL_PROJECTION);
    01581     glLoadIdentity();
    01582     gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
    01583     glMatrixMode(GL_MODELVIEW);
    01584
    01585     allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 0);
    01586
    01587     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    01588
    01589     glViewport(v[0], v[1], v[2], v[3]);
    01590     glMatrixMode(GL_PROJECTION);
    01591     glLoadMatrixd(allegro_gl_projection_matrix);
    01592     glMatrixMode(GL_MODELVIEW);
    01593     glLoadMatrixd(allegro_gl_modelview_matrix);
    01594
    01595     vid->memory_copy->vtable->draw_character(vid->memory_copy, sprite, x, y, color, bg);
    01596 }
    01597
    01598
    01599
    01600 static void allegro_gl_video_draw_256_sprite(BITMAP *bmp, BITMAP *sprite,
    01601                                       int x, int y) {
    01602     allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, -1, _textmode);
    01603 }
    01604
    01605
    01606
    01607 static void allegro_gl_video_draw_character(BITMAP *bmp, BITMAP *sprite,
    01608                                             int x, int y, int color, int bg) {
    01609     allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, color, bg);
    01610 }
    01611
    01612
    01613
    01614 /* FIXME: Doesn't work when FBO is not available.
    01615  * FIXME: Doesn't care for segmented video bitmaps.
    01616  */
    01617 static void allegro_gl_video_draw_glyph(struct BITMAP *bmp,
    01618                                AL_CONST struct FONT_GLYPH *glyph, int x, int y,
    01619                                int color, int bg) {
    01620     AGL_VIDEO_BITMAP *vid = bmp->extra;
    01621
    01622     static GLint v[4];
    01623     static double allegro_gl_projection_matrix[16];
    01624     static double allegro_gl_modelview_matrix[16];
    01625
    01626     if (!vid->fbo)
    01627         return;
    01628
    01629     glGetIntegerv(GL_VIEWPORT, &v[0]);
    01630     glMatrixMode(GL_MODELVIEW);
    01631     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
    01632     glMatrixMode(GL_PROJECTION);
    01633     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
    01634
    01635     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
    01636
    01637     glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
    01638     glMatrixMode(GL_PROJECTION);
    01639     glLoadIdentity();
    01640     gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
    01641     glMatrixMode(GL_MODELVIEW);
    01642
    01643     allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 1);
    01644
    01645     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    01646
    01647     glViewport(v[0], v[1], v[2], v[3]);
    01648     glMatrixMode(GL_PROJECTION);
    01649     glLoadMatrixd(allegro_gl_projection_matrix);
    01650     glMatrixMode(GL_MODELVIEW);
    01651     glLoadMatrixd(allegro_gl_modelview_matrix);
    01652
    01653     vid->memory_copy->vtable->draw_glyph(vid->memory_copy, glyph, x, y, color, bg);
    01654 }
    01655
    01656
    01657
    01658 static void allegro_gl_video_polygon3d_f(BITMAP *bmp, int type, BITMAP *texture,
    01659                                   int vc, V3D_f *vtx[])
    01660 {
    01661     AGL_VIDEO_BITMAP *vid = bmp->extra;
    01662
    01663     /* Switch to software mode is using polygon type that isn't supported by
    01664        allegro_gl_screen_polygon3d_f. */
    01665     int use_fbo = (type == POLYTYPE_FLAT) ||
    01666                   (type == POLYTYPE_GRGB) ||
    01667                   (type == POLYTYPE_GCOL) ||
    01668                   (type == POLYTYPE_ATEX) ||
    01669                   (type == POLYTYPE_PTEX) ||
    01670                   (type == POLYTYPE_ATEX_TRANS) ||
    01671                   (type == POLYTYPE_PTEX_TRANS);
    01672
    01673     if (vid->fbo && use_fbo) {
    01674         static GLint v[4];
    01675         static double allegro_gl_projection_matrix[16];
    01676         static double allegro_gl_modelview_matrix[16];
    01677
    01678         glGetIntegerv(GL_VIEWPORT, &v[0]);
    01679         glMatrixMode(GL_MODELVIEW);
    01680         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
    01681         glMatrixMode(GL_PROJECTION);
    01682         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
    01683
    01684         while (vid) {
    01685             BITMAP *mem_texture;
    01686
    01687             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
    01688
    01689             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
    01690             glMatrixMode(GL_PROJECTION);
    01691             glLoadIdentity();
    01692             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
    01693             glMatrixMode(GL_MODELVIEW);
    01694
    01695             allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx);
    01696
    01697             if (is_video_bitmap(texture)) {
    01698                 AGL_VIDEO_BITMAP *vbmp = texture->extra;
    01699                 mem_texture = vbmp->memory_copy;
    01700             }
    01701             else {
    01702                 mem_texture = texture;
    01703             }
    01704             polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx);
    01705
    01706             vid = vid->next;
    01707         }
    01708
    01709         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    01710
    01711         glViewport(v[0], v[1], v[2], v[3]);
    01712         glMatrixMode(GL_PROJECTION);
    01713         glLoadMatrixd(allegro_gl_projection_matrix);
    01714         glMatrixMode(GL_MODELVIEW);
    01715         glLoadMatrixd(allegro_gl_modelview_matrix);
    01716     }
    01717     else {
    01718         int i;
    01719         AGL_VIDEO_BITMAP *vid;
    01720
    01721         vid = bmp->extra;
    01722
    01723         if (is_sub_bitmap(bmp)) {
    01724             for (i = 0; i < vc; ++i) {
    01725                 vtx[i]->x += bmp->x_ofs;
    01726                 vtx[i]->y += bmp->y_ofs;
    01727             }
    01728         }
    01729
    01730         while (vid) {
    01731             BITMAP *mem_texture;
    01732             int _y1, _y2, _x1, _x2;
    01733             BITMAP *vbmp = vid->memory_copy;
    01734
    01735             _x1 = 9999;
    01736             for (i = 0; i < vc; ++i)
    01737                 if (vtx[i]->x < _x1) _x1 = vtx[i]->x;
    01738
    01739             _x2 = -9999;
    01740             for (i = 0; i < vc; ++i)
    01741                 if (vtx[i]->x > _x2) _x2 = vtx[i]->x;
    01742
    01743             _y1 = 9999;
    01744             for (i = 0; i < vc; ++i)
    01745                 if (vtx[i]->y < _y1) _y1 = vtx[i]->y;
    01746
    01747             _y2 = -9999;
    01748             for (i = 0; i < vc; ++i)
    01749                 if (vtx[i]->y > _y2) _y2 = vtx[i]->y;
    01750
    01751             if (vid->x_ofs > _x2 || vid->y_ofs > _y2
    01752              || vid->x_ofs + vbmp->w <= _x1
    01753              || vid->y_ofs + vbmp->h <= _y1) {
    01754
    01755                 vid = vid->next;
    01756                 continue;
    01757             }
    01758
    01759             _x1 = MAX(0, _x1 - vid->x_ofs);
    01760             _x2 = (_x2 - (vid->x_ofs + vbmp->w) > 0) ? vbmp->w - 1: _x2 - vid->x_ofs;
    01761             _y1 = MAX(0, _y1 - vid->y_ofs);
    01762             _y2 = (_x2 - (vid->y_ofs + vbmp->h) > 0) ? vbmp->h - 1: _y2 - vid->y_ofs;
    01763
    01764             if (is_video_bitmap(texture)) {
    01765                 AGL_VIDEO_BITMAP *tex = texture->extra;
    01766                 mem_texture = tex->memory_copy;
    01767             }
    01768             else {
    01769                 mem_texture = texture;
    01770             }
    01771             polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx);
    01772
    01773             update_texture_memory(vid, _x1, _y1, _x2, _y2);
    01774
    01775             vid = vid->next;
    01776         }
    01777     }
    01778
    01779     return;
    01780 }
    01781
    01782
    01783
    01784 static void allegro_gl_video_polygon3d(BITMAP *bmp, int type, BITMAP *texture,
    01785                                 int vc, V3D *vtx[])
    01786 {
    01787     int i;
    01788     V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
    01789     if (!vtx_f)
    01790         return;
    01791
    01792     for (i = 0; i < vc; i++) {
    01793         vtx_f[i] = malloc(sizeof(struct V3D_f));
    01794         if (!vtx_f[i]) {
    01795             int k;
    01796             for (k = 0; k < i; k++)
    01797                 free(vtx_f[k]);
    01798             free(vtx_f);
    01799             return;
    01800         }
    01801         vtx_f[i]->c = vtx[i]->c;
    01802         vtx_f[i]->u = fixtof(vtx[i]->u);
    01803         vtx_f[i]->v = fixtof(vtx[i]->v);
    01804         vtx_f[i]->x = fixtof(vtx[i]->x);
    01805         vtx_f[i]->y = fixtof(vtx[i]->y);
    01806         vtx_f[i]->z = fixtof(vtx[i]->z);
    01807     }
    01808
    01809     allegro_gl_video_polygon3d_f(bmp, type, texture, vc, vtx_f);
    01810
    01811     for (i = 0; i < vc; i++)
    01812         free(vtx_f[i]);
    01813     free(vtx_f);
    01814 }
    01815
    01816
    01817
    01818 static void allegro_gl_video_triangle3d(BITMAP *bmp, int type, BITMAP *texture,
    01819                                         V3D *v1, V3D *v2, V3D *v3)
    01820 {
    01821     V3D *vtx[3];
    01822     vtx[0] = v1;
    01823     vtx[1] = v2;
    01824     vtx[2] = v3;
    01825
    01826     allegro_gl_video_polygon3d(bmp, type, texture, 3, vtx);
    01827 }
    01828
    01829
    01830
    01831 static void allegro_gl_video_triangle3d_f(BITMAP *bmp, int type, BITMAP *texture,
    01832                                           V3D_f *v1, V3D_f *v2, V3D_f *v3)
    01833 {
    01834     V3D_f *vtx_f[3];
    01835     vtx_f[0] = v1;
    01836     vtx_f[1] = v2;
    01837     vtx_f[2] = v3;
    01838
    01839     allegro_gl_video_polygon3d_f(bmp, type, texture, 3, vtx_f);
    01840 }
    01841
    01842
    01843
    01844 static void allegro_gl_video_quad3d(BITMAP *bmp, int type, BITMAP *texture,
    01845                                     V3D *v1, V3D *v2, V3D *v3, V3D *v4)
    01846 {
    01847     V3D *vtx[4];
    01848     vtx[0] = v1;
    01849     vtx[1] = v2;
    01850     vtx[2] = v3;
    01851     vtx[3] = v4;
    01852
    01853     allegro_gl_video_polygon3d(bmp, type, texture, 4, vtx);
    01854 }
    01855
    01856
    01857
    01858 static void allegro_gl_video_quad3d_f(BITMAP *bmp, int type, BITMAP *texture,
    01859                                V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
    01860 {
    01861     V3D_f *vtx_f[4];
    01862     vtx_f[0] = v1;
    01863     vtx_f[1] = v2;
    01864     vtx_f[2] = v3;
    01865     vtx_f[3] = v4;
    01866
    01867     allegro_gl_video_polygon3d_f(bmp, type, texture, 4, vtx_f);
    01868 }
    01869
    01870
    01871
    01872 static void dummy_unwrite_bank(void)
    01873 {
    01874 }
    01875
    01876
    01877
    01878 static GFX_VTABLE allegro_gl_video_vtable = {
    01879     0,
    01880     0,
    01881     dummy_unwrite_bank,         //void *unwrite_bank;  /* C function on some machines, asm on i386 */
    01882     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
    01883     allegro_gl_video_acquire,
    01884     allegro_gl_video_release,
    01885     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
    01886     allegro_gl_created_sub_bitmap,
    01887     allegro_gl_video_getpixel,
    01888     allegro_gl_video_putpixel,
    01889     allegro_gl_video_vline,
    01890     allegro_gl_video_hline,
    01891     allegro_gl_video_hline,
    01892     allegro_gl_video_line,
    01893     allegro_gl_video_line,
    01894     allegro_gl_video_rectfill,
    01895     allegro_gl_video_triangle,
    01896     allegro_gl_video_draw_sprite,
    01897     allegro_gl_video_draw_256_sprite,
    01898     allegro_gl_video_draw_sprite_v_flip,
    01899     allegro_gl_video_draw_sprite_h_flip,
    01900     allegro_gl_video_draw_sprite_vh_flip,
    01901     allegro_gl_video_draw_trans_rgba_sprite,
    01902     allegro_gl_video_draw_trans_rgba_sprite,
    01903     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
    01904     NULL,                       //AL_METHOD(void, allegro_gl_video_draw_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
    01905     NULL,                       //AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
    01906     NULL,                       //AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
    01907     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
    01908     allegro_gl_video_draw_character,
    01909     allegro_gl_video_draw_glyph,
    01910     allegro_gl_video_blit_from_memory,
    01911     allegro_gl_video_blit_to_memory,
    01912     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));
    01913     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));
    01914     allegro_gl_screen_blit_to_self, /* Video bitmaps use same method as screen */
    01915     allegro_gl_screen_blit_to_self, /* ..._forward */
    01916     allegro_gl_screen_blit_to_self, /* ..._backward */
    01917     allegro_gl_memory_blit_between_formats,
    01918     allegro_gl_video_masked_blit,
    01919     allegro_gl_video_clear_to_color,
    01920     allegro_gl_video_pivot_scaled_sprite_flip,
    01921     allegro_gl_video_do_stretch_blit,
    01922     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));
    01923     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
    01924     NULL,                       //AL_METHOD(void, blit_end, (void));
    01925     _soft_polygon,              //AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color));
    01926     _soft_rect,                 //AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color));
    01927     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
    01928     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
    01929     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
    01930     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
    01931     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
    01932     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
    01933     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
    01934     allegro_gl_video_polygon3d,
    01935     allegro_gl_video_polygon3d_f,
    01936     allegro_gl_video_triangle3d,
    01937     allegro_gl_video_triangle3d_f,
    01938     allegro_gl_video_quad3d,
    01939     allegro_gl_video_quad3d_f,
    01940     allegro_gl_video_draw_sprite_ex
    01941 };
    01942