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  */
00012 #include <string.h>
00013 #include <limits.h>
00014 
00015 #include <allegro.h>
00016 
00017 #ifdef ALLEGRO_WINDOWS
00018 #include <winalleg.h>
00019 #endif
00020 
00021 #include "alleggl.h"
00022 #include "allglint.h"
00023 #include "glvtable.h"
00024 #include <allegro/internal/aintern.h>
00025 #ifdef ALLEGRO_MACOSX
00026 #include <OpenGL/glu.h>
00027 #else
00028 #include <GL/glu.h>
00029 #endif
00030 
00031 
00032 static GFX_VTABLE allegro_gl_video_vtable;
00033 
00034 /* Counter for video bitmaps. screen = 1 */
00035 static int video_bitmap_count = 2;
00036 
00037 static int __allegro_gl_video_bitmap_bpp = -1;
00038 
00039 
00040 void allegro_gl_destroy_video_bitmap(BITMAP *bmp);
00041 
00042 
00043 
00044 static int allegro_gl_make_video_bitmap_helper1(int w, int h, int x, int y,
00045                                    GLint target, AGL_VIDEO_BITMAP **pvid) {
00046 
00047     int internal_format;
00048     int bpp;
00049    
00050     if (__allegro_gl_video_bitmap_bpp == -1) {
00051         bpp = bitmap_color_depth(screen);
00052     }
00053     else {
00054         bpp = __allegro_gl_video_bitmap_bpp;
00055     }
00056 
00057     (*pvid) = malloc(sizeof(AGL_VIDEO_BITMAP));
00058             
00059     if (!(*pvid))
00060         return -1;
00061                 
00062     memset(*pvid, 0, sizeof(AGL_VIDEO_BITMAP));
00063         
00064     /* Create associated bitmap */
00065     (*pvid)->memory_copy = create_bitmap_ex(bpp, w, h);
00066     if (!(*pvid)->memory_copy)
00067         return -1;
00068     
00069     (*pvid)->format = __allegro_gl_get_bitmap_color_format((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
00070     (*pvid)->type = __allegro_gl_get_bitmap_type((*pvid)->memory_copy, 0);
00071     internal_format = __allegro_gl_get_texture_format_ex((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
00072 
00073     (*pvid)->target = target;
00074 
00075     /* Fill in some values in the bitmap to make it act as a subbitmap
00076      */
00077     (*pvid)->width  = w;
00078     (*pvid)->height = h;
00079     (*pvid)->x_ofs = x;
00080     (*pvid)->y_ofs = y;
00081 
00082     /* Make a texture out of it */
00083     glGenTextures(1, &((*pvid)->tex));
00084     if (!((*pvid)->tex))
00085         return -1;
00086 
00087     glEnable((*pvid)->target);
00088     glBindTexture((*pvid)->target, ((*pvid)->tex));
00089 
00090     glTexImage2D((*pvid)->target, 0, internal_format, w, h,
00091                  0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00092 
00093     /* By default, use the Allegro filtering mode - ie: Nearest */
00094     glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00095     glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00096 
00097     /* Clamp to edge */
00098     {   GLenum clamp = GL_CLAMP_TO_EDGE;
00099         if (!allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
00100             clamp = GL_CLAMP;
00101         }
00102         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_S, clamp);
00103         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_T, clamp);
00104     }
00105     glDisable((*pvid)->target);
00106 
00107     return 0;
00108 }
00109 
00110 
00111 
00112 static int allegro_gl_make_video_bitmap_helper0(int w, int h, int x, int y,
00113                                                 AGL_VIDEO_BITMAP **pvid) {
00114         
00115     int is_power_of_2 = (!(w & (w - 1)) && !(h & (h - 1)));
00116     int texture_rect_available = allegro_gl_extensions_GL.ARB_texture_rectangle
00117 #ifdef ALLEGRO_MACOSX
00118                              || allegro_gl_extensions_GL.EXT_texture_rectangle
00119 #endif
00120                              || allegro_gl_extensions_GL.NV_texture_rectangle;
00121     GLint max_rect_texture_size = 0;
00122 
00123     if (texture_rect_available) {
00124         glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_rect_texture_size);
00125     }
00126 
00127     if (w <= allegro_gl_info.max_texture_size &&
00128         h <= allegro_gl_info.max_texture_size) {
00129         if (allegro_gl_extensions_GL.ARB_texture_non_power_of_two ||
00130             is_power_of_2) {
00131             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
00132                                             GL_TEXTURE_2D, pvid)) {
00133                 return -1;
00134             }
00135         }
00136         else if (texture_rect_available &&
00137                  w <= max_rect_texture_size &&
00138                  h <= max_rect_texture_size) {
00139             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
00140                                             GL_TEXTURE_RECTANGLE_ARB, pvid)) {
00141                 return -1;
00142             }
00143         }
00144         else {
00145             /* NPO2 textures are not suppored by the driver in any way.
00146              * Split the bitmap into smaller POT bitmaps. */
00147             const unsigned int BITS = sizeof(int) * CHAR_BIT;
00148             unsigned int i, j;
00149             unsigned int w1, h1;
00150             unsigned int x1, y1;
00151             unsigned int p1, p2;
00152 
00153             /* Find the POTs using bits. */
00154             y1 = 0;
00155             for (i = 0; i < BITS; i++) {
00156                 p1 = 1 << i;
00157                 if (h & p1)
00158                     h1 = p1;
00159                 else
00160                     continue;
00161 
00162                 x1 = 0;
00163                 for (j = 0; j < BITS; j++) {
00164                     p2 = 1 << j;
00165                     if (w & p2)
00166                         w1 = p2;
00167                     else
00168                         continue;
00169 
00170                     if (allegro_gl_make_video_bitmap_helper0(w1, h1, x + x1,
00171                                                         y + y1, pvid)) {
00172                         return -1;
00173                     }
00174                     do {
00175                         pvid = &((*pvid)->next);
00176                     } while (*pvid);
00177 
00178                     x1 += w1;
00179                 }
00180 
00181                 y1 += h1;
00182             }
00183         }
00184     }
00185     else {
00186         /* Texture is too big to fit. Split it in 4 and try again. */
00187         int w1, w2, h1, h2;
00188 
00189         w2 = w / 2;
00190         w1 = w - w2;
00191 
00192         h2 = h / 2;
00193         h1 = h - h2;
00194 
00195         /* Even a 1x1 texture didn't work? Bail*/
00196         if (!w2 && !h2) {
00197             return -1;
00198         }
00199 
00200         /* Top-left corner */
00201         if (allegro_gl_make_video_bitmap_helper0(w1, h1, x, y, pvid)) {
00202             return -1;
00203         }
00204         do {
00205             pvid = &((*pvid)->next);
00206         } while (*pvid);
00207 
00208         /* Top-right corner */
00209         if (w2) {
00210             if (allegro_gl_make_video_bitmap_helper0(w2, h1, x + w1, y, pvid)) {
00211                 return -1;
00212             }
00213             do {
00214                 pvid = &((*pvid)->next);
00215             } while (*pvid);
00216         }
00217         /* Bottom-left corner */
00218         if (h2) {
00219             if (allegro_gl_make_video_bitmap_helper0(w1, h2, x, y + h1, pvid)) {
00220                 return -1;
00221             }
00222             do {
00223                 pvid = &((*pvid)->next);
00224             } while (*pvid);
00225         }
00226         /* Bottom-right corner */
00227         if (w2 && h2) {
00228             if (allegro_gl_make_video_bitmap_helper0(w2, h2, x + w1, y + h1, pvid)) {
00229                 return -1;
00230             }
00231             do {
00232                 pvid = &((*pvid)->next);
00233             } while (*pvid);
00234         }
00235     }
00236 
00237     return 0;
00238 }
00239 
00240 
00241 
00242 /* Will make a (potentially piece-wise) texture out of the specified bitmap
00243  * Source -must- be a memory bitmap or memory subbitmap (created by Allegro
00244  * only).
00245  *
00246  */
00247 static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) {
00248     
00249     /* Grab a pointer to the bitmap data to patch */
00250     void *ptr = &bmp->extra;
00251     AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)ptr;
00252     
00253     /* Convert bitmap to texture */
00254     if (allegro_gl_make_video_bitmap_helper0(bmp->w, bmp->h, 0, 0, pvid)) {
00255         goto agl_error;
00256     }
00257 
00258     return bmp;
00259     
00260 agl_error:
00261     allegro_gl_destroy_video_bitmap(bmp);
00262     return NULL;
00263 }
00264 
00265 
00266 
00267 /* void allegro_gl_destroy_video_bitmap(BITMAP *bmp) */
00272 void allegro_gl_destroy_video_bitmap(BITMAP *bmp) {
00273 
00274     AGL_VIDEO_BITMAP *vid = bmp ? bmp->extra : NULL, *next;
00275     
00276     if (!bmp)
00277         return;
00278     
00279     while (vid) {
00280         if (vid->memory_copy)
00281             destroy_bitmap(vid->memory_copy);
00282                 
00283         if (vid->tex)
00284             glDeleteTextures(1, &vid->tex);
00285                                 
00286         next = vid->next;
00287         free(vid);
00288         vid = next;
00289     }
00290 
00291     free(bmp->vtable);
00292     free(bmp);
00293     
00294     return;
00295 }
00296 
00297 
00298 
00299 /* BITMAP *allegro_gl_create_video_bitmap(int w, int h) */
00305 BITMAP *allegro_gl_create_video_bitmap(int w, int h) {
00306     GFX_VTABLE *vtable;
00307     BITMAP *bitmap;
00308 
00309     bitmap = malloc(sizeof(BITMAP) + sizeof(char *));
00310     
00311     if (!bitmap)
00312         return NULL;
00313 
00314     bitmap->dat = NULL;
00315     bitmap->w = bitmap->cr = w;
00316     bitmap->h = bitmap->cb = h;
00317     bitmap->clip = TRUE;
00318     bitmap->cl = bitmap->ct = 0;
00319     bitmap->write_bank = bitmap->read_bank = NULL;
00320     /* We should keep tracks of allocated bitmaps for the ref counter */
00321     bitmap->id = BMP_ID_VIDEO | video_bitmap_count;
00322     bitmap->extra = NULL;
00323     bitmap->x_ofs = 0;
00324     bitmap->y_ofs = 0;
00325     bitmap->seg = _default_ds();
00326     bitmap->line[0] = NULL;
00327 
00328     if (!allegro_gl_make_video_bitmap(bitmap)) {
00329         return NULL;
00330     }
00331     video_bitmap_count++;
00332     
00333     /* XXX <rohannessian> We ought to leave the Allegro values intact
00334      * Avoids bad interaction with correct Allegro programs.
00335      */
00336     vtable = malloc(sizeof(struct GFX_VTABLE));
00337     *vtable = allegro_gl_video_vtable;
00338     if (__allegro_gl_video_bitmap_bpp == -1) {
00339         vtable->color_depth = bitmap_color_depth(screen);
00340     }
00341     else {
00342         vtable->color_depth = __allegro_gl_video_bitmap_bpp;
00343     }
00344     switch (vtable->color_depth) {
00345         case 8:
00346             vtable->mask_color = MASK_COLOR_8;
00347         break;
00348         case 15:
00349             vtable->mask_color = MASK_COLOR_15;
00350         break;
00351         case 16:
00352             vtable->mask_color = MASK_COLOR_16;
00353         break;
00354         case 24:
00355             vtable->mask_color = MASK_COLOR_24;
00356         break;
00357         case 32:
00358             vtable->mask_color = MASK_COLOR_32;
00359         break;
00360     }
00361     bitmap->vtable = vtable;
00362 
00363     return bitmap;
00364 }
00365 
00366 
00367 
00368 /* allegro_gl_set_video_bitmap_color_depth(int bpp) */
00383 GLint allegro_gl_set_video_bitmap_color_depth(int bpp) {
00384     GLint old_val = __allegro_gl_video_bitmap_bpp;
00385     __allegro_gl_video_bitmap_bpp = bpp;
00386     return old_val;
00387 }
00388 
00389 
00390 /* static void allegro_gl_video_acquire(struct BITMAP *bmp) */
00397 static void allegro_gl_video_acquire(struct BITMAP *bmp) {}
00398 
00399 
00400 
00401 /* static void allegro_gl_video_release(struct BITMAP *bmp) */
00408 static void allegro_gl_video_release(struct BITMAP *bmp) {}
00409 
00410 
00411 
00412 static int allegro_gl_video_getpixel(struct BITMAP *bmp, int x, int y)
00413 {
00414     int pix = -1;
00415     AGL_VIDEO_BITMAP *vid;
00416     AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");  
00417     
00418     if (is_sub_bitmap(bmp)) {
00419         x += bmp->x_ofs;
00420         y += bmp->y_ofs;
00421     }
00422     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
00423         return -1;
00424     }
00425 
00426     vid = bmp->extra;
00427     
00428     while (vid) {
00429         if (vid->x_ofs <= x && vid->y_ofs <= y
00430          && vid->x_ofs + vid->memory_copy->w > x
00431          && vid->y_ofs + vid->memory_copy->h > y) {
00432             
00433             pix = getpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs);
00434             break;
00435         }
00436         vid = vid->next;
00437     }
00438     
00439     if (pix != -1) {
00440         return pix;
00441     }
00442     
00443     return -1;
00444 }
00445 
00446 
00447 
00448 static void allegro_gl_video_putpixel(struct BITMAP *bmp, int x, int y,
00449                                       int color) {
00450     AGL_VIDEO_BITMAP *vid;
00451 
00452     if (is_sub_bitmap(bmp)) {
00453         x += bmp->x_ofs;
00454         y += bmp->y_ofs;
00455     }
00456     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
00457         return;
00458     }
00459 
00460     vid = bmp->extra;
00461 
00462     while (vid) {
00463         if (vid->x_ofs <= x && vid->y_ofs <= y
00464          && vid->x_ofs + vid->memory_copy->w > x
00465          && vid->y_ofs + vid->memory_copy->h > y) {
00466             
00467             putpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs, color);
00468             
00469             glEnable(vid->target);
00470             glBindTexture(vid->target, vid->tex);
00471             glTexSubImage2D(vid->target, 0, x - vid->x_ofs,
00472                 y - vid->y_ofs, 1, 1, vid->format, vid->type, &color);
00473             glBindTexture(vid->target, 0);
00474             glDisable(vid->target);
00475                 
00476             break;
00477         }
00478         vid = vid->next;
00479     }
00480     
00481     return;
00482 }
00483 
00484 
00485 
00486 static void allegro_gl_video_vline(BITMAP *bmp, int x, int y1, int y2,
00487                                    int color) {
00488 
00489     AGL_VIDEO_BITMAP *vid;
00490     GLint saved_row_length;
00491     GLint saved_alignment;
00492     int bpp;
00493     
00494     AGL_LOG(2, "glvtable.c:allegro_gl_video_vline\n");
00495     vid = bmp->extra;
00496     
00497     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00498     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00499     
00500     if (is_sub_bitmap(bmp)) {
00501         x  += bmp->x_ofs;
00502         y1 += bmp->y_ofs;
00503         y2 += bmp->y_ofs;
00504     }
00505     if (x < bmp->cl || x >= bmp->cr) {
00506         return;
00507     }
00508     
00509     if (y1 > y2) {
00510         int temp = y1;
00511         y1 = y2;
00512         y2 = temp;
00513     }
00514 
00515     if (y1 < bmp->ct) {
00516         y1 = bmp->ct;
00517     }
00518     if (y2 >= bmp->cb) {
00519         y2 = bmp->cb - 1;
00520     }
00521 
00522     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00523     
00524     while (vid) {
00525         BITMAP *vbmp = vid->memory_copy;
00526         
00527         int _y1, _y2, _x;
00528         if (vid->x_ofs > x || vid->y_ofs > y2
00529          || vid->x_ofs + vbmp->w <= x
00530          || vid->y_ofs + vbmp->h <= y1) {
00531             
00532             vid = vid->next;
00533             continue;
00534         }
00535         
00536         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
00537         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
00538         _x = x - vid->x_ofs;
00539 
00540         vline(vbmp, _x, _y1, _y2, color);
00541 
00542         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00543         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00544                       vbmp->h > 1
00545                      ? (vbmp->line[1] - vbmp->line[0]) / bpp
00546                      : vbmp->w);
00547 
00548         glEnable(vid->target);
00549         glBindTexture(vid->target, vid->tex);
00550         glTexSubImage2D(vid->target, 0, _x, _y1, 1, _y2 - _y1 + 1, vid->format,
00551             vid->type, vbmp->line[_y1] + _x * bpp);
00552         glBindTexture(vid->target, 0);
00553         glDisable(vid->target);
00554 
00555         vid = vid->next;
00556     }
00557     
00558     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00559     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00560     
00561     return;
00562 }
00563 
00564 
00565 
00566 static void allegro_gl_video_hline(BITMAP *bmp, int x1, int y, int x2,
00567                                    int color) {
00568 
00569     AGL_VIDEO_BITMAP *vid;
00570     GLint saved_row_length;
00571     GLint saved_alignment;
00572     int bpp;
00573     
00574     AGL_LOG(2, "glvtable.c:allegro_gl_video_hline\n");
00575     vid = bmp->extra;
00576     
00577     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00578     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00579 
00580     if (is_sub_bitmap(bmp)) {
00581         x1 += bmp->x_ofs;
00582         x2 += bmp->x_ofs;
00583         y  += bmp->y_ofs;
00584     }
00585 
00586     if (y < bmp->ct || y >= bmp->cb) {
00587         return;
00588     }
00589     
00590     if (x1 > x2) {
00591         int temp = x1;
00592         x1 = x2;
00593         x2 = temp;
00594     }
00595 
00596     if (x1 < bmp->cl) {
00597         x1 = bmp->cl;
00598     }
00599     if (x2 >= bmp->cr) {
00600         x2 = bmp->cr - 1;
00601     }
00602 
00603     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00604 
00605     while (vid) {
00606         BITMAP *vbmp = vid->memory_copy;
00607         
00608         int _x1, _x2, _y;
00609         if (vid->y_ofs > y || vid->x_ofs > x2
00610          || vid->x_ofs + vbmp->w <= x1
00611          || vid->y_ofs + vbmp->h <= y) {
00612             
00613             vid = vid->next;
00614             continue;
00615         }
00616         
00617         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
00618         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
00619         _y = y - vid->y_ofs;
00620 
00621         hline(vbmp, _x1, _y, _x2, color);
00622     
00623         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00624         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00625                       vbmp->h > 1
00626                      ? (vbmp->line[1] - vbmp->line[0]) / bpp
00627                      : vbmp->w);
00628         
00629         glEnable(vid->target);
00630         glBindTexture(vid->target, vid->tex);
00631         glTexSubImage2D(vid->target, 0, _x1, _y, _x2 - _x1 + 1, 1, vid->format,
00632             vid->type, vbmp->line[_y] + _x1 * bpp);
00633         glBindTexture(vid->target, 0);
00634         glDisable(vid->target);
00635 
00636         vid = vid->next;
00637     }
00638     
00639     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00640     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00641     
00642     return;
00643 }
00644 
00645 
00646 
00647 static void allegro_gl_video_line(struct BITMAP *bmp, int x1, int y1, int x2,
00648                                   int y2, int color) {
00649     
00650     /* Note: very very slow */                      
00651     do_line(bmp, x1, y1, x2, y2, color, allegro_gl_video_putpixel);
00652     
00653     return;
00654 }
00655     
00656 
00657 
00658 static void allegro_gl_video_rectfill(struct BITMAP *bmp, int x1, int y1,
00659                                       int x2, int y2, int color) {
00660 
00661     AGL_VIDEO_BITMAP *vid;
00662     GLint saved_row_length;
00663     GLint saved_alignment;
00664     int bpp;
00665     
00666     AGL_LOG(2, "glvtable.c:allegro_gl_video_rectfill\n");
00667     vid = bmp->extra;
00668     
00669     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00670     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00671     
00672     if (is_sub_bitmap(bmp)) {
00673         x1 += bmp->x_ofs;
00674         x2 += bmp->x_ofs;
00675         y1 += bmp->y_ofs;
00676         y2 += bmp->y_ofs;
00677     }
00678     
00679     if (y1 > y2) {
00680         int temp = y1;
00681         y1 = y2;
00682         y2 = temp;
00683     }
00684 
00685     if (x1 > x2) {
00686         int temp = x1;
00687         x1 = x2;
00688         x2 = temp;
00689     }
00690 
00691     if (x1 < bmp->cl) {
00692         x1 = bmp->cl;
00693     }
00694     if (x2 >= bmp->cr) {
00695         x2 = bmp->cr - 1;
00696     }
00697     if (y1 < bmp->ct) {
00698         y1 = bmp->ct;
00699     }
00700     if (y1 >= bmp->cb) {
00701         y1 = bmp->cb - 1;
00702     }
00703 
00704     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00705 
00706     while (vid) {
00707         BITMAP *vbmp = vid->memory_copy;
00708         
00709         int _y1, _y2, _x1, _x2;
00710         if (vid->x_ofs > x2 || vid->y_ofs > y2
00711          || vid->x_ofs + vbmp->w <= x1
00712          || vid->y_ofs + vbmp->h <= y1) {
00713             
00714             vid = vid->next;
00715             continue;
00716         }
00717         
00718         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
00719         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
00720         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
00721         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
00722 
00723         rectfill(vbmp, _x1, _y1, _x2, _y2, color);
00724         
00725         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00726         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00727                       vbmp->h > 1
00728                      ? (vbmp->line[1] - vbmp->line[0]) / bpp
00729                      : vbmp->w);
00730 
00731         glEnable(vid->target);
00732         glBindTexture(vid->target, vid->tex);
00733         glTexSubImage2D(vid->target, 0,
00734             _x1, _y1, _x2 - _x1 + 1, _y2 - _y1 + 1, vid->format,
00735             vid->type, vbmp->line[_y1] + _x1 * bpp);
00736         glBindTexture(vid->target, 0);
00737         glDisable(vid->target);
00738 
00739         vid = vid->next;
00740     }
00741     
00742     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00743     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00744     
00745     return;
00746 }
00747 
00748 
00749 static void allegro_gl_video_triangle(struct BITMAP *bmp, int x1, int y1,
00750                                       int x2, int y2, int x3, int y3, int color)
00751 {   
00752     AGL_VIDEO_BITMAP *vid;
00753     GLint saved_row_length;
00754     GLint saved_alignment;
00755     int min_y, max_y, min_x, max_x;
00756     int bpp;
00757     
00758     AGL_LOG(2, "glvtable.c:allegro_gl_video_triangle\n");
00759     vid = bmp->extra;
00760     
00761     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00762     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00763 
00764     if (is_sub_bitmap(bmp)) {
00765         x1 += bmp->x_ofs;
00766         x2 += bmp->x_ofs;
00767         x3 += bmp->x_ofs;
00768         y1 += bmp->y_ofs;
00769         y2 += bmp->y_ofs;
00770         y3 += bmp->y_ofs;
00771     }
00772 
00773     min_y = MIN(y1, MIN(y2, y3));
00774     min_x = MIN(x1, MIN(x2, x3));
00775     max_y = MAX(y1, MAX(y2, y3));
00776     max_x = MAX(x1, MAX(x2, x3));
00777 
00778     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00779 
00780     while (vid) {
00781         BITMAP *vbmp = vid->memory_copy;
00782         
00783         int _y1, _y2, _x1, _x2, _x3, _y3;
00784         if (vid->x_ofs > max_x || vid->y_ofs > max_y
00785          || vid->x_ofs + vbmp->w <= min_x
00786          || vid->y_ofs + vbmp->h <= min_y) {
00787             
00788             vid = vid->next;
00789             continue;
00790         }
00791         
00792         _y1 = y1 - vid->y_ofs;
00793         _y2 = y2 - vid->y_ofs;
00794         _y3 = y3 - vid->y_ofs;
00795         _x1 = x1 - vid->x_ofs;
00796         _x2 = x2 - vid->x_ofs;
00797         _x3 = x3 - vid->x_ofs;
00798 
00799 
00800         set_clip_rect(vbmp, bmp->cl - vid->x_ofs, bmp->ct - vid->y_ofs,
00801                             bmp->cr - vid->x_ofs - 1, bmp->cb - vid->y_ofs - 1);
00802 
00803         triangle(vbmp, _x1, _y1, _x2, _y2, _x3, _y3, color);
00804 
00805         set_clip_rect(vbmp, 0, 0, vbmp->w - 1, vbmp->h - 1);
00806         
00807         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00808         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00809                       vbmp->h > 1
00810                      ? (vbmp->line[1] - vbmp->line[0]) / bpp
00811                      : vbmp->w);
00812         
00813         /* Not quite the minimal rectangle occupied by the triangle, but
00814          * pretty close
00815          */
00816         _y1 = MAX(0, min_y - vid->y_ofs);
00817         _y2 = MIN(vbmp->h - 1, max_y - vid->y_ofs);
00818         _x1 = MAX(0, min_x - vid->x_ofs);
00819         _x2 = MIN(vbmp->w - 1, max_x - vid->x_ofs);
00820             
00821         glEnable(vid->target);
00822         glBindTexture(vid->target, vid->tex);
00823         glTexSubImage2D(vid->target, 0,
00824             _x1, _y1, _x2 - _x1 + 1, _y2 - _y1 + 1, vid->format,
00825             vid->type, vbmp->line[_y1] + _x1 * bpp);
00826         glBindTexture(vid->target, 0);
00827         glDisable(vid->target);
00828 
00829         vid = vid->next;
00830     }
00831     
00832     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00833     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00834 }
00835 
00836 
00837 
00838 void allegro_gl_video_blit_from_memory(struct BITMAP *source,
00839                 struct BITMAP *dest, int source_x, int source_y,
00840                 int dest_x, int dest_y, int width, int height) {
00841 
00842     AGL_VIDEO_BITMAP *vid;
00843     BITMAP *dest_parent = dest;
00844     GLint saved_row_length;
00845     GLint saved_alignment;
00846     int bpp;
00847     GLenum format, type;
00848     
00849     AGL_LOG(2, "glvtable.c:allegro_gl_video_blit_from_memory\n");
00850 
00851     if (is_sub_bitmap (dest)) {
00852        dest_x += dest->x_ofs;
00853        dest_y += dest->y_ofs;
00854        while (dest_parent->id & BMP_ID_SUB)
00855           dest_parent = (BITMAP *)dest_parent->extra;
00856     }
00857 
00858     if (dest_x < dest->cl) {
00859         dest_x = dest->cl;
00860     }
00861     if (dest_y < dest->ct) {
00862         dest_y = dest->ct;
00863     }
00864     if (dest_x + width >= dest->cr) {
00865         width = dest->cr - dest_x;
00866     }
00867     if (dest_y + height >= dest->cb) {
00868         height = dest->cb - dest_y;
00869     }
00870     if (width < 1 || height < 1) {
00871         return;
00872     }
00873     
00874     vid = dest_parent->extra;
00875 
00876     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00877     format = vid->format;
00878     type = vid->type;
00879 
00880     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00881     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00882     
00883     while (vid) {
00884         BITMAP *temp = NULL;
00885         BITMAP *vbmp = vid->memory_copy;
00886 
00887         int _x, _y, _w, _h;
00888         if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height
00889          || vid->x_ofs + vbmp->w <= dest_x
00890          || vid->y_ofs + vbmp->h <= dest_y) {
00891             
00892             vid = vid->next;
00893             continue;
00894         }
00895 
00896         _x = MAX (vid->x_ofs, dest_x) - vid->x_ofs;
00897         _w = MIN (vid->x_ofs + vbmp->w, dest_x + width)
00898            - vid->x_ofs - _x;
00899         _y = MAX (vid->y_ofs, dest_y) - vid->y_ofs;
00900         _h = MIN (vid->y_ofs + vbmp->h, dest_y + height)
00901            - vid->y_ofs - _y;
00902 
00903         blit(source, vbmp, source_x + vid->x_ofs + _x - dest_x,
00904              source_y + vid->y_ofs + _y - dest_y, _x, _y, _w, _h);
00905 
00906         /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
00907          * the bitmap into something GL can understand - 24-bpp should do it.
00908          */
00909         if (!allegro_gl_extensions_GL.EXT_packed_pixels
00910                                         && bitmap_color_depth(source) < 24) {
00911             temp = create_bitmap_ex(24, vbmp->w, vbmp->h);
00912             if (!temp)
00913                 return;
00914 
00915             blit(vbmp, temp, 0, 0, 0, 0, temp->w, temp->h);
00916             vbmp = temp;
00917             bpp = BYTES_PER_PIXEL(bitmap_color_depth(vbmp));
00918             format = __allegro_gl_get_bitmap_color_format(vbmp, 0);
00919             type = __allegro_gl_get_bitmap_type(vbmp, 0);
00920         }
00921 
00922         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00923         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00924                       vbmp->h > 1
00925                      ? (vbmp->line[1] - vbmp->line[0]) / bpp
00926                      : vbmp->w);
00927 
00928         glEnable(vid->target);
00929         glBindTexture(vid->target, vid->tex);
00930         glTexSubImage2D(vid->target, 0, _x, _y, _w, _h,
00931             format, type, vbmp->line[_y] + _x * bpp);
00932         glBindTexture(vid->target, 0);
00933         glDisable(vid->target);
00934 
00935         if (temp)
00936             destroy_bitmap(vbmp);
00937             
00938         vid = vid->next;
00939     }
00940     
00941     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00942     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00943 
00944     return; 
00945 }
00946 
00947 
00948 
00949 void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest,
00950                          int source_x, int source_y, int dest_x, int dest_y,
00951                          int width, int height) {
00952 
00953     AGL_VIDEO_BITMAP *vid;
00954     BITMAP *source_parent = source;
00955     
00956     AGL_LOG(2, "glvtable.c:allegro_gl_video_blit_to_memory\n");
00957     
00958     if (is_sub_bitmap(source)) {
00959        source_x += source->x_ofs;
00960        source_y += source->y_ofs;
00961        while (source_parent->id & BMP_ID_SUB)
00962           source_parent = (BITMAP *)source_parent->extra;
00963     }
00964 
00965     vid = source_parent->extra;
00966     
00967     while (vid) {
00968         BITMAP *vbmp = vid->memory_copy;
00969         int x, y, dx, dy, w, h;
00970 
00971         x = MAX(source_x, vid->x_ofs) - vid->x_ofs;
00972         y = MAX(source_y, vid->y_ofs) - vid->y_ofs;
00973         w = MIN(vid->x_ofs + vbmp->w, source_x + width) - vid->x_ofs;
00974         h = MIN(vid->y_ofs + vbmp->h, source_y + height) - vid->y_ofs;
00975         dx = MAX(0, vid->x_ofs - source_x) + dest_x;
00976         dy = MAX(0, vid->y_ofs - source_y) + dest_y;
00977 
00978         blit(vbmp, dest, x, y, dx, dy, w, h);
00979     
00980         vid = vid->next;
00981     }
00982 
00983     return; 
00984 }
00985 
00986 
00987 
00988 static void allegro_gl_video_clear_to_color(BITMAP *bmp, int color) {
00989 
00990     AGL_LOG(2, "glvtable.c:allegro_gl_video_clear_to_color\n");
00991     
00992     allegro_gl_video_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
00993             
00994     return;
00995 }
00996 
00997 
00998 
00999 static void dummy_unwrite_bank(void)
01000 {
01001 }
01002 
01003 
01004 
01005 static GFX_VTABLE allegro_gl_video_vtable = {
01006     0,
01007     0,
01008     dummy_unwrite_bank,         //void *unwrite_bank;  /* C function on some machines, asm on i386 */
01009     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
01010     allegro_gl_video_acquire,
01011     allegro_gl_video_release,
01012     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
01013     allegro_gl_created_sub_bitmap,
01014     allegro_gl_video_getpixel,
01015     allegro_gl_video_putpixel,
01016     allegro_gl_video_vline,
01017     allegro_gl_video_hline,
01018     allegro_gl_video_hline,
01019     allegro_gl_video_line,
01020     allegro_gl_video_line,
01021     allegro_gl_video_rectfill,
01022     allegro_gl_video_triangle,
01023     NULL,/*allegro_gl_screen_draw_sprite,*/
01024     NULL,                       //AL_METHOD(void, draw_256_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y));
01025     NULL,/*allegro_gl_screen_draw_sprite_v_flip,*/
01026     NULL,/*allegro_gl_screen_draw_sprite_h_flip,*/
01027     NULL,/*allegro_gl_screen_draw_sprite_vh_flip,*/
01028     NULL,                       //AL_METHOD(void, draw_trans_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y));
01029     NULL,                       //AL_METHOD(void, draw_trans_rgba_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y));
01030     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
01031     NULL,                       //AL_METHOD(void, draw_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01032     NULL,                       //AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01033     NULL,                       //AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01034     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
01035     NULL,                       //AL_METHOD(void, draw_character, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
01036     NULL,/*allegro_gl_screen_draw_glyph,*/
01037     allegro_gl_video_blit_from_memory,
01038     allegro_gl_video_blit_to_memory,
01039     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));
01040     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));
01041     allegro_gl_screen_blit_to_self, /* Video bitmaps use same method as screen */
01042     allegro_gl_screen_blit_to_self, /* ..._forward */
01043     allegro_gl_screen_blit_to_self, /* ..._backward */
01044     allegro_gl_memory_blit_between_formats,
01045     NULL,                       //AL_METHOD(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
01046     allegro_gl_video_clear_to_color,
01047     NULL,                       //AL_METHOD(void, pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip));
01048     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));
01049     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));
01050     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
01051     NULL,                       //AL_METHOD(void, blit_end, (void));
01052     _soft_polygon,              //AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color));
01053     _soft_rect,                 //AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color));
01054     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
01055     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
01056     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
01057     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
01058     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
01059     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
01060     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
01061     _soft_polygon3d,            //AL_METHOD(void, polygon3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[]));
01062     _soft_polygon3d_f,          //AL_METHOD(void, polygon3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[]));
01063     _soft_triangle3d,           //AL_METHOD(void, triangle3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3));
01064     _soft_triangle3d_f,         //AL_METHOD(void, triangle3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3));
01065     _soft_quad3d,               //AL_METHOD(void, quad3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4));
01066     _soft_quad3d_f,             //AL_METHOD(void, quad3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4));
01067 };
01068 

Generated on Tue May 15 16:27:15 2007 for AllegroGL by  doxygen 1.4.7