texture.c

Go to the documentation of this file.
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 

Generated on Sun Nov 11 15:52:55 2007 for AllegroGL by  doxygen 1.5.2