videovtb.c

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

Generated on Mon Apr 3 18:20:13 2006 for AllegroGL by  doxygen 1.4.6