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