00001
00002
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00612
00613
00614
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
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
00644
00645
00646
00647
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
00663
00664
00665
00666
00667
00668
00669
00670
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
00684 if (flags & AGL_TEXTURE_FLIP) {
00685 need_flip = 1;
00686 }
00687
00688
00689
00690
00691 if (*type == -1) {
00692 TRACE(PREFIX_W "munge_bitmap: using temporary 24bpp bitmap\n");
00693 depth = 24;
00694 }
00695
00696
00697
00698
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
00720
00721
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
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
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
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
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
00790 if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
00791 if (temp) {
00792 destroy_bitmap(temp);
00793 }
00794 return ret;
00795 }
00796
00797
00798
00799
00800
00801
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
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
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
00835 if (need_alpha) {
00836 int i, j;
00837 int mask = bitmap_mask_color(ret);
00838
00839
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
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
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
00909 if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
00910
00911
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
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
00939 if (flags & AGL_TEXTURE_MIPMAP) {
00940
00941 if (allegro_gl_extensions_GL.SGIS_generate_mipmap) {
00942
00943
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
00956
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
00973
00974
00975
00976
00977 BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2);
00978
00979
00980
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
01055
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
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
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
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
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
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
01208
01209 if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) {
01210
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
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
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
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
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
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
01298
01299
01300
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
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
01330
01331
01332
01333
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
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
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
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
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
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