00001
00002
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
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
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
00076
00077 (*pvid)->width = w;
00078 (*pvid)->height = h;
00079 (*pvid)->x_ofs = x;
00080 (*pvid)->y_ofs = y;
00081
00082
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
00094 glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00095 glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00096
00097
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
00146
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
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
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
00196 if (!w2 && !h2) {
00197 return -1;
00198 }
00199
00200
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
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
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
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
00243
00244
00245
00246
00247 static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) {
00248
00249
00250 void *ptr = &bmp->extra;
00251 AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)ptr;
00252
00253
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
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
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
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
00334
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
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
00397 static void allegro_gl_video_acquire(struct BITMAP *bmp) {}
00398
00399
00400
00401
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
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
00814
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
00907
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,
01009 NULL,
01010 allegro_gl_video_acquire,
01011 allegro_gl_video_release,
01012 NULL,
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,
01024 NULL,
01025 NULL,
01026 NULL,
01027 NULL,
01028 NULL,
01029 NULL,
01030 NULL,
01031 NULL,
01032 NULL,
01033 NULL,
01034 NULL,
01035 NULL,
01036 NULL,
01037 allegro_gl_video_blit_from_memory,
01038 allegro_gl_video_blit_to_memory,
01039 NULL,
01040 NULL,
01041 allegro_gl_screen_blit_to_self,
01042 allegro_gl_screen_blit_to_self,
01043 allegro_gl_screen_blit_to_self,
01044 allegro_gl_memory_blit_between_formats,
01045 NULL,
01046 allegro_gl_video_clear_to_color,
01047 NULL,
01048 NULL,
01049 NULL,
01050 NULL,
01051 NULL,
01052 _soft_polygon,
01053 _soft_rect,
01054 _soft_circle,
01055 _soft_circlefill,
01056 _soft_ellipse,
01057 _soft_ellipsefill,
01058 _soft_arc,
01059 _soft_spline,
01060 _soft_floodfill,
01061 _soft_polygon3d,
01062 _soft_polygon3d_f,
01063 _soft_triangle3d,
01064 _soft_triangle3d_f,
01065 _soft_quad3d,
01066 _soft_quad3d_f,
01067 };
01068