00001
00002
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_screen_vtable;
00032 static GLuint __allegro_gl_pool_texture = 0;
00033
00034 static GLuint __allegro_gl_dummy_texture = 0;
00035
00036
00037 extern int __allegro_gl_blit_operation;
00038
00039
00040 #define H_FLIP 1
00041 #define V_FLIP 2
00042 #define REGULAR_BMP 1
00043
00044
00045 #define NO_ROTATION 2
00046
00047
00048
00049
00050
00059
00060
00061
00062 int __allegro_gl_make_power_of_2(int x) {
00063 x--;
00064 x |= (x >> 1);
00065 x |= (x >> 2);
00066 x |= (x >> 4);
00067 x |= (x >> 8);
00068 x |= (x >> 16);
00069 x++;
00070 return x;
00071 }
00072
00073
00074
00075 void __allegro_gl_set_drawing_mode(void) {
00076 switch (_drawing_mode) {
00077 case DRAW_MODE_SOLID:
00078 glDisable(GL_BLEND);
00079 glDisable(GL_COLOR_LOGIC_OP);
00080 break;
00081
00082 case DRAW_MODE_TRANS:
00083 glEnable(GL_BLEND);
00084 break;
00085
00086 case DRAW_MODE_XOR:
00087 glEnable(GL_COLOR_LOGIC_OP);
00088 glLogicOp(GL_XOR);
00089 break;
00090 }
00091 }
00092
00093
00094
00095 void __allegro_gl_unset_drawing_mode(void) {
00096 switch (_drawing_mode) {
00097 case DRAW_MODE_TRANS:
00098 glDisable(GL_BLEND);
00099 break;
00100
00101 case DRAW_MODE_XOR:
00102 glDisable(GL_LOGIC_OP);
00103 break;
00104 }
00105 }
00106
00107
00108
00109 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
00110 int color_depth)
00111 {
00112 AGL_LOG(2, "glvtable.c:split_color\n");
00113 *r = getr_depth(color_depth, color);
00114 *g = getg_depth(color_depth, color);
00115 *b = getb_depth(color_depth, color);
00116 if (color_depth == 32)
00117 *a = geta_depth(color_depth, color);
00118 else
00119 *a = 255;
00120 }
00121
00122
00123
00124
00125 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
00126 {
00127 bmp->extra = parent;
00128 }
00129
00130
00131
00137 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
00138
00139
00140
00141
00147 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
00148
00149
00150
00151 static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y)
00152 {
00153 GLubyte pixel[3];
00154 AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
00155 if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00156 || y < bmp->ct || y >= bmp->cb)) {
00157 return -1;
00158 }
00159 if (is_sub_bitmap(bmp)) {
00160 x += bmp->x_ofs;
00161 y += bmp->y_ofs;
00162 }
00163 glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
00164
00165 return makecol_depth(bitmap_color_depth(screen),
00166 pixel[0], pixel[1], pixel[2]);
00167 }
00168
00169
00170
00171 static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y,
00172 int color)
00173 {
00174 GLubyte r, g, b, a;
00175 AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n");
00176 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00177 if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00178 || y < bmp->ct || y >= bmp->cb)) {
00179 return;
00180 }
00181
00182 if (is_sub_bitmap(bmp)) {
00183 x += bmp->x_ofs;
00184 y += bmp->y_ofs;
00185 }
00186
00187 glColor4ub(r, g, b, a);
00188 __allegro_gl_set_drawing_mode();
00189 glBegin(GL_POINTS);
00190 glVertex2f(x, y);
00191 glEnd();
00192 __allegro_gl_unset_drawing_mode();
00193 }
00194
00195
00196
00197 static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2,
00198 int color)
00199 {
00200 GLubyte r, g, b, a;
00201 AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n");
00202
00203 if (y1 > y2) {
00204 int temp = y1;
00205 y1 = y2;
00206 y2 = temp;
00207 }
00208
00209 if (bmp->clip) {
00210 if ((x < bmp->cl) || (x >= bmp->cr)) {
00211 return;
00212 }
00213 if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
00214 return;
00215 }
00216 if (y1 < bmp->ct) {
00217 y1 = bmp->ct;
00218 }
00219 if (y2 >= bmp->cb) {
00220 y2 = bmp->cb - 1;
00221 }
00222 }
00223
00224 if (is_sub_bitmap(bmp)) {
00225 x += bmp->x_ofs;
00226 y1 += bmp->y_ofs;
00227 y2 += bmp->y_ofs;
00228 }
00229
00230 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00231
00232 glColor4ub(r, g, b, a);
00233 __allegro_gl_set_drawing_mode();
00234 glBegin(GL_LINES);
00235 glVertex2f(x, y1);
00236 glVertex2f(x, y2 + 0.325 * 3);
00237 glEnd();
00238 __allegro_gl_unset_drawing_mode();
00239
00240 return;
00241 }
00242
00243
00244
00245 static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2,
00246 int color)
00247 {
00248 GLubyte r, g, b, a;
00249 AGL_LOG(2, "glvtable.c:allegro_gl_hline\n");
00250
00251 if (x1 > x2) {
00252 int temp = x1;
00253 x1 = x2;
00254 x2 = temp;
00255 }
00256 if (bmp->clip) {
00257 if ((y < bmp->ct) || (y >= bmp->cb)) {
00258 return;
00259 }
00260 if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
00261 return;
00262 }
00263 if (x1 < bmp->cl) {
00264 x1 = bmp->cl;
00265 }
00266 if (x2 >= bmp->cr) {
00267 x2 = bmp->cr - 1;
00268 }
00269 }
00270 if (is_sub_bitmap(bmp)) {
00271 x1 += bmp->x_ofs;
00272 x2 += bmp->x_ofs;
00273 y += bmp->y_ofs;
00274 }
00275
00276 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00277
00278 glColor4ub(r, g, b, a);
00279 __allegro_gl_set_drawing_mode();
00280 glBegin(GL_LINES);
00281 glVertex2f(x1 - 0.325, y);
00282 glVertex2f(x2 + 0.325 * 2, y);
00283 glEnd();
00284 __allegro_gl_unset_drawing_mode();
00285
00286 return;
00287 }
00288
00289
00290
00291 static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2,
00292 int y2, int color)
00293 {
00294 GLubyte r, g, b, a;
00295 AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n");
00296
00297 if (bmp->clip) {
00298 glPushAttrib(GL_SCISSOR_BIT);
00299 glEnable(GL_SCISSOR_TEST);
00300 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
00301 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00302 }
00303 if (is_sub_bitmap(bmp)) {
00304 x1 += bmp->x_ofs;
00305 x2 += bmp->x_ofs;
00306 y1 += bmp->y_ofs;
00307 y2 += bmp->y_ofs;
00308 }
00309
00310 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00311
00312 glColor4ub(r, g, b, a);
00313 __allegro_gl_set_drawing_mode();
00314 glBegin(GL_LINES);
00315 glVertex2f(x1 + 0.1625, y1 + 0.1625);
00316 glVertex2f(x2 + 0.1625, y2 + 0.1625);
00317 glEnd();
00318
00319
00320 glBegin(GL_POINTS);
00321 glVertex2f(x2 + 0.1625, y2 + 0.1625);
00322 glEnd();
00323 __allegro_gl_unset_drawing_mode();
00324
00325 if (bmp->clip) {
00326 glPopAttrib();
00327 }
00328
00329 return;
00330 }
00331
00332
00333
00334 static void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1,
00335 int x2, int y2, int color)
00336 {
00337 GLubyte r, g, b, a;
00338 AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n");
00339
00340 if (x1 > x2) {
00341 int temp = x1;
00342 x1 = x2;
00343 x2 = temp;
00344 }
00345
00346 if (y1 > y2) {
00347 int temp = y1;
00348 y1 = y2;
00349 y2 = temp;
00350 }
00351
00352 if (bmp->clip) {
00353 if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
00354 return;
00355 }
00356 if (x1 < bmp->cl) {
00357 x1 = bmp->cl;
00358 }
00359 if (x2 >= bmp->cr) {
00360 x2 = bmp->cr - 1;
00361 }
00362 if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
00363 return;
00364 }
00365 if (y1 < bmp->ct) {
00366 y1 = bmp->ct;
00367 }
00368 if (y2 >= bmp->cb) {
00369 y2 = bmp->cb - 1;
00370 }
00371 }
00372 if (is_sub_bitmap(bmp)) {
00373 x1 += bmp->x_ofs;
00374 x2 += bmp->x_ofs;
00375 y1 += bmp->y_ofs;
00376 y2 += bmp->y_ofs;
00377 }
00378
00379 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00380 glColor4ub(r, g, b, a);
00381 __allegro_gl_set_drawing_mode();
00382 glRecti(x1, y2, x2, y1);
00383 __allegro_gl_unset_drawing_mode();
00384
00385 return;
00386 }
00387
00388
00389
00390 static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1,
00391 int x2, int y2, int x3, int y3, int color)
00392 {
00393 GLubyte r, g, b, a;
00394 AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n");
00395
00396 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00397
00398 if (bmp->clip) {
00399 glPushAttrib(GL_SCISSOR_BIT);
00400 glEnable(GL_SCISSOR_TEST);
00401 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
00402 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00403 }
00404 if (is_sub_bitmap(bmp)) {
00405 x1 += bmp->x_ofs;
00406 y1 += bmp->y_ofs;
00407 x2 += bmp->x_ofs;
00408 y2 += bmp->y_ofs;
00409 x3 += bmp->x_ofs;
00410 y3 += bmp->y_ofs;
00411 }
00412
00413 glColor4ub(r, g, b, a);
00414 __allegro_gl_set_drawing_mode();
00415 glBegin(GL_TRIANGLES);
00416 glVertex2f(x1, y1);
00417 glVertex2f(x2, y2);
00418 glVertex2f(x3, y3);
00419 glEnd();
00420 __allegro_gl_unset_drawing_mode();
00421
00422 if (bmp->clip) {
00423 glPopAttrib();
00424 }
00425 }
00426
00427
00428
00429 #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \
00430 width, height) { \
00431 if (dest->clip) { \
00432 if ((dest_x >= dest->cr) || (dest_y >= dest->cb) \
00433 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \
00434 width = 0; \
00435 } \
00436 if (dest_x < dest->cl) { \
00437 width += dest_x - dest->cl; \
00438 source_x -= dest_x - dest->cl; \
00439 dest_x = dest->cl; \
00440 } \
00441 if (dest_y < dest->ct) { \
00442 height += dest_y - dest->ct; \
00443 source_y -= dest_y - dest->ct; \
00444 dest_y = dest->ct; \
00445 } \
00446 if (dest_x + width > dest->cr) { \
00447 width = dest->cr - dest_x; \
00448 } \
00449 if (dest_y + height > dest->cb) { \
00450 height = dest->cb - dest_y; \
00451 } \
00452 } \
00453 if (source->clip) { \
00454 if ((source_x >= source->cr) || (source_y >= source->cb) \
00455 || (source_x + width < source->cl) \
00456 || (source_y + height < source->ct)) { \
00457 width = 0; \
00458 } \
00459 if (source_x < source->cl) { \
00460 width += source_x - source->cl; \
00461 dest_x -= source_x - source->cl; \
00462 source_x = source->cl; \
00463 } \
00464 if (source_y < source->ct) { \
00465 height += source_y - source->ct; \
00466 dest_y -= source_y - source->ct; \
00467 source_y = source->ct; \
00468 } \
00469 if (source_x + width > source->cr) { \
00470 width = source->cr - source_x; \
00471 } \
00472 if (source_y + height > source->cb) { \
00473 height = source->cb - source_y; \
00474 } \
00475 } \
00476 }
00477
00478
00479
00480
00481 static void allegro_gl_screen_blit_from_memory(
00482 struct BITMAP *source, struct BITMAP *dest,
00483 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00484 {
00485 GLfloat saved_zoom_x, saved_zoom_y;
00486 GLint saved_row_length;
00487 BITMAP *temp = NULL;
00488 void *data;
00489 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n");
00490
00491 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00492 width, height);
00493
00494 if (width <= 0 || height <= 0) {
00495 return;
00496 }
00497
00498
00499 if (is_sub_bitmap(dest)) {
00500 dest_x += dest->x_ofs;
00501 dest_y += dest->y_ofs;
00502 }
00503
00504
00505
00506
00507
00508 data = source->line[source_y]
00509 + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source));
00510
00511
00512
00513
00514 if (!allegro_gl_extensions_GL.EXT_packed_pixels
00515 && bitmap_color_depth(source) < 24) {
00516 temp = create_bitmap_ex(24, width, height);
00517
00518 if (temp) {
00519 blit(source, temp, source_x, source_y, 0, 0, width, height);
00520 source_x = 0;
00521 source_y = 0;
00522 data = temp->line[0];
00523 }
00524 else {
00525
00526 return;
00527 }
00528 source = temp;
00529 }
00530
00531
00532
00533 glGetFloatv(GL_ZOOM_X, &saved_zoom_x);
00534 glGetFloatv(GL_ZOOM_Y, &saved_zoom_y);
00535 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00536
00537 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00538
00539 glRasterPos2i(dest_x, dest_y);
00540
00541
00542
00543
00544 glPixelZoom (1.0, -1.0);
00545 glPixelStorei(GL_UNPACK_ROW_LENGTH,
00546 (source->line[1] - source->line[0])
00547 / BYTES_PER_PIXEL(source->vtable->color_depth));
00548
00549 glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0),
00550 __allegro_gl_get_bitmap_type(source, 0), data);
00551
00552
00553 glPixelZoom(saved_zoom_x, saved_zoom_y);
00554 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00555
00556 if (temp) {
00557 destroy_bitmap(temp);
00558 }
00559 return;
00560 }
00561
00562
00563
00564 static void allegro_gl_screen_blit_to_memory(
00565 struct BITMAP *source, struct BITMAP *dest,
00566 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00567 {
00568 GLint saved_row_length;
00569 GLint saved_alignment;
00570 GLint saved_pack_invert;
00571
00572 BITMAP *bmp = NULL;
00573
00574 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n");
00575
00576 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00577 width, height);
00578
00579 if (is_sub_bitmap(source)) {
00580 source_x += source->x_ofs;
00581 source_y += source->y_ofs;
00582 }
00583 if (is_sub_bitmap(dest)) {
00584 dest_x += dest->x_ofs;
00585 dest_y += dest->y_ofs;
00586 }
00587
00588 if (width <= 0 || height <= 0) {
00589 return;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 if ( !allegro_gl_extensions_GL.MESA_pack_invert
00602 || (!allegro_gl_extensions_GL.EXT_packed_pixels
00603 && bitmap_color_depth(dest) < 24)) {
00604
00605
00606
00607
00608 if ((!allegro_gl_extensions_GL.EXT_packed_pixels
00609 && bitmap_color_depth(dest) < 24)) {
00610 bmp = create_bitmap_ex(24, width, height);
00611 }
00612 else {
00613 bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height);
00614 }
00615 if (!bmp)
00616 return;
00617 }
00618
00619 glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length);
00620 glGetIntegerv(GL_PACK_ALIGNMENT, &saved_alignment);
00621 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
00622 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00623
00624 if (!allegro_gl_extensions_GL.MESA_pack_invert) {
00625
00626 glReadPixels(source_x, source->h - source_y - height, width, height,
00627 __allegro_gl_get_bitmap_color_format(bmp, 0),
00628 __allegro_gl_get_bitmap_type(bmp, 0), bmp->dat);
00629 }
00630 else {
00631 glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert);
00632 glPixelStorei(GL_PACK_INVERT_MESA, TRUE);
00633 glPixelStorei(GL_PACK_ROW_LENGTH,
00634 (dest->line[1] - dest->line[0])
00635 / BYTES_PER_PIXEL(dest->vtable->color_depth));
00636
00637 glReadPixels(source_x, source->h - source_y - height, width, height,
00638 __allegro_gl_get_bitmap_color_format(dest, 0),
00639 __allegro_gl_get_bitmap_type(dest, 0), dest->line[0]);
00640
00641 glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert);
00642 }
00643
00644 glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length);
00645 glPixelStorei(GL_PACK_ALIGNMENT, saved_alignment);
00646
00647
00648 if (bmp) {
00649
00650 int y, dy;
00651
00652 for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) {
00653 blit(bmp, dest, 0, y, dest_x, dy, width, 1);
00654 }
00655
00656 destroy_bitmap(bmp);
00657 }
00658
00659 return;
00660 }
00661
00662
00663
00664
00665 void allegro_gl_screen_blit_to_self (
00666 struct BITMAP *source, struct BITMAP *dest,
00667 int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00668 {
00669 AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n");
00670
00671 BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00672 width, height);
00673
00674 if (is_sub_bitmap(source)) {
00675 source_x += source->x_ofs;
00676 source_y += source->y_ofs;
00677 }
00678 if (is_sub_bitmap(dest)) {
00679 dest_x += dest->x_ofs;
00680 dest_y += dest->y_ofs;
00681 }
00682
00683 if (width <= 0 || height <= 0) {
00684 return;
00685 }
00686
00687
00688 if (is_screen_bitmap(source) && is_screen_bitmap(dest)) {
00689 glRasterPos2i(dest_x, dest_y + height - 1);
00690 glCopyPixels(source_x, SCREEN_H - source_y - height, width, height,
00691 GL_COLOR);
00692 }
00693
00694 else if (is_screen_bitmap(dest) && is_video_bitmap(source)) {
00695 AGL_VIDEO_BITMAP *vid;
00696 BITMAP *source_parent = source;
00697 GLfloat current_color[4];
00698
00699 while (source_parent->id & BMP_ID_SUB) {
00700 source_parent = (BITMAP *)source_parent->extra;
00701 }
00702 vid = source_parent->extra;
00703
00704 glGetFloatv(GL_CURRENT_COLOR, current_color);
00705 glColor4ub(255, 255, 255, 255);
00706
00707 while (vid) {
00708 int sx, sy;
00709 int dx, dy;
00710 int w, h;
00711
00712 if (source_x >= vid->x_ofs + vid->memory_copy->w ||
00713 source_y >= vid->y_ofs + vid->memory_copy->h ||
00714 vid->x_ofs >= source_x + width ||
00715 vid->y_ofs >= source_y + height) {
00716 vid = vid->next;
00717 continue;
00718 }
00719
00720 sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;
00721 w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)
00722 - vid->x_ofs - sx;
00723 sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;
00724 h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height)
00725 - vid->y_ofs - sy;
00726
00727 dx = dest_x + vid->x_ofs + sx - source_x;
00728 dy = dest_y + vid->y_ofs + sy - source_y;
00729
00730 glEnable(vid->target);
00731 glBindTexture(vid->target, vid->tex);
00732
00733 if (vid->target == GL_TEXTURE_2D) {
00734 float tx = sx / (float)vid->memory_copy->w;
00735 float ty = sy / (float)vid->memory_copy->h;
00736 float tw = w / (float)vid->memory_copy->w;
00737 float th = h / (float)vid->memory_copy->h;
00738
00739 glBegin(GL_QUADS);
00740 glTexCoord2f(tx, ty);
00741 glVertex2f(dx, dy);
00742 glTexCoord2f(tx, ty + th);
00743 glVertex2f(dx, dy + h);
00744 glTexCoord2f(tx + tw, ty + th);
00745 glVertex2f(dx + w, dy + h);
00746 glTexCoord2f(tx + tw, ty);
00747 glVertex2f(dx + w, dy);
00748 glEnd();
00749 }
00750 else {
00751 glBegin(GL_QUADS);
00752 glTexCoord2i(sx, sy);
00753 glVertex2f(dx, dy);
00754 glTexCoord2i(sx, sy + h);
00755 glVertex2f(dx, dy + h);
00756 glTexCoord2i(sx + w, sy + h);
00757 glVertex2f(dx + w, dy + h);
00758 glTexCoord2i(sx + w, sy);
00759 glVertex2f(dx + w, dy);
00760 glEnd();
00761 }
00762
00763 glBindTexture(vid->target, 0);
00764 glDisable(vid->target);
00765
00766 vid = vid->next;
00767 }
00768
00769 glColor4fv(current_color);
00770 }
00771
00772
00773 else if (is_screen_bitmap(source) && is_video_bitmap(dest)) {
00774
00775 AGL_VIDEO_BITMAP *vid;
00776 BITMAP *source_parent = source;
00777
00778 while (source_parent->id & BMP_ID_SUB) {
00779 source_parent = (BITMAP *)source_parent->extra;
00780 }
00781
00782 vid = dest->extra;
00783
00784 while (vid) {
00785 int sx, sy;
00786 int dx, dy;
00787 int w, h;
00788
00789 if (dest_x >= vid->x_ofs + vid->memory_copy->w ||
00790 dest_y >= vid->y_ofs + vid->memory_copy->h ||
00791 vid->x_ofs >= dest_x + width ||
00792 vid->y_ofs >= dest_y + height) {
00793 vid = vid->next;
00794 continue;
00795 }
00796
00797 dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;
00798 w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)
00799 - vid->x_ofs - dx;
00800 dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;
00801 h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)
00802 - vid->y_ofs - dy;
00803
00804 sx = source_x + vid->x_ofs + dx - dest_x;
00805 sy = source_y + vid->y_ofs + dy - dest_y;
00806
00807
00808 allegro_gl_screen_blit_to_memory(source, vid->memory_copy,
00809 sx, sy, dx, dy, w, h);
00810
00811 allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0,
00812 vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h);
00813
00814 vid = vid->next;
00815 }
00816 }
00817 }
00818
00819
00820
00821 static void upload_and_display_texture(struct BITMAP *source,
00822 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00823 int flip_dir, GLint format, GLint type)
00824 {
00825 float tx, ty;
00826 GLint saved_row_length;
00827 int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
00828 int i, j;
00829
00830 glEnable(GL_ALPHA_TEST);
00831 glAlphaFunc(GL_GREATER, 0.0f);
00832
00833 glEnable(GL_TEXTURE_2D);
00834 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
00835
00836 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00837 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00838
00839 glPixelStorei(GL_UNPACK_ROW_LENGTH,
00840 (source->line[1] - source->line[0]) / bytes_per_pixel);
00841
00842 for (i = 0; i <= abs(width) / 256; i++) {
00843 for (j = 0; j <= abs(height) / 256; j++) {
00844
00845 void *data = source->line[source_y + j * 256]
00846 + (source_x + i * 256) * bytes_per_pixel;
00847 int w = abs(width) - i * 256;
00848 int h = abs(height) - j * 256;
00849 int dx = dest_x + i * 256;
00850 int dy = dest_y + j * 256;
00851
00852 w = (w & -256) ? 256 : w;
00853 h = (h & -256) ? 256 : h;
00854
00855 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
00856
00857 tx = (float)w / 256.;
00858 ty = (float)h / 256.;
00859
00860 if (flip_dir & H_FLIP) {
00861 dx = 2*dest_x + width - dx;
00862 w = -w;
00863 }
00864
00865 if (flip_dir & V_FLIP) {
00866 dy = 2*dest_y + height - dy;
00867 h = -h;
00868 }
00869
00870 if (width < 0) w = -w;
00871 if (height < 0) h = -h;
00872
00873 glBegin(GL_QUADS);
00874 glTexCoord2f(0., 0.);
00875 glVertex2i(dx, dy);
00876 glTexCoord2f(0., ty);
00877 glVertex2i(dx, dy + h);
00878 glTexCoord2f(tx, ty);
00879 glVertex2i(dx + w, dy + h);
00880 glTexCoord2f(tx, 0.);
00881 glVertex2i(dx + w, dy);
00882 glEnd();
00883 }
00884 }
00885
00886
00887 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00888 glBindTexture(GL_TEXTURE_2D, 0);
00889 glDisable(GL_TEXTURE_2D);
00890 glDisable(GL_ALPHA_TEST);
00891
00892 return;
00893 }
00894
00895
00896
00897 static void do_screen_masked_blit_standard(GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
00898 {
00899 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
00900
00901 if (blit_type & NO_ROTATION) {
00902 GLint saved_row_length;
00903 float dx = dest_x, dy = dest_y;
00904 GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y;
00905
00906 glEnable(GL_ALPHA_TEST);
00907 glAlphaFunc(GL_GREATER, 0.0f);
00908
00909 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00910 glGetFloatv(GL_ZOOM_X, &old_zoom_x);
00911 glGetFloatv(GL_ZOOM_Y, &old_zoom_y);
00912
00913 if (flip_dir & H_FLIP) {
00914 zoom_x = -1.0f;
00915
00916
00917 dx += abs(width) - 0.5;
00918 }
00919 else {
00920 zoom_x = (float) width / abs(width);
00921 }
00922
00923 if (flip_dir & V_FLIP) {
00924 zoom_y = 1.0f;
00925 dy += abs(height) - 0.5;
00926 }
00927 else {
00928 zoom_y = -1.0f * width / abs(width);
00929 }
00930
00931 glRasterPos2f(dx, dy);
00932 glPixelZoom(zoom_x, zoom_y);
00933 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00934 glPixelStorei(GL_UNPACK_ROW_LENGTH,
00935 (temp->line[1] - temp->line[0])
00936 / BYTES_PER_PIXEL(bitmap_color_depth(temp)));
00937
00938 glDrawPixels(abs(width), abs(height), format, type, temp->line[0]);
00939
00940 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00941 glPixelZoom(old_zoom_x, old_zoom_y);
00942 }
00943 else {
00944 upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height,
00945 flip_dir, format, type);
00946 }
00947
00948 glPopAttrib();
00949 }
00950
00951
00952
00953 static void screen_masked_blit_standard(struct BITMAP *source,
00954 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00955 int flip_dir, int blit_type)
00956 {
00957 BITMAP *temp = NULL;
00958
00959 GLint format, type;
00960
00961 format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED);
00962 type = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED);
00963
00964 temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source,
00965 source_x, source_y, abs(width), abs(height),
00966 &type, &format);
00967
00968 if (temp) {
00969 source = temp;
00970 }
00971
00972 do_screen_masked_blit_standard(format, type, source, source_x, source_y,
00973 dest_x, dest_y, width, height, flip_dir, blit_type);
00974
00975 if (temp) {
00976 destroy_bitmap(temp);
00977 }
00978
00979 return;
00980 }
00981
00982
00983
00984 static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp)
00985 {
00986 GLfloat mask_color[4];
00987 int depth = bitmap_color_depth(bmp);
00988 int color = bitmap_mask_color(bmp);
00989
00990 mask_color[0] = getr_depth(depth, color) / 255.;
00991 mask_color[1] = getg_depth(depth, color) / 255.;
00992 mask_color[2] = getb_depth(depth, color) / 255.;
00993 mask_color[3] = 0.;
00994
00995 glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color);
00996 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
00997 glEnable(GL_REGISTER_COMBINERS_NV);
00998
00999 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
01000 GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
01001 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
01002 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
01003 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
01004 GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01005 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
01006 GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB);
01007 glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV,
01008 GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE,
01009 GL_FALSE, GL_FALSE, GL_FALSE);
01010
01011 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
01012 GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01013 glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
01014 GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01015 glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV,
01016 GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE,
01017 GL_TRUE, GL_FALSE, GL_FALSE);
01018
01019 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
01020 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01021 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO,
01022 GL_UNSIGNED_INVERT_NV, GL_RGB);
01023 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO,
01024 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01025 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO,
01026 GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01027 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV,
01028 GL_UNSIGNED_IDENTITY_NV, GL_BLUE);
01029
01030 return;
01031 }
01032
01033
01034
01035 static void screen_masked_blit_nv_register(struct BITMAP *source,
01036 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01037 int flip_dir, int blit_type)
01038 {
01039 BITMAP *temp = NULL;
01040 GLint type = __allegro_gl_get_bitmap_type(source, 0);
01041 GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01042
01043 if (type == -1) {
01044 temp = create_bitmap_ex(24, width, height);
01045 if (!temp) {
01046 return;
01047 }
01048 blit(source, temp, source_x, source_y, 0, 0, width, height);
01049 source = temp;
01050 source_x = 0;
01051 source_y = 0;
01052
01053 type = __allegro_gl_get_bitmap_type(source, 0);
01054 format = __allegro_gl_get_bitmap_color_format(source, 0);
01055 }
01056
01057 glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01058 __allegro_gl_init_nv_register_combiners(source);
01059
01060 upload_and_display_texture(source, source_x, source_y, dest_x, dest_y,
01061 width, height, flip_dir, format, type);
01062
01063 glPopAttrib();
01064
01065 if (temp) {
01066 destroy_bitmap(temp);
01067 }
01068 return;
01069 }
01070
01071
01072
01073 static void __allegro_gl_init_combine_textures(BITMAP *bmp)
01074 {
01075 GLubyte mask_color[4];
01076
01077 split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1],
01078 &mask_color[2], &mask_color[3], bitmap_color_depth(bmp));
01079 glColor4ubv(mask_color);
01080
01081 glActiveTexture(GL_TEXTURE0);
01082 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01083 glEnable(GL_TEXTURE_2D);
01084 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
01085 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01086 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
01087 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
01088
01089
01090
01091
01092
01093 glActiveTexture(GL_TEXTURE1);
01094 glEnable(GL_TEXTURE_2D);
01095 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01096 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
01097 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
01098 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
01099
01100
01101
01102 glActiveTexture(GL_TEXTURE2);
01103 glEnable(GL_TEXTURE_2D);
01104 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01105 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
01106 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01107 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
01108 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
01109
01110 glActiveTexture(GL_TEXTURE0);
01111
01112 return;
01113 }
01114
01115
01116
01117 static void screen_masked_blit_combine_tex(struct BITMAP *source,
01118 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01119 int flip_dir, int blit_type)
01120 {
01121 float tx, ty;
01122 BITMAP *temp = NULL;
01123 GLint saved_row_length;
01124 GLint type = __allegro_gl_get_bitmap_type(source, 0);
01125 GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01126 int bytes_per_pixel;
01127 int i, j;
01128 GLfloat current_color[4];
01129
01130 if (type == -1) {
01131 temp = create_bitmap_ex(24, width, height);
01132 if (!temp)
01133 return;
01134 blit(source, temp, source_x, source_y, 0, 0, width, height);
01135 source = temp;
01136 source_x = 0;
01137 source_y = 0;
01138
01139 type = __allegro_gl_get_bitmap_type(source, 0);
01140 format = __allegro_gl_get_bitmap_color_format(source, 0);
01141 }
01142
01143 glEnable(GL_TEXTURE_2D);
01144 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01145
01146 glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01147 glGetFloatv(GL_CURRENT_COLOR, current_color);
01148 __allegro_gl_init_combine_textures(source);
01149
01150 glActiveTexture(GL_TEXTURE0);
01151 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01152 glActiveTexture(GL_TEXTURE1);
01153 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01154 glActiveTexture(GL_TEXTURE2);
01155 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01156 glActiveTexture(GL_TEXTURE0);
01157
01158 bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
01159
01160 glEnable(GL_ALPHA_TEST);
01161 glAlphaFunc(GL_GREATER, 0.0f);
01162
01163 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01164 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01165
01166 glPixelStorei(GL_UNPACK_ROW_LENGTH,
01167 (source->line[1] - source->line[0]) / bytes_per_pixel);
01168
01169 for (i = 0; i <= width / 256; i++) {
01170 for (j = 0; j <= height / 256; j++) {
01171
01172 void *data = source->line[source_y + j * 256]
01173 + (source_x + i * 256) * bytes_per_pixel;
01174 int w = width - i * 256;
01175 int h = height - j * 256;
01176 int dx = dest_x + i * 256;
01177 int dy = dest_y + j * 256;
01178
01179 w = (w & -256) ? 256 : w;
01180 h = (h & -256) ? 256 : h;
01181
01182 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
01183
01184 tx = (float)w / 256.;
01185 ty = (float)h / 256.;
01186
01187 if (flip_dir & H_FLIP) {
01188 dx = 2*dest_x + width - dx;
01189 w = -w;
01190 }
01191
01192 if (flip_dir & V_FLIP) {
01193 dy = 2*dest_y + height - dy;
01194 h = -h;
01195 }
01196
01197 glBegin(GL_QUADS);
01198 glMultiTexCoord2f(GL_TEXTURE0, 0., 0.);
01199 glMultiTexCoord2f(GL_TEXTURE1, 0., 0.);
01200 glMultiTexCoord2f(GL_TEXTURE2, 0., 0.);
01201 glVertex2f(dx, dy);
01202 glMultiTexCoord2f(GL_TEXTURE0, 0., ty);
01203 glMultiTexCoord2f(GL_TEXTURE1, 0., ty);
01204 glMultiTexCoord2f(GL_TEXTURE2, 0., ty);
01205 glVertex2f(dx, dy + h);
01206 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01207 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01208 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01209 glVertex2f(dx + w, dy + h);
01210 glMultiTexCoord2f(GL_TEXTURE0, tx, 0.);
01211 glMultiTexCoord2f(GL_TEXTURE1, tx, 0.);
01212 glMultiTexCoord2f(GL_TEXTURE2, tx, 0.);
01213 glVertex2f(dx + w, dy);
01214 glEnd();
01215 }
01216 }
01217
01218
01219 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01220 glBindTexture(GL_TEXTURE_2D, 0);
01221 glDisable(GL_TEXTURE_2D);
01222 glPopAttrib();
01223 glColor4fv(current_color);
01224
01225 if (temp) {
01226 destroy_bitmap(temp);
01227 }
01228
01229 return;
01230 }
01231
01232
01233
01234 static void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
01235 int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01236 int flip_dir, int blit_type)
01237 {
01238
01239
01240
01241
01242
01243
01244 if (dest->clip && (blit_type & NO_ROTATION)) {
01245 if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
01246 || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) {
01247 return;
01248 }
01249 if (flip_dir & H_FLIP) {
01250 if (dest_x < dest->cl) {
01251 width += dest_x - dest->cl;
01252 dest_x = dest->cl;
01253 }
01254 if (dest_x + width > dest->cr) {
01255 source_x += dest_x + width - dest->cr;
01256 width = dest->cr - dest_x;
01257 }
01258 }
01259 else {
01260 if (dest_x < dest->cl) {
01261 width += dest_x - dest->cl;
01262 source_x -= dest_x - dest->cl;
01263 dest_x = dest->cl;
01264 }
01265 if (dest_x + width > dest->cr) {
01266 width = dest->cr - dest_x;
01267 }
01268 }
01269 if (flip_dir & V_FLIP) {
01270 if (dest_y < dest->ct) {
01271 height += dest_y - dest->ct;
01272 dest_y = dest->ct;
01273 }
01274 if (dest_y + height > dest->cb) {
01275 source_y += dest_y + height - dest->cb;
01276 height = dest->cb - dest_y;
01277 }
01278 }
01279 else {
01280 if (dest_y < dest->ct) {
01281 height += dest_y - dest->ct;
01282 source_y -= dest_y - dest->ct;
01283 dest_y = dest->ct;
01284 }
01285 if (dest_y + height > dest->cb) {
01286 height = dest->cb - dest_y;
01287 }
01288 }
01289 }
01290
01291
01292 if (source->clip && (blit_type & REGULAR_BMP)) {
01293 if ((source_x >= source->cr) || (source_y >= source->cb)
01294 || (source_x + width < source->cl)
01295 || (source_y + height < source->ct)) {
01296 return;
01297 }
01298 if (source_x < source->cl) {
01299 width += source_x - source->cl;
01300 dest_x -= source_x - source->cl;
01301 source_x = source->cl;
01302 }
01303 if (source_y < source->ct) {
01304 height += source_y - source->ct;
01305 dest_y -= source_y - source->ct;
01306 source_y = source->ct;
01307 }
01308 if (source_x + width > source->cr) {
01309 width = source->cr - source_x;
01310 }
01311 if (source_y + height > source->cb) {
01312 height = source->cb - source_y;
01313 }
01314 }
01315 if (is_sub_bitmap(dest)) {
01316 dest_x += dest->x_ofs;
01317 dest_y += dest->y_ofs;
01318 }
01319 if (width <= 0 || height <= 0)
01320 return;
01321
01322
01323 if (!is_video_bitmap(source) && !is_screen_bitmap(source)) {
01324
01325 __allegro_gl_driver->screen_masked_blit(source, source_x, source_y,
01326 dest_x, dest_y, width, height, flip_dir, blit_type);
01327 }
01328
01329 else if (is_video_bitmap(source)) {
01330 AGL_VIDEO_BITMAP *vid;
01331 BITMAP *source_parent = source;
01332
01333 int use_combiners = 0;
01334
01335
01336 if (allegro_gl_extensions_GL.NV_register_combiners
01337 || allegro_gl_info.num_texture_units >= 3) {
01338
01339 use_combiners = 1;
01340
01341 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
01342
01343 if (allegro_gl_extensions_GL.NV_register_combiners) {
01344 __allegro_gl_init_nv_register_combiners(source);
01345 }
01346 else {
01347 __allegro_gl_init_combine_textures(source);
01348 }
01349
01350 glEnable(GL_ALPHA_TEST);
01351 glAlphaFunc(GL_GREATER, 0.0f);
01352 }
01353
01354 while (source_parent->id & BMP_ID_SUB) {
01355 source_parent = (BITMAP *)source_parent->extra;
01356 }
01357 vid = source_parent->extra;
01358
01359 while (vid) {
01360 int sx, sy;
01361 int dx, dy;
01362 int w, h;
01363
01364 if (source_x >= vid->x_ofs + vid->memory_copy->w ||
01365 source_y >= vid->y_ofs + vid->memory_copy->h ||
01366 vid->x_ofs >= source_x + width ||
01367 vid->y_ofs >= source_y + height) {
01368 vid = vid->next;
01369 continue;
01370 }
01371
01372 sx = MAX (vid->x_ofs, source_x) - vid->x_ofs;
01373 w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width)
01374 - vid->x_ofs - sx;
01375 sy = MAX (vid->y_ofs, source_y) - vid->y_ofs;
01376 h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height)
01377 - vid->y_ofs - sy;
01378
01379 dx = dest_x + vid->x_ofs + sx - source_x;
01380 dy = dest_y + vid->y_ofs + sy - source_y;
01381
01382 if (flip_dir & H_FLIP) {
01383 dx = 2*dest_x + width - dx;
01384 w = -w;
01385 }
01386
01387 if (flip_dir & V_FLIP) {
01388 dy = 2*dest_y + height - dy;
01389 h = -h;
01390 }
01391
01392 if (use_combiners) {
01393 if (allegro_gl_extensions_GL.NV_register_combiners) {
01394 glEnable(vid->target);
01395 glBindTexture(vid->target, vid->tex);
01396 glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01397 glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01398
01399 if (vid->target == GL_TEXTURE_2D) {
01400 float tx = sx / (float)vid->memory_copy->w;
01401 float ty = sy / (float)vid->memory_copy->h;
01402 float tw = abs(w) / (float)vid->memory_copy->w;
01403 float th = abs(h) / (float)vid->memory_copy->h;
01404
01405 glBegin(GL_QUADS);
01406 glTexCoord2f(tx, ty);
01407 glVertex2f(dx, dy);
01408 glTexCoord2f(tx, ty + th);
01409 glVertex2f(dx, dy + h);
01410 glTexCoord2f(tx + tw, ty + th);
01411 glVertex2f(dx + w, dy + h);
01412 glTexCoord2f(tx + tw, ty);
01413 glVertex2f(dx + w, dy);
01414 glEnd();
01415 }
01416 else {
01417 glBegin(GL_QUADS);
01418 glTexCoord2i(sx, sy);
01419 glVertex2f(dx, dy);
01420 glTexCoord2i(sx, sy + h);
01421 glVertex2f(dx, dy + h);
01422 glTexCoord2i(sx + w, sy + h);
01423 glVertex2f(dx + w, dy + h);
01424 glTexCoord2i(sx + w, sy);
01425 glVertex2f(dx + w, dy);
01426 glEnd();
01427 }
01428
01429 glBindTexture(vid->target, 0);
01430 glDisable(vid->target);
01431 }
01432 else {
01433 glEnable(vid->target);
01434 glActiveTexture(GL_TEXTURE0);
01435 glBindTexture(vid->target, vid->tex);
01436 glActiveTexture(GL_TEXTURE1);
01437 glBindTexture(vid->target, vid->tex);
01438 glActiveTexture(GL_TEXTURE2);
01439 glBindTexture(vid->target, vid->tex);
01440 glActiveTexture(GL_TEXTURE0);
01441 glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01442 glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01443
01444 if (vid->target == GL_TEXTURE_2D) {
01445 float tx, ty, tw, th;
01446 tx = sx / (float)vid->memory_copy->w;
01447 ty = sy / (float)vid->memory_copy->h;
01448 tw = abs(w) / (float)vid->memory_copy->w;
01449 th = abs(h) / (float)vid->memory_copy->h;
01450
01451 glBegin(GL_QUADS);
01452 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01453 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01454 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01455 glVertex2f(dx, dy);
01456 glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th);
01457 glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th);
01458 glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th);
01459 glVertex2f(dx, dy + h);
01460 glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th);
01461 glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th);
01462 glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th);
01463 glVertex2f(dx + w, dy + h);
01464 glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty);
01465 glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty);
01466 glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty);
01467 glVertex2f(dx + w, dy);
01468 glEnd();
01469 }
01470 else {
01471 glBegin(GL_QUADS);
01472 glMultiTexCoord2i(GL_TEXTURE0, dx, dy);
01473 glMultiTexCoord2i(GL_TEXTURE1, dx, dy);
01474 glMultiTexCoord2i(GL_TEXTURE2, dx, dy);
01475 glVertex2f(dx, dy);
01476 glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h);
01477 glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h);
01478 glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h);
01479 glVertex2f(dx, dy + h);
01480 glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h);
01481 glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h);
01482 glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h);
01483 glVertex2f(dx + w, dy + h);
01484 glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy);
01485 glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy);
01486 glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy);
01487 glVertex2f(dx + w, dy);
01488 glEnd();
01489 }
01490
01491 glBindTexture(vid->target, 0);
01492 glDisable(vid->target);
01493 }
01494 }
01495 else {
01496 screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy,
01497 w, h, FALSE, blit_type);
01498 }
01499
01500 vid = vid->next;
01501 }
01502
01503 if (use_combiners) {
01504 glPopAttrib();
01505 }
01506 }
01507 return;
01508 }
01509
01510
01511
01512 static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans)
01513 {
01514 BITMAP *temp = NULL;
01515 int y, x, src_depth;
01516 signed long src_mask;
01517
01518 #define DRAW_RLE_8888(bits) \
01519 { \
01520 for (y = 0; y < sprite->h; y++) { \
01521 signed long c = *s++; \
01522 for (x = 0; x < sprite->w;) { \
01523 if (c == src_mask) \
01524 break; \
01525 if (c > 0) { \
01526 \
01527 for (c--; c>=0; c--) { \
01528 unsigned long col = *s++; \
01529 if (bits == 32 && trans) \
01530 _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
01531 else \
01532 _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
01533 } \
01534 } \
01535 else { \
01536 \
01537 hline(temp, x, y, x-c+1, 0); \
01538 x -= c; \
01539 } \
01540 c = *s++; \
01541 } \
01542 } \
01543 }
01544
01545 #define DRAW_RLE_5551(bits) \
01546 { \
01547 for (y = 0; y < sprite->h; y++) { \
01548 signed long c = *s++; \
01549 for (x = 0; x < sprite->w;) { \
01550 if (c == src_mask) \
01551 break; \
01552 if (c > 0) { \
01553 \
01554 for (c--; c>=0; c--) { \
01555 unsigned long col = *s++; \
01556 _putpixel16(temp, x++, y, (1 << ((_rgb_r_shift_15 > _rgb_b_shift_15) ? 0 : 15)) \
01557 | ((getr##bits(col) >> 3) << _rgb_r_shift_15) \
01558 | ((getg##bits(col) >> 3) << _rgb_g_shift_15) \
01559 | ((getb##bits(col) >> 3) << _rgb_b_shift_15)); \
01560 } \
01561 } \
01562 else { \
01563 \
01564 hline(temp, x, y, x-c+1, 0); \
01565 x -= c; \
01566 } \
01567 c = *s++; \
01568 } \
01569 } \
01570 }
01571
01572 src_depth = sprite->color_depth;
01573 if (src_depth == 8)
01574 src_mask = 0;
01575 else
01576 src_mask = makecol_depth(src_depth, 255, 0, 255);
01577
01578 if ((allegro_gl_extensions_GL.EXT_packed_pixels
01579 || allegro_gl_opengl_version() >= 1.2) && src_depth <= 16) {
01580 temp = create_bitmap_ex(15, sprite->w, sprite->h);
01581 }
01582 else {
01583 temp = create_bitmap_ex(32, sprite->w, sprite->h);
01584 }
01585
01586 if (!temp) return NULL;
01587
01588
01589 if (bitmap_color_depth(temp) == 32) {
01590 switch(src_depth) {
01591 case 8:
01592 {
01593 signed char *s = (signed char*)sprite->dat;
01594 DRAW_RLE_8888(8);
01595 break;
01596 }
01597 case 15:
01598 {
01599 int16_t *s = (int16_t*)sprite->dat;
01600 DRAW_RLE_8888(15);
01601 break;
01602 }
01603 case 16:
01604 {
01605 int16_t *s = (int16_t*)sprite->dat;
01606 DRAW_RLE_8888(16);
01607 break;
01608 }
01609 case 24:
01610 {
01611 int32_t *s = (int32_t*)sprite->dat;
01612 DRAW_RLE_8888(24);
01613 break;
01614 }
01615 case 32:
01616 {
01617 int32_t *s = (int32_t*)sprite->dat;
01618 DRAW_RLE_8888(32);
01619 break;
01620 }
01621 }
01622 }
01623
01624 else {
01625 switch(src_depth) {
01626 case 8:
01627 {
01628 signed char *s = (signed char*)sprite->dat;
01629 DRAW_RLE_5551(8);
01630 break;
01631 }
01632 case 15:
01633 {
01634 int16_t *s = (int16_t*)sprite->dat;
01635 DRAW_RLE_5551(15);
01636 break;
01637 }
01638 case 16:
01639 {
01640 int16_t *s = (int16_t*)sprite->dat;
01641 DRAW_RLE_5551(16);
01642 break;
01643 }
01644 }
01645 }
01646
01647 return temp;
01648 }
01649
01650
01651
01652 static void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
01653 {
01654 BITMAP *temp = NULL, *temp2 = NULL;
01655 int source_x = 0, source_y = 0;
01656 int width = sprite->w, height = sprite->h;
01657
01658 temp = __allegro_gl_convert_rle_sprite(sprite, FALSE);
01659 if (!temp)
01660 return;
01661
01662 BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01663
01664 if (is_sub_bitmap(bmp)) {
01665 x += bmp->x_ofs;
01666 y += bmp->y_ofs;
01667 }
01668
01669 if (width <= 0 || height <= 0) {
01670 destroy_bitmap(temp);
01671 return;
01672 }
01673
01674 temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01675 if (!temp2) {
01676 destroy_bitmap(temp);
01677 return;
01678 }
01679
01680 do_screen_masked_blit_standard(GL_RGBA,
01681 __allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2,
01682 0, 0, x, y, width, height, FALSE, NO_ROTATION);
01683
01684 destroy_bitmap(temp2);
01685 destroy_bitmap(temp);
01686 }
01687
01688
01689 static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp,
01690 AL_CONST struct RLE_SPRITE *sprite, int x, int y) {
01691 BITMAP *temp = NULL, *temp2 = NULL;
01692 int source_x = 0, source_y = 0;
01693 int width = sprite->w, height = sprite->h;
01694
01695 temp = __allegro_gl_convert_rle_sprite(sprite, TRUE);
01696 if (!temp)
01697 return;
01698
01699 BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01700
01701 if (is_sub_bitmap(bmp)) {
01702 x += bmp->x_ofs;
01703 y += bmp->y_ofs;
01704 }
01705
01706 if (width <= 0 || height <= 0) {
01707 destroy_bitmap(temp);
01708 return;
01709 }
01710
01711 temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01712 if (!temp2) {
01713 destroy_bitmap(temp);
01714 return;
01715 }
01716
01717 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01718 glEnable(GL_COLOR_LOGIC_OP);
01719 else
01720 glEnable(GL_BLEND);
01721
01722 upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE);
01723
01724 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01725 glDisable(GL_COLOR_LOGIC_OP);
01726 else
01727 glDisable(GL_BLEND);
01728
01729 destroy_bitmap(temp2);
01730 destroy_bitmap(temp);
01731 }
01732
01733
01734
01735 static void allegro_gl_screen_masked_blit(struct BITMAP *source,
01736 struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
01737 int width, int height)
01738 {
01739 AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n");
01740 do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y,
01741 width, height, FALSE, REGULAR_BMP | NO_ROTATION);
01742 }
01743
01744
01745
01746 static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp,
01747 struct BITMAP *sprite, int x, int y)
01748 {
01749 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n");
01750 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01751 FALSE, NO_ROTATION);
01752 }
01753
01754
01755
01756 static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp,
01757 struct BITMAP *sprite, int x, int y)
01758 {
01759 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n");
01760 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01761 V_FLIP, NO_ROTATION);
01762 }
01763
01764
01765
01766 static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp,
01767 struct BITMAP *sprite, int x, int y)
01768 {
01769 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n");
01770 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01771 H_FLIP, NO_ROTATION);
01772 }
01773
01774
01775
01776 static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp,
01777 struct BITMAP *sprite, int x, int y)
01778 {
01779 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n");
01780 do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01781 V_FLIP | H_FLIP, NO_ROTATION);
01782 }
01783
01784
01785
01786 static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp,
01787 struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle,
01788 fixed scale, int v_flip)
01789 {
01790 double dscale = fixtof(scale);
01791 GLint matrix_mode;
01792 AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n");
01793
01794 #define BIN_2_DEG(x) ((x) * 180.0 / 128)
01795
01796 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01797 glMatrixMode(GL_MODELVIEW);
01798 glPushMatrix();
01799 glTranslated(fixtof(x), fixtof(y), 0.);
01800 glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
01801 glScaled(dscale, dscale, dscale);
01802 glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
01803
01804 do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
01805 sprite->w, sprite->h, v_flip ? V_FLIP : FALSE, FALSE);
01806 glPopMatrix();
01807 glMatrixMode(matrix_mode);
01808
01809 #undef BIN_2_DEG
01810
01811 return;
01812 }
01813
01814
01815
01816 static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp,
01817 struct BITMAP *sprite, int x, int y) {
01818
01819 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01820 glEnable(GL_COLOR_LOGIC_OP);
01821 else
01822 glEnable(GL_BLEND);
01823
01824
01825 if (is_video_bitmap(sprite)) {
01826 allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h);
01827 }
01828
01829 else if (is_memory_bitmap(sprite)) {
01830 upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, GL_RGBA, GL_UNSIGNED_BYTE);
01831 }
01832
01833 if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01834 glDisable(GL_COLOR_LOGIC_OP);
01835 else
01836 glDisable(GL_BLEND);
01837
01838 return;
01839 }
01840
01841
01842
01843 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
01844 AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01845 int color, int bg)
01846 {
01847 GLubyte r, g, b, a;
01848 int x_offs = 0;
01849 int i;
01850
01851 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph\n");
01852
01853 if (bmp->clip) {
01854 glPushAttrib(GL_SCISSOR_BIT);
01855 glEnable(GL_SCISSOR_TEST);
01856 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
01857 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
01858
01859 if (x < bmp->cl) {
01860 x_offs -= x - bmp->cl;
01861 x = bmp->cl;
01862 }
01863 }
01864 if (is_sub_bitmap(bmp)) {
01865 x += bmp->x_ofs;
01866 y += bmp->y_ofs;
01867 }
01868
01869 if (bg != -1) {
01870 split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01871 glColor4ub(r, g, b, a);
01872 glRecti(x, y, x + glyph->w, y + glyph->h);
01873 }
01874
01875 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01876 glColor4ub(r, g, b, a);
01877 glRasterPos2i(x, y);
01878 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01879 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01880
01881 for (i = 0; i < glyph->h; i++) {
01882 glBitmap(glyph->w, 1, x_offs, i, 0, 0,
01883 glyph->dat + i * ((glyph->w + 7) / 8));
01884 }
01885
01886 if (bmp->clip) {
01887 glPopAttrib();
01888 }
01889
01890 return;
01891 }
01892
01893
01894
01895 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
01896 struct BITMAP *sprite, int x, int y, int color, int bg)
01897 {
01898
01899
01900
01901
01902 static GLfloat red_map[256];
01903 static GLfloat green_map[256];
01904 static GLfloat blue_map[256];
01905 static GLfloat alpha_map[256];
01906 GLubyte r, g, b, a;
01907 int i;
01908 GLint saved_row_length;
01909 GLint width, height;
01910 int sprite_x = 0, sprite_y = 0;
01911 void *data;
01912 int *table;
01913
01914 width = sprite->w;
01915 height = sprite->h;
01916
01917 if (bmp->clip) {
01918 if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
01919 || (y + height < bmp->ct)) {
01920 return;
01921 }
01922 if (x < bmp->cl) {
01923 width += x - bmp->cl;
01924 sprite_x -= (x - bmp->cl);
01925 x = bmp->cl;
01926 }
01927 if (y < bmp->ct) {
01928 height += y - bmp->ct;
01929 sprite_y -= (y - bmp->ct);
01930 y = bmp->ct;
01931 }
01932 if (x + width > bmp->cr) {
01933 width = bmp->cr - x;
01934 }
01935 if (y + height > bmp->cb) {
01936 height = bmp->cb - y;
01937 }
01938 }
01939 if (is_sub_bitmap(bmp)) {
01940 x += bmp->x_ofs;
01941 y += bmp->y_ofs;
01942 }
01943
01944 data = sprite->line[sprite_y]
01945 + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
01946
01947 if (_textmode < 0) {
01948 glAlphaFunc(GL_GREATER, 0.0f);
01949 glEnable(GL_ALPHA_TEST);
01950 alpha_map[0] = 0.;
01951 }
01952 else {
01953 split_color(_textmode, &r, &g, &b, &a, bitmap_color_depth(bmp));
01954 red_map[0] = r / 255.;
01955 green_map[0] = g / 255.;
01956 blue_map[0] = b / 255.;
01957 alpha_map[0] = 1.;
01958 }
01959
01960 if (color < 0) {
01961 table = _palette_expansion_table(bitmap_color_depth(bmp));
01962
01963 for(i = 1; i < 255; i++) {
01964 split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
01965 red_map[i] = r / 255.;
01966 green_map[i] = g / 255.;
01967 blue_map[i] = b / 255.;
01968 alpha_map[i] = 1.;
01969 }
01970 }
01971 else {
01972 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01973
01974 for(i = 1; i < 255; i++) {
01975 red_map[i] = r / 255.;
01976 green_map[i] = g / 255.;
01977 blue_map[i] = b / 255.;
01978 alpha_map[i] = 1.;
01979 }
01980 }
01981
01982 glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
01983 glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
01984 glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
01985 glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
01986
01987 glRasterPos2i(x, y);
01988 glPushAttrib(GL_PIXEL_MODE_BIT);
01989 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01990
01991 glPixelZoom(1.0, -1.0);
01992 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01993 glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
01994 glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
01995
01996 glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
01997 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01998 glPopAttrib();
01999 if (_textmode < 0) {
02000 glDisable(GL_ALPHA_TEST);
02001 }
02002
02003 return;
02004 }
02005
02006
02007
02008 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
02009 struct BITMAP *sprite, int x, int y, int color, int bg)
02010 {
02011 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
02012 allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
02013 }
02014
02015
02016
02017 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
02018 struct BITMAP *sprite, int x, int y)
02019 {
02020 AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
02021 allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, _textmode);
02022 }
02023
02024
02025
02026 static void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
02027 {
02028 GLubyte r, g, b, a;
02029 GLfloat old_col[4];
02030
02031 AGL_LOG(2, "glvtable.c:allegro_gl_screen_clear_to_color\n");
02032 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02033
02034 glPushAttrib(GL_SCISSOR_BIT);
02035
02036 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
02037 glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
02038 ((float) a / 255));
02039
02040 if (bmp->clip) {
02041 glEnable(GL_SCISSOR_TEST);
02042 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02043 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02044 }
02045 else {
02046 glScissor(0, 0, SCREEN_W, SCREEN_H);
02047 }
02048 glClear(GL_COLOR_BUFFER_BIT);
02049
02050 glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
02051
02052 glPopAttrib();
02053
02054 return;
02055 }
02056
02057
02058
02059
02060 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
02061 AL_CONST int *points, int color) {
02062 GLubyte r, g, b, a;
02063 int i;
02064
02065 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02066 glColor4ub(r, g, b, a);
02067
02068 glPushAttrib(GL_SCISSOR_BIT);
02069
02070 if (bmp->clip) {
02071 glEnable(GL_SCISSOR_TEST);
02072 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02073 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02074 }
02075 else {
02076 glScissor(0, 0, SCREEN_W, SCREEN_H);
02077 }
02078
02079 __allegro_gl_set_drawing_mode();
02080 glBegin(GL_POLYGON);
02081 for (i = 0; i < vertices*2-1; i+=2) {
02082 if (is_sub_bitmap(bmp)) {
02083 glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
02084 }
02085 else {
02086 glVertex2f(points[i], points[i+1]);
02087 }
02088 }
02089 glEnd();
02090 __allegro_gl_unset_drawing_mode();
02091
02092 glPopAttrib();
02093 }
02094
02095
02096
02097 static void allegro_gl_screen_rect(struct BITMAP *bmp,
02098 int x1, int y1, int x2, int y2, int color) {
02099 GLubyte r, g, b, a;
02100
02101 split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02102 glColor4ub(r, g, b, a);
02103
02104 glPushAttrib(GL_SCISSOR_BIT);
02105
02106 if (bmp->clip) {
02107 glEnable(GL_SCISSOR_TEST);
02108 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02109 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02110 }
02111 else {
02112 glScissor(0, 0, SCREEN_W, SCREEN_H);
02113 }
02114 if (is_sub_bitmap(bmp)) {
02115 x1 += bmp->x_ofs;
02116 x2 += bmp->x_ofs;
02117 y1 += bmp->y_ofs;
02118 y2 += bmp->y_ofs;
02119 }
02120
02121 __allegro_gl_set_drawing_mode();
02122 glBegin(GL_LINE_STRIP);
02123 glVertex2f(x1, y1);
02124 glVertex2f(x2, y1);
02125 glVertex2f(x2, y2);
02126 glVertex2f(x1, y2);
02127 glVertex2f(x1, y1);
02128 glEnd();
02129 __allegro_gl_unset_drawing_mode();
02130
02131 glPopAttrib();
02132 }
02133
02134
02135
02136 static void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
02137 struct BITMAP *texture, int vc,
02138 V3D_f *vtx[]) {
02139 int i;
02140 int use_z = FALSE;
02141
02142 if (type & POLYTYPE_ZBUF) {
02143 use_z = TRUE;
02144 type &= ~POLYTYPE_ZBUF;
02145 }
02146
02147
02148 if ((type != POLYTYPE_FLAT) && (type != POLYTYPE_GRGB)
02149 && (type != POLYTYPE_GCOL)) {
02150 if (texture && !is_video_bitmap(texture))
02151 _soft_polygon3d_f(bmp, type, texture, vc, vtx);
02152 return;
02153 }
02154
02155 if (bmp->clip) {
02156 glEnable(GL_SCISSOR_TEST);
02157 glScissor(bmp->x_ofs + bmp->cl, SCREEN_H - bmp->y_ofs - bmp->cb,
02158 bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02159 }
02160 else {
02161 glScissor(0, 0, SCREEN_W, SCREEN_H);
02162 }
02163 if (is_sub_bitmap(bmp)) {
02164 for (i = 0; i < vc*2-1; i+=2) {
02165 vtx[i] += bmp->x_ofs;
02166 vtx[i+1] += bmp->y_ofs;
02167 }
02168 }
02169
02170 if (use_z) {
02171 glEnable(GL_DEPTH_TEST);
02172 glDepthFunc(GL_LESS);
02173 glDepthMask(GL_TRUE);
02174 }
02175 else
02176 __allegro_gl_set_drawing_mode();
02177
02178 glBegin(GL_POLYGON);
02179 for (i = 0; i < vc; i++) {
02180 if (type & POLYTYPE_FLAT)
02181 glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
02182 else if (type & POLYTYPE_GRGB)
02183 glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
02184 else if (type & POLYTYPE_GCOL)
02185 glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
02186
02187 if (use_z)
02188 glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
02189 else
02190 glVertex2f(vtx[i]->x, vtx[i]->y);
02191 }
02192 if (use_z)
02193 glVertex3f(vtx[0]->x, vtx[0]->y, 1.f / vtx[0]->z);
02194 else
02195 glVertex2f(vtx[0]->x, vtx[0]->y);
02196
02197 glEnd();
02198
02199 if (use_z) {
02200 glDisable(GL_DEPTH_TEST);
02201 glDepthMask(GL_FALSE);
02202 }
02203 else
02204 __allegro_gl_unset_drawing_mode();
02205 }
02206
02207
02208
02209 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
02210 struct BITMAP *texture, int vc,
02211 V3D *vtx[]) {
02212 int i;
02213 V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
02214 if (!vtx_f)
02215 return;
02216
02217 for (i = 0; i < vc; i++) {
02218 vtx_f[i] = malloc(sizeof(struct V3D_f));
02219 if (!vtx_f[i]) {
02220 int k;
02221 for (k = 0; k < i; k++)
02222 free(vtx_f[k]);
02223 free(vtx_f);
02224 return;
02225 }
02226 vtx_f[i]->c = vtx[i]->c;
02227 vtx_f[i]->u = fixtof(vtx[i]->u);
02228 vtx_f[i]->v = fixtof(vtx[i]->v);
02229 vtx_f[i]->x = fixtof(vtx[i]->x);
02230 vtx_f[i]->y = fixtof(vtx[i]->y);
02231 vtx_f[i]->z = fixtof(vtx[i]->z);
02232 }
02233
02234 allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
02235 for (i = 0; i < vc; i++)
02236 free(vtx_f[i]);
02237 free(vtx_f);
02238 }
02239
02240
02241 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
02242 struct BITMAP *texture,
02243 V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
02244
02245 V3D_f *vtx_f[4];
02246 vtx_f[0] = v1;
02247 vtx_f[1] = v2;
02248 vtx_f[2] = v3;
02249 vtx_f[3] = v4;
02250
02251 allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
02252 }
02253
02254
02255
02256 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
02257 struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
02258
02259 V3D *vtx[4];
02260 vtx[0] = v1;
02261 vtx[1] = v2;
02262 vtx[2] = v3;
02263 vtx[3] = v4;
02264
02265 allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
02266 }
02267
02268
02269
02270 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
02271 struct BITMAP *texture,
02272 V3D *v1, V3D *v2, V3D *v3) {
02273 V3D *vtx[3];
02274 vtx[0] = v1;
02275 vtx[1] = v2;
02276 vtx[2] = v3;
02277
02278 allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
02279 }
02280
02281
02282
02283 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
02284 struct BITMAP *texture,
02285 V3D_f *v1, V3D_f *v2, V3D_f *v3) {
02286 V3D_f *vtx_f[3];
02287 vtx_f[0] = v1;
02288 vtx_f[1] = v2;
02289 vtx_f[2] = v3;
02290
02291 allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
02292 }
02293
02294
02295
02296 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
02297 {
02298 int maskcolor = (*vtable)->mask_color;
02299 int depth = (*vtable)->color_depth;
02300
02301 AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
02302 allegro_gl_screen_vtable.color_depth = depth;
02303
02304
02305
02306
02307 allegro_gl_screen_vtable.mask_color =
02308 makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
02309
02310 *vtable = &allegro_gl_screen_vtable;
02311
02312 __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
02313 if (allegro_gl_extensions_GL.NV_register_combiners) {
02314 __allegro_gl_driver->screen_masked_blit
02315 = screen_masked_blit_nv_register;
02316 }
02317 else if (allegro_gl_info.num_texture_units >= 3) {
02318 __allegro_gl_driver->screen_masked_blit =
02319 screen_masked_blit_combine_tex;
02320 }
02321 }
02322
02323
02324
02325
02326 static double allegro_gl_projection_matrix[16];
02327 static double allegro_gl_modelview_matrix[16];
02328
02329
02330
02361 void allegro_gl_set_allegro_mode(void)
02362 {
02363 AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
02364
02365
02366 glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
02367 | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02368 glDisable(GL_DEPTH_TEST);
02369 glDisable(GL_CULL_FACE);
02370 glDisable(GL_FOG);
02371 glDisable(GL_LIGHTING);
02372 glDisable(GL_BLEND);
02373 glDisable(GL_ALPHA_TEST);
02374 glDepthMask(GL_FALSE);
02375 glEnable(GL_TEXTURE_2D);
02376 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02377 glPointSize(1.);
02378
02379
02380 if (!__allegro_gl_pool_texture) {
02381 glGenTextures(1, &__allegro_gl_pool_texture);
02382 }
02383
02384 glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
02385
02386 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
02387 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
02388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02390
02391 glBindTexture(GL_TEXTURE_2D, 0);
02392 allegro_gl_set_projection();
02393
02394
02395
02396
02397 if (allegro_gl_info.is_ati_rage_pro) {
02398 if (!__allegro_gl_dummy_texture) {
02399 GLubyte tex[4] = {255, 255, 255, 255};
02400 glGenTextures(1, &__allegro_gl_dummy_texture);
02401 glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02402 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
02403 GL_RGBA, GL_UNSIGNED_BYTE, tex);
02404 }
02405 glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02406 }
02407 #ifdef ALLEGRO_MACOSX
02408
02409
02410
02411 glBegin(GL_POINTS);
02412 glEnd();
02413 #endif
02414 }
02415
02416
02417
02430 void allegro_gl_unset_allegro_mode(void)
02431 {
02432 AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
02433
02434 switch(allegro_gl_display_info.vidmem_policy) {
02435 case AGL_KEEP:
02436 break;
02437 case AGL_RELEASE:
02438 if (__allegro_gl_pool_texture) {
02439 glDeleteTextures(1, &__allegro_gl_pool_texture);
02440 __allegro_gl_pool_texture = 0;
02441 }
02442 break;
02443 }
02444 allegro_gl_unset_projection();
02445 glPopAttrib();
02446 }
02447
02448
02449
02479 void allegro_gl_set_projection(void)
02480 {
02481 GLint v[4];
02482 AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
02483
02484
02485 glGetIntegerv(GL_VIEWPORT, &v[0]);
02486 glMatrixMode(GL_MODELVIEW);
02487 glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
02488 glLoadIdentity();
02489 glMatrixMode(GL_PROJECTION);
02490 glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
02491 glLoadIdentity();
02492 gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
02493 }
02494
02495
02496
02506 void allegro_gl_unset_projection(void)
02507 {
02508 AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
02509 glMatrixMode(GL_PROJECTION);
02510 glLoadMatrixd(allegro_gl_projection_matrix);
02511 glMatrixMode(GL_MODELVIEW);
02512 glLoadMatrixd(allegro_gl_modelview_matrix);
02513 }
02514
02515
02516
02517 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
02518 struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
02519 int width, int height)
02520 {
02521 AGL_LOG(2, "AGL::blit_between_formats\n");
02522
02523
02524 if (is_screen_bitmap(src)) {
02525 allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
02526 dest_x, dest_y, width, height);
02527 return;
02528 }
02529
02530
02531 if (is_video_bitmap(src)) {
02532 allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
02533 dest_x, dest_y, width, height);
02534 return;
02535 }
02536
02537
02538 if (is_screen_bitmap(dest)) {
02539 allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
02540 dest_x, dest_y, width, height);
02541 return;
02542 }
02543
02544
02545 if (is_video_bitmap(dest)) {
02546 allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
02547 dest_x, dest_y, width, height);
02548 return;
02549 }
02550
02551 switch(bitmap_color_depth(dest)) {
02552 #ifdef ALLEGRO_COLOR8
02553 case 8:
02554 __blit_between_formats8(src, dest, source_x, source_y,
02555 dest_x, dest_y, width, height);
02556 return;
02557 #endif
02558 #ifdef ALLEGRO_COLOR16
02559 case 15:
02560 __blit_between_formats15(src, dest, source_x, source_y,
02561 dest_x, dest_y, width, height);
02562 return;
02563 case 16:
02564 __blit_between_formats16(src, dest, source_x, source_y,
02565 dest_x, dest_y, width, height);
02566 return;
02567 #endif
02568 #ifdef ALLEGRO_COLOR24
02569 case 24:
02570 __blit_between_formats24(src, dest, source_x, source_y,
02571 dest_x, dest_y, width, height);
02572 return;
02573 #endif
02574 #ifdef ALLEGRO_COLOR32
02575 case 32:
02576 __blit_between_formats32(src, dest, source_x, source_y,
02577 dest_x, dest_y, width, height);
02578 return;
02579 #endif
02580 default:
02581 TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
02582 bitmap_color_depth(src), bitmap_color_depth(dest));
02583 return;
02584 }
02585 }
02586
02587
02588
02589 static void dummy_unwrite_bank(void)
02590 {
02591 }
02592
02593
02594
02595 static GFX_VTABLE allegro_gl_screen_vtable = {
02596 0,
02597 0,
02598 dummy_unwrite_bank,
02599 NULL,
02600 allegro_gl_screen_acquire,
02601 allegro_gl_screen_release,
02602 NULL,
02603 NULL,
02604 allegro_gl_screen_getpixel,
02605 allegro_gl_screen_putpixel,
02606 allegro_gl_screen_vline,
02607 allegro_gl_screen_hline,
02608 allegro_gl_screen_hline,
02609 allegro_gl_screen_line,
02610 allegro_gl_screen_line,
02611 allegro_gl_screen_rectfill,
02612 allegro_gl_screen_triangle,
02613 allegro_gl_screen_draw_sprite,
02614 allegro_gl_screen_draw_256_sprite,
02615 allegro_gl_screen_draw_sprite_v_flip,
02616 allegro_gl_screen_draw_sprite_h_flip,
02617 allegro_gl_screen_draw_sprite_vh_flip,
02618 allegro_gl_screen_draw_trans_rgba_sprite,
02619 allegro_gl_screen_draw_trans_rgba_sprite,
02620 NULL,
02621 allegro_gl_screen_draw_rle_sprite,
02622 allegro_gl_screen_draw_trans_rgba_rle_sprite,
02623 allegro_gl_screen_draw_trans_rgba_rle_sprite,
02624 NULL,
02625 allegro_gl_screen_draw_character,
02626 allegro_gl_screen_draw_glyph,
02627 allegro_gl_screen_blit_from_memory,
02628 allegro_gl_screen_blit_to_memory,
02629 NULL,
02630 NULL,
02631 allegro_gl_screen_blit_to_self,
02632 allegro_gl_screen_blit_to_self,
02633 allegro_gl_screen_blit_to_self,
02634 allegro_gl_memory_blit_between_formats,
02635 allegro_gl_screen_masked_blit,
02636 allegro_gl_screen_clear_to_color,
02637 allegro_gl_screen_pivot_scaled_sprite_flip,
02638 NULL,
02639 NULL,
02640 NULL,
02641 NULL,
02642 allegro_gl_screen_polygon,
02643 allegro_gl_screen_rect,
02644 _soft_circle,
02645 _soft_circlefill,
02646 _soft_ellipse,
02647 _soft_ellipsefill,
02648 _soft_arc,
02649 _soft_spline,
02650 _soft_floodfill,
02651 allegro_gl_screen_polygon3d,
02652 allegro_gl_screen_polygon3d_f,
02653 allegro_gl_screen_triangle3d,
02654 allegro_gl_screen_triangle3d_f,
02655 allegro_gl_screen_quad3d,
02656 allegro_gl_screen_quad3d_f
02657 };
02658