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 "alleggl.h" 00011 #include "allglint.h" 00012 00013 #include <allegro/internal/aintern.h> 00014 00015 #ifdef ALLEGRO_MACOSX 00016 #include <OpenGL/glu.h> 00017 #else 00018 #include <GL/glu.h> 00019 #endif 00020 00021 static GLint allegro_gl_opengl_internal_texture_format = -1; 00022 static int allegro_gl_use_mipmapping_for_textures = 0; 00023 int __allegro_gl_use_alpha = FALSE; 00024 int __allegro_gl_flip_texture = TRUE; 00025 GLint __allegro_gl_texture_read_format[5]; 00026 GLint __allegro_gl_texture_components[5]; 00027 00028 #define PREFIX_I "agl-tex INFO: " 00029 #define PREFIX_W "agl-tex WARNING: " 00030 #define PREFIX_E "agl-tex ERROR: " 00031 00032 00038 char const *__allegro_gl_get_format_description(GLint format) 00039 { 00040 static char str[256]; 00041 #define F(s) case s: return #s 00042 switch (format) { 00043 F(GL_ALPHA); 00044 F(GL_ALPHA4); 00045 F(GL_ALPHA8); 00046 F(GL_ALPHA12); 00047 F(GL_ALPHA16); 00048 F(GL_ALPHA16F_ARB); 00049 F(GL_ALPHA32F_ARB); 00050 F(GL_INTENSITY); 00051 F(GL_INTENSITY4); 00052 F(GL_INTENSITY8); 00053 F(GL_INTENSITY12); 00054 F(GL_INTENSITY16); 00055 F(GL_INTENSITY16F_ARB); 00056 F(GL_INTENSITY32F_ARB); 00057 F(GL_LUMINANCE); 00058 F(GL_LUMINANCE4); 00059 F(GL_LUMINANCE8); 00060 F(GL_LUMINANCE12); 00061 F(GL_LUMINANCE16); 00062 F(GL_LUMINANCE16F_ARB); 00063 F(GL_LUMINANCE32F_ARB); 00064 F(GL_LUMINANCE_ALPHA); 00065 F(GL_LUMINANCE4_ALPHA4); 00066 F(GL_LUMINANCE12_ALPHA4); 00067 F(GL_LUMINANCE8_ALPHA8); 00068 F(GL_LUMINANCE6_ALPHA2); 00069 F(GL_LUMINANCE12_ALPHA12); 00070 F(GL_LUMINANCE16_ALPHA16); 00071 F(GL_LUMINANCE_ALPHA16F_ARB); 00072 F(GL_LUMINANCE_ALPHA32F_ARB); 00073 F(GL_RGB); 00074 F(GL_R3_G3_B2); 00075 F(GL_RGB4); 00076 F(GL_RGB5); 00077 F(GL_RGB8); 00078 F(GL_RGB10); 00079 F(GL_RGB12); 00080 F(GL_RGB16); 00081 F(GL_RGB16F_ARB); 00082 F(GL_RGB32F_ARB); 00083 F(GL_RGBA); 00084 F(GL_RGBA2); 00085 F(GL_RGBA4); 00086 F(GL_RGB5_A1); 00087 F(GL_RGBA8); 00088 F(GL_RGB10_A2); 00089 F(GL_RGBA12); 00090 F(GL_RGBA16); 00091 F(GL_RGBA16F_ARB); 00092 F(GL_RGBA32F_ARB); 00093 } 00094 uszprintf(str, sizeof str, "%x", format); 00095 return str; 00096 #undef F 00097 } 00098 00099 00100 00101 /* int __allegro_gl_get_num_channels(GLenum format) */ 00111 int __allegro_gl_get_num_channels(GLenum format) { 00112 00113 switch (format) { 00114 case 1: 00115 case GL_ALPHA: 00116 case GL_ALPHA4: 00117 case GL_ALPHA8: 00118 case GL_ALPHA12: 00119 case GL_ALPHA16: 00120 case GL_ALPHA16F_ARB: 00121 case GL_ALPHA32F_ARB: 00122 case GL_INTENSITY: 00123 case GL_INTENSITY4: 00124 case GL_INTENSITY8: 00125 case GL_INTENSITY12: 00126 case GL_INTENSITY16: 00127 case GL_INTENSITY16F_ARB: 00128 case GL_INTENSITY32F_ARB: 00129 case GL_LUMINANCE: 00130 case GL_LUMINANCE4: 00131 case GL_LUMINANCE8: 00132 case GL_LUMINANCE12: 00133 case GL_LUMINANCE16: 00134 case GL_LUMINANCE16F_ARB: 00135 case GL_LUMINANCE32F_ARB: 00136 return 1; 00137 case 2: 00138 case GL_LUMINANCE_ALPHA: 00139 case GL_LUMINANCE4_ALPHA4: 00140 case GL_LUMINANCE12_ALPHA4: 00141 case GL_LUMINANCE8_ALPHA8: 00142 case GL_LUMINANCE6_ALPHA2: 00143 case GL_LUMINANCE12_ALPHA12: 00144 case GL_LUMINANCE16_ALPHA16: 00145 case GL_LUMINANCE_ALPHA16F_ARB: 00146 case GL_LUMINANCE_ALPHA32F_ARB: 00147 return 2; 00148 case 3: 00149 case GL_RGB: 00150 case GL_R3_G3_B2: 00151 case GL_RGB4: 00152 case GL_RGB5: 00153 case GL_RGB8: 00154 case GL_RGB10: 00155 case GL_RGB12: 00156 case GL_RGB16: 00157 case GL_RGB16F_ARB: 00158 case GL_RGB32F_ARB: 00159 return 3; 00160 case 4: 00161 case GL_RGBA: 00162 case GL_RGBA2: 00163 case GL_RGBA4: 00164 case GL_RGB5_A1: 00165 case GL_RGBA8: 00166 case GL_RGB10_A2: 00167 case GL_RGBA12: 00168 case GL_RGBA16: 00169 case GL_RGBA16F_ARB: 00170 case GL_RGBA32F_ARB: 00171 return 4; 00172 default: 00173 return 0; 00174 } 00175 } 00176 00177 00178 00179 /* GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) */ 00190 GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) { 00191 00192 if (!bmp) { 00193 return -1; 00194 } 00195 00196 switch (bitmap_color_depth(bmp)) { 00197 case 32: 00198 if (flags 00199 & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) { 00200 return GL_RGBA8; 00201 } 00202 else { 00203 return GL_RGB8; 00204 } 00205 case 8: 00206 return GL_INTENSITY8; 00207 case 15: 00208 if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { 00209 return GL_RGB5_A1; 00210 } 00211 else { 00212 return GL_RGB5; 00213 } 00214 case 16: 00215 case 24: 00216 if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { 00217 return GL_RGBA8; 00218 } 00219 else { 00220 return GL_RGB8; 00221 } 00222 default: 00223 return -1; 00224 } 00225 00226 return -1; 00227 } 00228 00229 00230 00231 /* GLint allegro_gl_get_texture_format(BITMAP *bmp) */ 00248 GLint allegro_gl_get_texture_format(BITMAP *bmp) { 00249 00250 if (bmp && allegro_gl_opengl_internal_texture_format == -1) { 00251 return __allegro_gl_get_texture_format_ex(bmp, 00252 __allegro_gl_use_alpha ? AGL_TEXTURE_FORCE_ALPHA_INTERNAL : 0); 00253 } 00254 00255 return allegro_gl_opengl_internal_texture_format; 00256 } 00257 00258 00259 00260 /* GLint allegro_gl_set_texture_format(GLint format) */ 00282 GLint allegro_gl_set_texture_format(GLint format) { 00283 00284 GLint old = allegro_gl_opengl_internal_texture_format; 00285 allegro_gl_opengl_internal_texture_format = format; 00286 return old; 00287 } 00288 00289 00290 00291 /* GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) */ 00311 GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) { 00312 00313 int c = bitmap_color_depth(bmp); 00314 00315 switch (c) { 00316 00317 case 8: 00318 return __allegro_gl_texture_read_format[0]; 00319 00320 case 15: 00321 return __allegro_gl_texture_read_format[1]; 00322 00323 case 16: 00324 return __allegro_gl_texture_read_format[2]; 00325 00326 case 24: 00327 return __allegro_gl_texture_read_format[3]; 00328 00329 case 32: 00330 return __allegro_gl_texture_read_format[4]; 00331 00332 default: 00333 TRACE(PREFIX_E "get_bitmap_type: unhandled bitmap depth: %d\n", 00334 c); 00335 return -1; 00336 } 00337 } 00338 00339 00340 00341 /* GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) */ 00355 GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) { 00356 00357 int c = bitmap_color_depth(bmp); 00358 00359 switch (c) { 00360 00361 case 8: 00362 if (flags & AGL_TEXTURE_ALPHA_ONLY) { 00363 return GL_ALPHA; 00364 } 00365 else { 00366 return __allegro_gl_texture_components[0]; 00367 } 00368 00369 case 15: 00370 if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { 00371 return GL_RGBA; 00372 } 00373 else { 00374 return __allegro_gl_texture_components[1]; 00375 } 00376 00377 case 16: 00378 return __allegro_gl_texture_components[2]; 00379 00380 case 24: 00381 return __allegro_gl_texture_components[3]; 00382 00383 case 32: 00384 if (flags & (AGL_TEXTURE_HAS_ALPHA 00385 | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) { 00386 return GL_RGBA; 00387 } 00388 else { 00389 return __allegro_gl_texture_components[4]; 00390 } 00391 00392 default: 00393 TRACE(PREFIX_E "get_bitmap_color_format: unhandled bitmap " 00394 "depth: %d\n", c); 00395 return -1; 00396 } 00397 } 00398 00399 00400 00401 /* int allegro_gl_use_mipmapping(int enable) */ 00415 int allegro_gl_use_mipmapping(int enable) { 00416 00417 int old = allegro_gl_use_mipmapping_for_textures; 00418 allegro_gl_use_mipmapping_for_textures = enable; 00419 return old; 00420 } 00421 00422 00423 00424 /* int allegro_gl_use_alpha_channel(int enable) */ 00439 int allegro_gl_use_alpha_channel(int enable) { 00440 00441 int old = __allegro_gl_use_alpha; 00442 __allegro_gl_use_alpha = enable; 00443 return old; 00444 } 00445 00446 00447 00448 /* int allegro_gl_flip_texture(int enable) */ 00464 int allegro_gl_flip_texture(int enable) { 00465 00466 int old = __allegro_gl_flip_texture; 00467 __allegro_gl_flip_texture = enable; 00468 return old; 00469 } 00470 00471 00472 00473 /* int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLuint internal_format) */ 00495 int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, 00496 GLint internal_format) { 00497 00498 return (allegro_gl_make_texture_ex(flags | AGL_TEXTURE_CHECK_VALID_INTERNAL, 00499 bmp, internal_format) ? TRUE : FALSE); 00500 } 00501 00502 00503 00504 /* Convert flags from pre-0.2.0 to 0.2.0+ */ 00505 static int __allegro_gl_convert_flags(int flags) { 00506 00507 flags |= AGL_TEXTURE_RESCALE; 00508 00509 if (allegro_gl_use_mipmapping_for_textures) { 00510 flags |= AGL_TEXTURE_MIPMAP; 00511 } 00512 if (__allegro_gl_use_alpha) { 00513 flags |= AGL_TEXTURE_HAS_ALPHA; 00514 } 00515 if (__allegro_gl_flip_texture) { 00516 flags |= AGL_TEXTURE_FLIP; 00517 } 00518 00519 if (allegro_gl_opengl_internal_texture_format == GL_ALPHA4 00520 || allegro_gl_opengl_internal_texture_format == GL_ALPHA8 00521 || allegro_gl_opengl_internal_texture_format == GL_ALPHA12 00522 || allegro_gl_opengl_internal_texture_format == GL_ALPHA16 00523 || allegro_gl_opengl_internal_texture_format == GL_ALPHA 00524 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY4 00525 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY8 00526 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY12 00527 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY16 00528 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY 00529 || allegro_gl_opengl_internal_texture_format == 1) { 00530 flags |= AGL_TEXTURE_ALPHA_ONLY; 00531 } 00532 00533 return flags; 00534 } 00535 00536 00537 00538 /* int allegro_gl_check_texture(BITMAP *bmp) */ 00557 int allegro_gl_check_texture(BITMAP *bmp) { 00558 00559 int flags = __allegro_gl_convert_flags(0); 00560 00561 return allegro_gl_check_texture_ex(flags, bmp, 00562 allegro_gl_opengl_internal_texture_format); 00563 } 00564 00565 00566 00567 /* Integer log2 function. Not optimized for speed. */ 00568 static int log2i(int n) { 00569 00570 int k; 00571 00572 if (n < 1) { 00573 return -1; 00574 } 00575 00576 k = 0; 00577 while (n >>= 1) { 00578 k++; 00579 } 00580 00581 return k; 00582 } 00583 00584 00585 00586 /* BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, GLint *type, GLint *format) */ 00596 BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y, 00597 int w, int h, GLint *type, GLint *format) { 00598 00599 BITMAP *ret = 0, *temp = 0; 00600 00601 int need_rescale = 0; 00602 int need_alpha = 0; 00603 int need_flip = 0; 00604 int depth = bitmap_color_depth(bmp); 00605 int force_copy = 0; 00606 00607 const int old_w = w, old_h = h; 00608 00609 if (flags & AGL_TEXTURE_RESCALE) { 00610 00611 /* Check if rescaling is needed */ 00612 00613 /* NP2 is not supported, and the texture isn't a power-of-two. 00614 * Resize the next power of 2 00615 */ 00616 if (!allegro_gl_extensions_GL.ARB_texture_non_power_of_two 00617 && ((w & (w - 1)) || (h & (h - 1)))) { 00618 w = __allegro_gl_make_power_of_2(w); 00619 h = __allegro_gl_make_power_of_2(h); 00620 TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " 00621 "%ix%i to %ix%i due to non-power-of-2 source size.\n", 00622 old_w, old_h, w, h); 00623 need_rescale = 1; 00624 } 00625 00626 /* Don't go over the max texture size */ 00627 if (w > allegro_gl_info.max_texture_size) { 00628 w = allegro_gl_info.max_texture_size; 00629 TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " 00630 "%ix%i to %ix%i due to max supported size exceed.\n", 00631 old_w, old_h, w, h); 00632 need_rescale = 1; 00633 } 00634 00635 if (h > allegro_gl_info.max_texture_size) { 00636 h = allegro_gl_info.max_texture_size; 00637 TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " 00638 "%ix%i to %ix%i due to max supported size exceed.\n", 00639 old_w, old_h, w, h); 00640 need_rescale = 1; 00641 } 00642 00643 /* Voodoos don't support mipmaps for textures greater than 32x32. 00644 * If we're allowed to rescale, rescale the bitmap to 32x32. 00645 * XXX <rohannessian> Apparently, this is a bug in one version 00646 * of the Voodoo GL driver. Need to figure out a workaround 00647 * for that. 00648 */ 00649 if (allegro_gl_info.is_voodoo && (flags & AGL_TEXTURE_MIPMAP) 00650 && (w > 32 || h > 32)) { 00651 00652 w = MIN(32, w); 00653 h = MIN(32, h); 00654 00655 TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " 00656 "%ix%i to %ix%i due to Voodoo driver bug.\n", 00657 old_w, old_h, w, h); 00658 need_rescale = 1; 00659 } 00660 } 00661 00662 /* Matrox G200 cards have a bug where rectangular textures can't have 00663 * more than 4 levels of mipmaps (max_mip == 3). This doesn't seem 00664 * to affect square textures. 00665 * 00666 * Note: Using GLU to build the mipmaps seems to work. Maybe AGL is 00667 * doing something wrong? 00668 * 00669 * Workaround: Use GLU to build the mipmaps, and force depth to 24 or 00670 * 32. 00671 */ 00672 if ( allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP)) { 00673 int wl = log2i(w); 00674 int hl = log2i(h); 00675 00676 if (w != h && MAX(wl, hl) > 3 && depth < 24 00677 && !(flags & AGL_TEXTURE_ALPHA_ONLY)) { 00678 TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n"); 00679 depth = 24; 00680 } 00681 } 00682 00683 /* Do we need to flip the texture on the t axis? */ 00684 if (flags & AGL_TEXTURE_FLIP) { 00685 need_flip = 1; 00686 } 00687 00688 00689 /* If not supported, blit to a 24 bpp bitmap and try again 00690 */ 00691 if (*type == -1) { 00692 TRACE(PREFIX_W "munge_bitmap: using temporary 24bpp bitmap\n"); 00693 depth = 24; 00694 } 00695 00696 /* We need a texture that can be used for masked blits. 00697 * Insert an alpha channel if one is not there. 00698 * If it's already there, replace it by 0/1 as needed. 00699 */ 00700 if ((flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_ALPHA_ONLY)) { 00701 need_alpha = 1; 00702 00703 switch (depth) { 00704 case 15: 00705 if (!allegro_gl_extensions_GL.EXT_packed_pixels) { 00706 depth = 32; 00707 } 00708 break; 00709 case 8: 00710 case 16: 00711 case 24: 00712 case 32: 00713 depth = 32; 00714 break; 00715 } 00716 force_copy = 1; 00717 } 00718 00719 /* Allegro fills in 0 for the alpha channel. Matrox G200 seems to ignore 00720 * the internal format; so we need to drop down to 24-bpp if no alpha 00721 * will be needed. 00722 */ 00723 if (allegro_gl_info.is_matrox_g200 && !(flags & AGL_TEXTURE_MASKED) 00724 && !(flags & AGL_TEXTURE_HAS_ALPHA) && depth == 32) { 00725 TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n"); 00726 depth = 24; 00727 force_copy = 1; 00728 } 00729 00730 00731 /* Do we need to do a color depth conversion or bitmap copy? */ 00732 if (depth != bitmap_color_depth(bmp) || force_copy) { 00733 00734 TRACE(PREFIX_I "munge_bitmap: Need to perform depth conversion from %i " 00735 "to %i bpp.\n", bitmap_color_depth(bmp), depth); 00736 00737 temp = create_bitmap_ex(depth, bmp->w, bmp->h); 00738 00739 if (!temp) { 00740 TRACE(PREFIX_E "munge_bitmap: Unable to create temporary bitmap " 00741 "%ix%ix%i\n", bmp->w, bmp->h, depth); 00742 return NULL; 00743 } 00744 00745 /* XXX <rohannessian> Use palette conversion? 00746 */ 00747 if (bitmap_color_depth(bmp) == 8 && depth > 8) { 00748 int i, j; 00749 for (j = 0; j < bmp->h; j++) { 00750 for (i = 0; i < bmp->w; i++) { 00751 int c = _getpixel(bmp, i, j); 00752 putpixel(temp, i, j, makecol_depth(depth, c, c, c)); 00753 } 00754 } 00755 } 00756 else { 00757 blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h); 00758 } 00759 bmp = temp; 00760 00761 *format = __allegro_gl_get_bitmap_color_format(bmp, flags); 00762 *type = __allegro_gl_get_bitmap_type(bmp, flags); 00763 } 00764 00765 00766 00767 /* Nothing to do? */ 00768 if (!need_rescale && !need_alpha && !need_flip) { 00769 00770 TRACE(PREFIX_I "munge_bitmap: No need for munging - returning %p\n", 00771 temp); 00772 00773 /* Return depth-converte bitmap, if present */ 00774 if (temp) { 00775 return temp; 00776 } 00777 return NULL; 00778 } 00779 00780 ret = create_bitmap_ex(depth, w, h); 00781 00782 if (!ret) { 00783 TRACE(PREFIX_E "munge_bitmap: Unable to create result bitmap " 00784 "%ix%ix%i\n", w, h, depth); 00785 goto error; 00786 } 00787 00788 00789 /* No need to fill in bitmap if we're just making a query */ 00790 if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { 00791 if (temp) { 00792 destroy_bitmap(temp); 00793 } 00794 return ret; 00795 } 00796 00797 00798 /* Perform flip 00799 * I don't want to have to deal with *yet another* temporary bitmap 00800 * so instead, I fugde the line pointers around. 00801 * This will work because we require Allegro memory bitmaps anyway. 00802 */ 00803 if (need_flip) { 00804 int i; 00805 TRACE(PREFIX_I "munge_bitmap: Flipping bitmap.\n"); 00806 for (i = 0; i < bmp->h/2; i++) { 00807 unsigned char *l = bmp->line[i]; 00808 bmp->line[i] = bmp->line[bmp->h - i - 1]; 00809 bmp->line[bmp->h - i - 1] = l; 00810 } 00811 } 00812 00813 /* Rescale bitmap */ 00814 if (need_rescale) { 00815 TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap.\n"); 00816 stretch_blit(bmp, ret, x, y, old_w, old_h, 0, 0, ret->w, ret->h); 00817 } 00818 else { 00819 TRACE(PREFIX_I "munge_bitmap: Copying bitmap.\n"); 00820 blit(bmp, ret, x, y, 0, 0, w, h); 00821 } 00822 00823 /* Restore the original bitmap, if needed */ 00824 if (need_flip && !temp) { 00825 int i; 00826 TRACE(PREFIX_I "munge_bitmap: Unflipping bitmap.\n"); 00827 for (i = 0; i < bmp->h/2; i++) { 00828 unsigned char *l = bmp->line[i]; 00829 bmp->line[i] = bmp->line[bmp->h - i - 1]; 00830 bmp->line[bmp->h - i - 1] = l; 00831 } 00832 } 00833 00834 /* Insert alpha channel */ 00835 if (need_alpha) { 00836 int i, j; 00837 int mask = bitmap_mask_color(ret); 00838 00839 /* alpha mask for 5.5.5.1 pixels */ 00840 int alpha = (-1) ^ makecol_depth(depth, 255, 255, 255); 00841 00842 TRACE(PREFIX_I "munge_bitmap: Inserting alpha channel.\n"); 00843 00844 for (j = 0; j < h; j++) { 00845 for (i = 0; i < w; i++) { 00846 int pix; 00847 00848 switch (depth) { 00849 case 32: 00850 pix = _getpixel32(ret, i, j); 00851 00852 if (pix == mask) { 00853 pix = 0; 00854 } 00855 else if ((flags & AGL_TEXTURE_HAS_ALPHA) == 0) { 00856 int r, g, b; 00857 r = getr32(pix); 00858 g = getg32(pix); 00859 b = getb32(pix); 00860 pix = makeacol32(r, g, b, 255); 00861 } 00862 _putpixel32(ret, i, j, pix); 00863 break; 00864 case 15: 00865 pix = _getpixel16(ret, i, j); 00866 00867 if (pix == mask) { 00868 pix = 0; 00869 } 00870 else { 00871 pix |= alpha; 00872 } 00873 00874 _putpixel16(temp, i, j, pix); 00875 break; 00876 default: 00877 /* Shouldn't actually come here */ 00878 ASSERT(0); 00879 } 00880 } 00881 } 00882 } 00883 00884 00885 error: 00886 if (temp) { 00887 destroy_bitmap(temp); 00888 } 00889 00890 return ret; 00891 } 00892 00893 00894 00895 /* Perform the actual texture upload. Helper for agl_make_texture_ex(). 00896 */ 00897 static GLuint do_texture_upload(BITMAP *bmp, GLuint tex, GLint internal_format, 00898 GLint format, GLint type, int flags) { 00899 00900 int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(bmp)); 00901 GLint saved_row_length; 00902 GLint saved_alignment; 00903 GLenum target = GL_TEXTURE_2D; 00904 00905 glBindTexture(target, tex); 00906 00907 00908 /* Handle proxy texture checks */ 00909 if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { 00910 /* <bcoconni> allegro_gl_check_texture is broken with GL drivers based 00911 * on Mesa. It seems this is a Mesa bug... 00912 */ 00913 if (allegro_gl_info.is_mesa_driver) { 00914 AGL_LOG(1, "* Note * check_texture: Mesa driver detected: " 00915 "PROXY_TEXTURE_2D tests are skipped\n"); 00916 return tex; 00917 } 00918 else { 00919 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internal_format, 00920 bmp->w, bmp->h, 0, format, type, NULL); 00921 00922 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, 00923 GL_TEXTURE_COMPONENTS, &internal_format); 00924 00925 return (internal_format ? tex : 0); 00926 } 00927 } 00928 00929 00930 /* Set up pixel transfer mode */ 00931 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); 00932 glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment); 00933 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 00934 00935 TRACE(PREFIX_I "do_texture_upload: Making texture: bpp: %i\n", 00936 bitmap_color_depth(bmp)); 00937 00938 /* Generate mipmaps, if needed */ 00939 if (flags & AGL_TEXTURE_MIPMAP) { 00940 00941 if (allegro_gl_extensions_GL.SGIS_generate_mipmap) { 00942 /* Easy way out - let the driver do it ;) 00943 * We do need to set high-qual mipmap generation though. 00944 */ 00945 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); 00946 glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); 00947 TRACE(PREFIX_I "do_texture_upload: Using SGIS_generate_mipmap for " 00948 "mipmap generation.\n"); 00949 } 00950 else if (allegro_gl_info.is_matrox_g200 00951 && (flags & AGL_TEXTURE_MIPMAP) && (bitmap_color_depth(bmp) >= 24 00952 || bitmap_color_depth(bmp) == 8) 00953 && (bmp->w != bmp->h)) { 00954 00955 /* Matrox G200 has issues with our mipmapping code. Use GLU if we 00956 * can. 00957 */ 00958 TRACE(PREFIX_I "do_texture_upload: Using GLU for mipmaps.\n"); 00959 glPixelStorei(GL_UNPACK_ROW_LENGTH, bmp->h > 1 00960 ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel 00961 : bmp->w); 00962 glPixelStorei(GL_UNPACK_ROW_LENGTH, 00963 (bmp->line[1] - bmp->line[0]) / bytes_per_pixel); 00964 gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format, bmp->w, bmp->h, 00965 format, type, bmp->line[0]); 00966 } 00967 else { 00968 int w = bmp->w; 00969 int h = bmp->h; 00970 int depth = bitmap_color_depth(bmp); 00971 00972 /* The driver can't generate mipmaps for us. We can't rely on GLU 00973 * since the Win32 version doesn't support any of the new pixel 00974 * formats. Instead, we'll use our own downsampler (which only 00975 * has to work on Allegro BITMAPs) 00976 */ 00977 BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2); 00978 00979 /* We need to generate mipmaps up to 1x1 - compute the number 00980 * of levels we need. 00981 */ 00982 int num_levels = log2i(MAX(bmp->w, bmp->h)); 00983 00984 int i, x, y; 00985 00986 BITMAP *src, *dest; 00987 00988 TRACE(PREFIX_I "do_texture_upload: Using Allegro for " 00989 "mipmap generation.\n"); 00990 00991 if (!temp) { 00992 TRACE(PREFIX_E "do_texture_upload: Unable to create " 00993 "temporary bitmap sized %ix%ix%i for mipmap generation!", 00994 w / 2, h / 2, depth); 00995 tex = 0; 00996 goto end; 00997 } 00998 00999 src = bmp; 01000 dest = temp; 01001 01002 for (i = 1; i <= num_levels; i++) { 01003 01004 for (y = 0; y < h; y += 2) { 01005 for (x = 0; x < w; x += 2) { 01006 01007 int r, g, b, a; 01008 int pix[4]; 01009 int avg; 01010 01011 pix[0] = getpixel(src, x, y); 01012 pix[1] = getpixel(src, x + 1, y); 01013 pix[2] = getpixel(src, x, y + 1); 01014 pix[3] = getpixel(src, x + 1, y + 1); 01015 01016 if (w == 1) { 01017 pix[1] = pix[0]; 01018 pix[3] = pix[2]; 01019 } 01020 if (h == 1) { 01021 pix[2] = pix[0]; 01022 pix[3] = pix[1]; 01023 } 01024 01025 if (flags & AGL_TEXTURE_ALPHA_ONLY) { 01026 avg = (pix[0] + pix[1] + pix[2] + pix[3] + 2) / 4; 01027 } 01028 else { 01029 r = (getr_depth(depth, pix[0]) 01030 + getr_depth(depth, pix[1]) 01031 + getr_depth(depth, pix[2]) 01032 + getr_depth(depth, pix[3]) + 2) / 4; 01033 g = (getg_depth(depth, pix[0]) 01034 + getg_depth(depth, pix[1]) 01035 + getg_depth(depth, pix[2]) 01036 + getg_depth(depth, pix[3]) + 2) / 4; 01037 b = (getb_depth(depth, pix[0]) 01038 + getb_depth(depth, pix[1]) 01039 + getb_depth(depth, pix[2]) 01040 + getb_depth(depth, pix[3]) + 2) / 4; 01041 a = (geta_depth(depth, pix[0]) 01042 + geta_depth(depth, pix[1]) 01043 + geta_depth(depth, pix[2]) 01044 + geta_depth(depth, pix[3]) + 2) / 4; 01045 01046 avg = makeacol_depth(depth, r, g, b, a); 01047 } 01048 01049 putpixel(dest, x / 2, y / 2, avg); 01050 } 01051 } 01052 src = temp; 01053 01054 /* Note - we round down; we're still compatible with 01055 * ARB_texture_non_power_of_two. 01056 */ 01057 w = MAX(w / 2, 1); 01058 h = MAX(h / 2, 1); 01059 01060 TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n", 01061 (temp->h > 1) 01062 ? (long int)((temp->line[1] - temp->line[0]) / bytes_per_pixel) 01063 : temp->w); 01064 01065 glPixelStorei(GL_UNPACK_ROW_LENGTH, temp->h > 1 01066 ? (temp->line[1] - temp->line[0]) / bytes_per_pixel 01067 : temp->w); 01068 01069 glTexImage2D(GL_TEXTURE_2D, i, internal_format, 01070 w, h, 0, format, type, temp->line[0]); 01071 01072 TRACE(PREFIX_I "do_texture_upload: Mipmap level: %i, " 01073 "size: %i x %i\n", i, w, h); 01074 01075 TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level %i, " 01076 "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x." 01077 "\n", i, __allegro_gl_get_format_description(internal_format), 01078 bmp->w, bmp->h, format, type); 01079 } 01080 01081 destroy_bitmap(temp); 01082 } 01083 } 01084 01085 glPixelStorei(GL_UNPACK_ROW_LENGTH, (bmp->h > 1) 01086 ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel 01087 : bmp->w); 01088 01089 TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n", 01090 (bmp->h > 1) ? (long int)((bmp->line[1] - bmp->line[0]) / bytes_per_pixel) 01091 : bmp->w); 01092 01093 /* Upload the base texture */ 01094 glGetError(); 01095 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, 01096 bmp->w, bmp->h, 0, format, type, bmp->line[0]); 01097 01098 TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level 0, " 01099 "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x.\n", 01100 __allegro_gl_get_format_description(internal_format), 01101 bmp->w, bmp->h, format, type); 01102 01103 TRACE(PREFIX_I "do_texture_upload: GL Error code: 0x%x\n", glGetError()); 01104 01105 if (!(flags & AGL_TEXTURE_MIPMAP)) { 01106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 01107 } 01108 01109 end: 01110 /* Restore state */ 01111 glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); 01112 glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment); 01113 01114 return tex; 01115 } 01116 01117 01118 01119 /* GLuint allegro_gl_make_texture_ex(int flag, BITMAP *bmp, GLint internal_format) */ 01165 GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format) 01166 { 01167 GLuint tex = 0, ret = 0; 01168 BITMAP *temp = NULL; 01169 GLint type; 01170 GLint format; 01171 GLint old_tex; 01172 01173 /* Print the parameters */ 01174 #ifdef DEBUGMODE 01175 char buf[1024] = ""; 01176 # define PFLAG(name) if (flags & name) strcat(buf, #name "|"); 01177 PFLAG(AGL_TEXTURE_MIPMAP); 01178 PFLAG(AGL_TEXTURE_HAS_ALPHA); 01179 PFLAG(AGL_TEXTURE_FLIP); 01180 PFLAG(AGL_TEXTURE_MASKED); 01181 PFLAG(AGL_TEXTURE_RESCALE); 01182 PFLAG(AGL_TEXTURE_ALPHA_ONLY); 01183 # undef PFLAG 01184 01185 TRACE(PREFIX_I "make_texture_ex: flags: %s, bitmap %ix%i, %i bpp.\n", buf, 01186 bmp ? bmp->w : 0, bmp ? bmp->h : 0, 01187 bmp ? bitmap_color_depth(bmp) : 0); 01188 if (internal_format == -1) { 01189 TRACE(PREFIX_I "internalformat: AUTO\n"); 01190 } 01191 else { 01192 TRACE(PREFIX_I "internalformat: %s\n", 01193 __allegro_gl_get_format_description(internal_format)); 01194 } 01195 #endif 01196 01197 /* Basic parameter checks */ 01198 if (!__allegro_gl_valid_context) 01199 return 0; 01200 01201 if (!bmp) { 01202 return 0; 01203 } 01204 01205 glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_tex); 01206 01207 /* Voodoo cards don't seem to support mipmaps for textures over 32x32... 01208 */ 01209 if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) { 01210 /* Disable mipmapping if the user didn't allow us to rescale */ 01211 if (!(flags & AGL_TEXTURE_RESCALE)) { 01212 TRACE(PREFIX_I "make_texture_ex: Voodoo card detected && texture " 01213 "size > 32 texels && no rescaling. Disabling mipmaps.\n"); 01214 flags &= ~AGL_TEXTURE_MIPMAP; 01215 } 01216 } 01217 01218 /* Check the maximum texture size */ 01219 if (bmp->w > allegro_gl_info.max_texture_size 01220 || bmp->h > allegro_gl_info.max_texture_size) { 01221 if ((flags & AGL_TEXTURE_RESCALE) == 0) { 01222 TRACE(PREFIX_I "make_texture_ex: Max texture size exceeded but no " 01223 "rescaling allowed. Returning 0 (unsupported).\n"); 01224 return 0; 01225 } 01226 } 01227 01228 /* Check power-of-2 */ 01229 if (((bmp->w & (bmp->w - 1)) || (bmp->h & (bmp->h - 1))) 01230 && !(flags & AGL_TEXTURE_RESCALE) 01231 && !allegro_gl_extensions_GL.ARB_texture_non_power_of_two) { 01232 TRACE(PREFIX_I "make_texture_ex: Non-power-of-2 sized bitmap provided, " 01233 "no rescaling allowed, and ARB_texture_non_power_of_two " 01234 "unsupported. Returning 0 (unsupported).\n"); 01235 return 0; 01236 } 01237 01238 01239 /* Get OpenGL format and type for this pixel data */ 01240 format = __allegro_gl_get_bitmap_color_format(bmp, flags); 01241 type = __allegro_gl_get_bitmap_type(bmp, flags); 01242 01243 if (flags & AGL_TEXTURE_ALPHA_ONLY) { 01244 type = GL_UNSIGNED_BYTE; 01245 if (internal_format == GL_ALPHA || internal_format == GL_ALPHA4 01246 || internal_format == GL_ALPHA8) { 01247 format = GL_ALPHA; 01248 } 01249 else if (internal_format == GL_INTENSITY 01250 || internal_format == GL_INTENSITY4 01251 || internal_format == GL_INTENSITY8) { 01252 format = GL_RED; 01253 } 01254 else if (internal_format == GL_LUMINANCE 01255 || internal_format == GL_LUMINANCE4 01256 || internal_format == GL_LUMINANCE8) { 01257 format = GL_LUMINANCE; 01258 } 01259 01260 /* Alpha bitmaps must be 8-bpp */ 01261 if (bitmap_color_depth(bmp) != 8) { 01262 return 0; 01263 } 01264 } 01265 01266 if (flags & AGL_TEXTURE_MASKED) { 01267 flags |= AGL_TEXTURE_FORCE_ALPHA_INTERNAL; 01268 } 01269 01270 TRACE(PREFIX_I "make_texture_ex: Preselected texture format: %s, " 01271 "type: 0x%x\n", __allegro_gl_get_format_description(format), type); 01272 01273 /* Munge the bitmap if needed (rescaling, alpha channel, etc) */ 01274 temp = __allegro_gl_munge_bitmap(flags, bmp, 0, 0, bmp->w, bmp->h, 01275 &type, &format); 01276 if (temp) { 01277 bmp = temp; 01278 } 01279 01280 if (internal_format == -1) { 01281 internal_format = __allegro_gl_get_texture_format_ex(bmp, flags); 01282 TRACE(PREFIX_I "make_texture_ex: Picked internalformat: %s\n", 01283 __allegro_gl_get_format_description(internal_format)); 01284 } 01285 01286 if (internal_format == -1) { 01287 TRACE(PREFIX_E "make_texture_ex: Invalid internal format!: " 01288 "%s\n", __allegro_gl_get_format_description(internal_format)); 01289 goto end; 01290 } 01291 01292 TRACE(PREFIX_I "make_texture_ex: dest format=%s, source format=%s, " 01293 "type=0x%x\n", __allegro_gl_get_format_description(internal_format), 01294 __allegro_gl_get_format_description(format), (int)type); 01295 01296 01297 /* ATI Radeon 7000 inverts R and B components when generating mipmaps and 01298 * the internal format is GL_RGB8, but only on mipmaps. Instead, we'll use 01299 * GL_RGBA8. This works for bitmaps of depth <= 24. For 32-bpp bitmaps, 01300 * some additional tricks are needed: We must fill in alpha with 255. 01301 */ 01302 if (allegro_gl_info.is_ati_radeon_7000 && (flags & AGL_TEXTURE_MIPMAP) 01303 && internal_format == GL_RGB8 01304 && allegro_gl_extensions_GL.SGIS_generate_mipmap) { 01305 01306 int i, j; 01307 int depth = bitmap_color_depth(bmp); 01308 01309 TRACE(PREFIX_I "make_texture_ex: ATI Radeon 7000 detected, mipmapping " 01310 "used, SGIS_generate_mipmap available and selected " 01311 "internalformat is GL_RGB8 but format is GL_RGBA. Working around " 01312 "ATI driver bug by upgrading bitmap to 32-bpp and using GL_RGBA8 " 01313 "instead.\n"); 01314 01315 if (depth == 32) { 01316 01317 /* Create temp bitmap if not already there */ 01318 if (!temp) { 01319 temp = create_bitmap_ex(depth, bmp->w, bmp->h); 01320 if (!temp) { 01321 TRACE(PREFIX_E "make_texture_ex: Unable to allocate " 01322 "memory for temporary bitmap (Radeon 7000 path)!\n"); 01323 goto end; 01324 } 01325 blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h); 01326 bmp = temp; 01327 } 01328 01329 /* Slow path, until ATI finally gets around to fixing their 01330 * drivers. 01331 * 01332 * Note: If destination internal format was GL_RGBx, then no masking 01333 * code is needed. 01334 */ 01335 for (j = 0; j < bmp->h; j++) { 01336 for (i = 0; i < bmp->w; i++) { 01337 int pix = _getpixel32(bmp, i, j); 01338 _putpixel32(bmp, i, j, 01339 makeacol32(getr32(pix), getg32(pix), getb32(pix), 255)); 01340 } 01341 } 01342 } 01343 internal_format = GL_RGBA8; 01344 } 01345 01346 01347 /* Generate the texture */ 01348 glGenTextures(1, &tex); 01349 if (!tex) { 01350 TRACE(PREFIX_E "make_texture_ex: Unable to create GL texture!\n"); 01351 goto end; 01352 } 01353 01354 ret = do_texture_upload(bmp, tex, internal_format, format, type, flags); 01355 01356 end: 01357 if (temp) { 01358 destroy_bitmap(temp); 01359 } 01360 01361 if (!ret && tex) { 01362 glDeleteTextures(1, &tex); 01363 } 01364 01365 glBindTexture(GL_TEXTURE_2D, old_tex); 01366 01367 return tex; 01368 } 01369 01370 01371 01372 01373 01374 /* GLuint allegro_gl_make_texture(BITMAP *bmp) */ 01383 GLuint allegro_gl_make_texture(BITMAP *bmp) { 01384 01385 int flags = __allegro_gl_convert_flags(0); 01386 01387 return allegro_gl_make_texture_ex(flags, bmp, 01388 allegro_gl_opengl_internal_texture_format); 01389 } 01390 01391 01392 01393 /* GLuint allegro_gl_make_masked_texture(BITMAP *bmp) */ 01402 GLuint allegro_gl_make_masked_texture(BITMAP *bmp) { 01403 01404 int flags = __allegro_gl_convert_flags(AGL_TEXTURE_MASKED); 01405 01406 return allegro_gl_make_texture_ex(flags, bmp, 01407 allegro_gl_opengl_internal_texture_format); 01408 } 01409 01410 01411 01412 /* GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) */ 01433 GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) { 01434 01435 int flags = __allegro_gl_convert_flags(0); 01436 return __allegro_gl_get_bitmap_type(bmp, flags); 01437 } 01438 01439 01440 01441 /* GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) */ 01456 GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) { 01457 01458 int flags = __allegro_gl_convert_flags(0); 01459 return __allegro_gl_get_bitmap_color_format(bmp, flags); 01460 } 01461