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

Generated on Sun Dec 3 18:06:49 2006 for AllegroGL by  doxygen 1.5.1