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
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
00052 (*pvid)->memory_copy = create_bitmap_ex(32, w, h);
00053
00054 if (!(*pvid)->memory_copy)
00055 return -1;
00056
00057
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
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
00082 glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00083 glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00084
00085
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
00105
00106
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
00121
00122
00123 int wc, hc;
00124 w = w / 2;
00125 h = h / 2;
00126
00127
00128 if (!w && !h) {
00129 return -1;
00130 }
00131
00132 wc = w ? w : 1;
00133 hc = h ? h : 1;
00134
00135
00136 if (allegro_gl_make_video_bitmap_helper0(wc, hc, 0, 0, pvid)) {
00137 return -1;
00138 }
00139 pvid = &((*pvid)->next);
00140
00141
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
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
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
00165
00166
00167 return -1;
00168 }
00169 return 0;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) {
00181
00182
00183 AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)&bmp->extra;
00184
00185
00186 GLint old_bind;
00187 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_bind);
00188
00189
00190 if (allegro_gl_make_video_bitmap_helper0(bmp->w, bmp->h, 0, 0, pvid)) {
00191 goto agl_error;
00192 }
00193
00194
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
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
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
00243
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
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
00292 static void allegro_gl_video_acquire(struct BITMAP *bmp) {}
00293
00294
00295
00296
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
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
00704
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,
00860 NULL,
00861 allegro_gl_video_acquire,
00862 allegro_gl_video_release,
00863 NULL,
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,
00877 NULL,
00878 NULL,
00879 NULL,
00880 NULL,
00881 NULL,
00882 NULL,
00883 NULL,
00884 NULL,
00885 NULL,
00886 NULL,
00887 NULL,
00888 NULL,
00889 NULL,
00890 allegro_gl_video_blit_from_memory,
00891 allegro_gl_video_blit_to_memory,
00892 NULL,
00893 NULL,
00894 allegro_gl_screen_blit_to_self,
00895 allegro_gl_screen_blit_to_self,
00896 allegro_gl_screen_blit_to_self,
00897 allegro_gl_memory_blit_between_formats,
00898 NULL,
00899 allegro_gl_video_clear_to_color,
00900 NULL,
00901 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 1, 17)
00902 NULL,
00903 NULL,
00904 NULL,
00905 NULL,
00906 _soft_polygon,
00907 _soft_rect,
00908 _soft_circle,
00909 _soft_circlefill,
00910 _soft_ellipse,
00911 _soft_ellipsefill,
00912 _soft_arc,
00913 _soft_spline,
00914 _soft_floodfill,
00915 _soft_polygon3d,
00916 _soft_polygon3d_f,
00917 _soft_triangle3d,
00918 _soft_triangle3d_f,
00919 _soft_quad3d,
00920 _soft_quad3d_f,
00921 #else
00922 NULL,
00923 NULL
00924 #endif
00925 };
00926