Main Page | Modules | File List | Globals | Related Pages

texture.c

Go to the documentation of this file.
00001 
00005 #include <string.h>
00006 
00007 #include "alleggl.h"
00008 #include "allglint.h"
00009 
00010 #include <allegro/internal/aintern.h>
00011 
00012 #ifdef ALLEGRO_MACOSX
00013 #include <OpenGL/glu.h>
00014 #else
00015 #include <GL/glu.h>
00016 #endif
00017 
00018 static GLint allegro_gl_opengl_internal_texture_format = -1;
00019 static int allegro_gl_use_mipmapping_for_textures = 0;
00020 int __allegro_gl_use_alpha = FALSE;
00021 int __allegro_gl_flip_texture = TRUE;
00022 GLint __allegro_gl_texture_read_format[5];
00023 GLint __allegro_gl_texture_components[5];
00024 
00025 
00026 
00027 /* GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) */
00038 GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) {
00039 
00040     if (!bmp) {
00041         return -1;
00042     }
00043 
00044     switch (bitmap_color_depth(bmp)) {
00045         case 32:
00046             if (flags
00047                  & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
00048                 return GL_RGBA8;
00049             }
00050             else {
00051                 return GL_RGB8;
00052             }
00053         case 8:
00054             return GL_INTENSITY8;
00055         case 15:
00056             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00057                 return GL_RGB5_A1;
00058             }
00059             else {
00060                 return GL_RGB5;
00061             }
00062         case 16:
00063         case 24:
00064             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00065                 return GL_RGBA8;
00066             }
00067             else {
00068                 return GL_RGB8;
00069             }
00070         default:
00071             return -1;
00072     }
00073 
00074     return -1;
00075 }
00076 
00077 
00078 
00079 /* GLint allegro_gl_get_texture_format(BITMAP *bmp) */
00096 GLint allegro_gl_get_texture_format(BITMAP *bmp) {
00097 
00098     if (bmp && allegro_gl_opengl_internal_texture_format == -1) {
00099         return __allegro_gl_get_texture_format_ex(bmp,
00100                 __allegro_gl_use_alpha ? AGL_TEXTURE_FORCE_ALPHA_INTERNAL : 0);
00101     }
00102     
00103     return allegro_gl_opengl_internal_texture_format;
00104 }
00105 
00106 
00107 
00108 /* GLint allegro_gl_set_texture_format(GLint format) */
00130 GLint allegro_gl_set_texture_format(GLint format) {
00131 
00132     GLint old = allegro_gl_opengl_internal_texture_format;
00133     allegro_gl_opengl_internal_texture_format = format;
00134     return old;
00135 }
00136 
00137 
00138 
00139 /* GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) */
00159 GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) {
00160 
00161     int c = bitmap_color_depth(bmp);
00162 
00163     switch (c) {
00164 
00165         case 8:
00166             return __allegro_gl_texture_read_format[0];
00167 
00168         case 15:
00169             return __allegro_gl_texture_read_format[1];
00170 
00171         case 16:
00172             return __allegro_gl_texture_read_format[2];
00173 
00174         case 24:
00175             return __allegro_gl_texture_read_format[3];
00176 
00177         case 32:
00178             return __allegro_gl_texture_read_format[4];
00179     
00180         default:
00181             TRACE("** ERROR ** get_bitmap_type: unhandled bitmap depth: %d\n",
00182                   c);
00183             return -1;
00184     }
00185 }
00186 
00187 
00188 
00189 /* GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) */
00203 GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) {
00204 
00205     int c = bitmap_color_depth(bmp);
00206 
00207     switch (c) {
00208 
00209         case 8:
00210             if (flags & AGL_TEXTURE_ALPHA_ONLY) {
00211                 return GL_ALPHA;
00212             }
00213             else {
00214                 return __allegro_gl_texture_components[0];
00215             }
00216 
00217         case 15:
00218             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00219                 return GL_RGBA;
00220             }
00221             else {
00222                 return __allegro_gl_texture_components[1];
00223             }
00224 
00225         case 16:
00226             return __allegro_gl_texture_components[2];
00227 
00228         case 24:
00229             return __allegro_gl_texture_components[3];
00230 
00231         case 32:
00232             if (flags & (AGL_TEXTURE_HAS_ALPHA
00233                        | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
00234                 return GL_RGBA;
00235             }
00236             else {
00237                 return __allegro_gl_texture_components[4];
00238             }
00239     
00240         default:
00241             TRACE("** ERROR ** get_bitmap_color_format: unhandled bitmap "
00242                   "depth: %d\n", c);
00243             return -1;
00244     }
00245 }
00246 
00247 
00248 
00249 /* int allegro_gl_use_mipmapping(int enable) */
00263 int allegro_gl_use_mipmapping(int enable) {
00264 
00265     int old = allegro_gl_use_mipmapping_for_textures;
00266     allegro_gl_use_mipmapping_for_textures = enable;
00267     return old;
00268 }
00269     
00270 
00271 
00272 /* int allegro_gl_use_alpha_channel(int enable) */
00287 int allegro_gl_use_alpha_channel(int enable) {
00288 
00289     int old = __allegro_gl_use_alpha;
00290     __allegro_gl_use_alpha = enable;
00291     return old;
00292 }
00293     
00294 
00295 
00296 /* int allegro_gl_flip_texture(int enable) */
00312 int allegro_gl_flip_texture(int enable) {
00313 
00314     int old = __allegro_gl_flip_texture;
00315     __allegro_gl_flip_texture = enable;
00316     return old;
00317 }
00318     
00319 
00320 
00321 /* int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLuint internal_format) */
00343 int allegro_gl_check_texture_ex(int flags, BITMAP *bmp,
00344                                    GLint internal_format) {
00345 
00346     return (allegro_gl_make_texture_ex(flags | AGL_TEXTURE_CHECK_VALID_INTERNAL,
00347                                        bmp, internal_format) ? TRUE : FALSE);
00348 }
00349 
00350 
00351 
00352 /* Convert flags from pre-0.2.0 to 0.2.0+ */
00353 static int __allegro_gl_convert_flags(int flags) {
00354 
00355     flags |= AGL_TEXTURE_RESCALE;
00356 
00357     if (allegro_gl_use_mipmapping_for_textures) {
00358         flags |= AGL_TEXTURE_MIPMAP;
00359     }
00360     if (__allegro_gl_use_alpha) {
00361         flags |= AGL_TEXTURE_HAS_ALPHA;
00362     }
00363     if (__allegro_gl_flip_texture) {
00364         flags |= AGL_TEXTURE_FLIP;
00365     }
00366 
00367     if (allegro_gl_opengl_internal_texture_format == GL_ALPHA4
00368      || allegro_gl_opengl_internal_texture_format == GL_ALPHA8
00369      || allegro_gl_opengl_internal_texture_format == GL_ALPHA12
00370      || allegro_gl_opengl_internal_texture_format == GL_ALPHA16
00371      || allegro_gl_opengl_internal_texture_format == GL_ALPHA
00372      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY4
00373      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY8
00374      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY12
00375      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY16
00376      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY
00377      || allegro_gl_opengl_internal_texture_format == 1) {
00378         flags |= AGL_TEXTURE_ALPHA_ONLY;
00379     }
00380 
00381     return flags;
00382 }
00383 
00384 
00385 
00386 /* int allegro_gl_check_texture(BITMAP *bmp) */
00405 int allegro_gl_check_texture(BITMAP *bmp) {
00406 
00407     int flags = __allegro_gl_convert_flags(0);
00408     
00409     return allegro_gl_check_texture_ex(flags, bmp,
00410                                      allegro_gl_opengl_internal_texture_format);
00411 }
00412 
00413 
00414 
00415 /* Integer log2 function. Not optimized for speed. */
00416 static int log2i(int n) {
00417     
00418     int k;
00419     
00420     if (n < 1) {
00421         return -1;
00422     }
00423 
00424     k = 0;
00425     while (n >>= 1) {
00426         k++;
00427     }
00428 
00429     return k;
00430 }
00431 
00432 
00433 
00434 /* BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, GLint *type, GLint *format) */
00444 BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y,
00445                                   int w, int h, GLint *type, GLint *format) {
00446     
00447     BITMAP *ret = 0, *temp = 0;
00448 
00449     int need_rescale = 0;
00450     int need_alpha   = 0;
00451     int need_flip    = 0;
00452     int depth = bitmap_color_depth(bmp);
00453     int force_copy   = 0;
00454 
00455     const int old_w = w, old_h = h;
00456 
00457     if (flags & AGL_TEXTURE_RESCALE) {
00458         
00459         /* Check if rescaling is needed */
00460         
00461         /* XXX <rohannessian> Insert ARB_np2 and NV_texture_rectangle checks
00462          * here
00463          */
00464         if ((w & (w - 1)) || (h & (h - 1))) {
00465             need_rescale = 1;
00466         }
00467         
00468         /* Voodoos don't support mipmaps for textures greater than 32x32.
00469          * If we're allowed to rescale, rescale the bitmap to 32x32.
00470          */
00471         if (  allegro_gl_info.is_voodoo && (flags & AGL_TEXTURE_MIPMAP)
00472           && (w > 32 || h > 32)) {
00473 
00474             w = MIN(32, w);
00475             h = MIN(32, h);
00476             need_rescale = 1;
00477         }
00478     }
00479 
00480     /* Matrox G200 cards have a bug where rectangular textures can't have
00481      * more than 4 levels of mipmaps (max_mip == 3). This doesn't seem
00482      * to affect square textures.
00483      *
00484      * Note: Using GLU to build the mipmaps seems to work. Maybe AGL is
00485      * doing something wrong?
00486      *
00487      * Workaround: Use GLU to build the mipmaps, and force depth to 24 or
00488      * 32.
00489      */
00490     if ( allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP)) {
00491         int wl = log2i(w);
00492         int hl = log2i(h);
00493 
00494         if (w != h && MAX(wl, hl) > 3 && depth < 24
00495          && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
00496             TRACE("* Note * munge_bitmap: G200 path in use.\n");
00497             depth = 24;
00498         }
00499     }
00500     
00501     if (flags & AGL_TEXTURE_FLIP) {
00502         need_flip = 1;
00503     }
00504 
00505     /* If not supported, blit to a 24 bpp bitmap and try again
00506      */
00507     if (*type == -1) {
00508         TRACE("** Warning ** munge_bitmap: using temporary 24bpp bitmap\n");
00509 
00510         depth   = 24;
00511     }
00512 
00513     if ((flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
00514         need_alpha = 1;
00515 
00516         switch (depth) {
00517         case 15:
00518             if (!allegro_gl_extensions_GL.EXT_packed_pixels) {
00519                 depth = 32;
00520             }
00521             break;
00522         case 8:
00523         case 16:
00524         case 24:
00525         case 32:
00526             depth = 32;
00527             break;
00528         }
00529         force_copy = 1;
00530     }
00531 
00532     /* Allegro fills in 0 for the alpha channel. Matrox G200 seems to ignore
00533      * the internal format; so we need to drop down to 24-bpp if no alpha
00534      * will be needed.
00535      */
00536     if (allegro_gl_info.is_matrox_g200 && !(flags & AGL_TEXTURE_MASKED)
00537        && !(flags & AGL_TEXTURE_HAS_ALPHA) && depth == 32) {
00538         depth = 24;
00539         force_copy = 1;
00540     }
00541 
00542     
00543     /* Do we need to do a color depth conversion or bitmap copy? */
00544     if (depth != bitmap_color_depth(bmp) || force_copy) {
00545 
00546         TRACE("* Note * munge_bitmap: Need to perform depth conversion from %i "
00547               "to %i bpp.\n", bitmap_color_depth(bmp), depth);
00548 
00549         temp = create_bitmap_ex(depth, bmp->w, bmp->h);
00550 
00551         if (!temp) {
00552             TRACE("** ERROR ** munge_bitmap: Unable to create temporary bitmap "
00553                   "%ix%ix%i\n", bmp->w, bmp->h, depth);
00554             return NULL;
00555         }
00556 
00557         if (bitmap_color_depth(bmp) == 8 && depth > 8) {
00558             int i, j;
00559             for (j = 0; j < bmp->h; j++) {
00560                 for (i = 0; i < bmp->w; i++) {
00561                     int c = _getpixel(bmp, i, j);
00562                     putpixel(temp, i, j, makecol_depth(depth, c, c, c));
00563                 }
00564             }
00565         }
00566         else {
00567             blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
00568         }
00569         bmp = temp;
00570 
00571         *format = __allegro_gl_get_bitmap_color_format(bmp, flags);
00572         *type = __allegro_gl_get_bitmap_type(bmp, flags);
00573     }
00574 
00575 
00576     /* Compute new bitmap size */
00577     w = __allegro_gl_make_power_of_2(w);
00578     h = __allegro_gl_make_power_of_2(h);
00579 
00580 
00581     /* Nothing to do? */
00582     if (!need_rescale && !need_alpha && !need_flip) {
00583 
00584         TRACE("* Note * munge_bitmap: No need for munging - returning %p\n",
00585               temp);
00586         
00587         /* Return depth-converte bitmap, if present */
00588         if (temp) {
00589             return temp;
00590         }
00591         return NULL;
00592     }
00593 
00594     ret = create_bitmap_ex(depth, w, h);
00595     
00596     if (!ret) {
00597         TRACE("** ERROR ** munge_bitmap: Unable to create result bitmap "
00598               "%ix%ix%i\n", w, h, depth);
00599         goto error;
00600     }
00601 
00602 
00603     /* No need to fill in bitmap if we're just making a query */
00604     if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
00605         return ret;
00606     }
00607 
00608 
00609     /* Perform flip
00610      * I don't want to have to deal with *yet another* temporary bitmap
00611      * so instead, I fugde the line pointers around.
00612      * This will work because we require Allegro memory bitmaps anyway.
00613      */
00614     if (need_flip) {
00615         int i;
00616         for (i = 0; i < bmp->h/2; i++) {
00617             char *l = bmp->line[i];
00618             bmp->line[i] = bmp->line[bmp->h - i - 1];
00619             bmp->line[bmp->h - i - 1] = l;
00620         }
00621     }
00622     
00623     /* Rescale bitmap */
00624     if (need_rescale) {
00625         stretch_blit(bmp, ret, x, y, old_w, old_h, 0, 0, ret->w, ret->h);
00626     }
00627     else {
00628         blit(bmp, ret, x, y, 0, 0, w, h);
00629     }
00630 
00631     /* Restore the original bitmap, if needed */
00632     if (need_flip && !temp) {
00633         int i;
00634         for (i = 0; i < bmp->h/2; i++) {
00635             char *l = bmp->line[i];
00636             bmp->line[i] = bmp->line[bmp->h - i - 1];
00637             bmp->line[bmp->h - i - 1] = l;
00638         }
00639     }
00640     
00641     /* Insert alpha channel */
00642     if (need_alpha) {
00643         int i, j;
00644         int mask = bitmap_mask_color(ret);
00645 
00646         /* alpha mask for 5.5.5.1 pixels */
00647         int alpha = (-1) ^ makecol_depth(depth, 255, 255, 255);
00648 
00649         for (j = 0; j < h; j++) {
00650             for (i = 0; i < w; i++) {
00651                 int pix;
00652                 
00653                 switch (depth) {
00654                 case 32:
00655                     pix = _getpixel32(ret, i, j);
00656 
00657                     if (pix == mask) {
00658                         pix = 0;
00659                     }
00660                     else if ((flags & AGL_TEXTURE_HAS_ALPHA) == 0) {
00661                         int r, g, b;
00662                         r = getr32(pix);
00663                         g = getg32(pix);
00664                         b = getb32(pix);
00665                         pix = makeacol32(r, g, b, 255);
00666                     }
00667                     _putpixel32(ret, i, j, pix);
00668                     break;
00669                 case 15: 
00670                     pix = _getpixel16(ret, i, j);
00671 
00672                     if (pix == mask) {
00673                         pix = 0;
00674                     }
00675                     else {
00676                         pix = ((getr15(pix) >> 3) << _rgb_r_shift_15)
00677                             | ((getg15(pix) >> 3) << _rgb_g_shift_15)
00678                             | ((getb15(pix) >> 3) << _rgb_b_shift_15)
00679                             | alpha;
00680                     }
00681                     
00682                     _putpixel16(temp, i, j, pix);
00683                     break;
00684                 default:
00685                     /* Shouldn't actually come here */
00686                     ASSERT(0);
00687                 }
00688             }
00689         }
00690     }
00691 
00692 
00693 error:
00694     if (temp) {
00695         destroy_bitmap(temp);
00696     }
00697 
00698     return ret;
00699 }
00700 
00701 
00702 
00703 /* Perform the actual texture upload. Helper for agl_make_texture_ex().
00704  */
00705 static GLuint do_texture_upload(BITMAP *bmp, GLuint tex, GLint internal_format,
00706                               GLint format, GLint type, int flags) {
00707 
00708     int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(bmp));
00709     GLint saved_row_length;
00710     GLint saved_alignment;
00711     GLenum target = GL_TEXTURE_2D;
00712 
00713     glBindTexture(target, tex);
00714     
00715 
00716     /* Handle proxy texture checks */
00717     if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { 
00718         /* <bcoconni> allegro_gl_check_texture is broken with GL drivers based
00719          *  on Mesa. It seems this is a Mesa bug...
00720          */
00721         if (allegro_gl_info.is_mesa_driver) {
00722             AGL_LOG(1, "* Note * check_texture: Mesa driver detected: "
00723                    "PROXY_TEXTURE_2D tests are skipped\n");
00724             return tex;
00725         }
00726         else {
00727             glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internal_format,
00728                          bmp->w, bmp->h, 0, format, type, NULL);
00729 
00730             glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
00731                                      GL_TEXTURE_COMPONENTS, &internal_format);
00732 
00733             return (internal_format ? tex : 0);
00734         }
00735     }
00736     
00737 
00738     /* Set up pixel transfer mode */
00739     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00740     glGetIntegerv(GL_UNPACK_ALIGNMENT,  &saved_alignment);
00741     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00742 
00743     TRACE("* Note * do_texture_upload: Making texture: bpp: %i\n",
00744           bitmap_color_depth(bmp));
00745 
00746     /* Generate mipmaps, if needed */
00747     if (flags & AGL_TEXTURE_MIPMAP) {
00748         
00749         if (allegro_gl_extensions_GL.SGIS_generate_mipmap) {
00750             /* Easy way out - let the driver do it ;) */
00751             glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
00752         }
00753         else if (allegro_gl_info.is_matrox_g200
00754              && (flags & AGL_TEXTURE_MIPMAP) && (bitmap_color_depth(bmp) >= 24
00755                 || bitmap_color_depth(bmp) == 8)
00756              && (bmp->w != bmp->h)) {
00757                 
00758             /* Matrox G200 has issues with our mipmapping code. Use GLU if we
00759              * can.
00760              */
00761             TRACE("* Note * do_texture_upload: Using GLU for mipmaps.\n");
00762             glPixelStorei(GL_UNPACK_ROW_LENGTH,
00763                                (bmp->line[1] - bmp->line[0]) / bytes_per_pixel);
00764             gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format, bmp->w, bmp->h,
00765                               format, type, bmp->line[0]);
00766         }
00767         else {
00768             int w = bmp->w;
00769             int h = bmp->h;
00770             int depth = bitmap_color_depth(bmp);
00771             
00772             /* The driver can't generate mipmaps for us. We can't rely on GLU
00773              * since the Win32 version doesn't support any of the new pixel
00774              * formats. Instead, we'll use our own downsampler (which only
00775              * has to work on Allegro BITMAPs)
00776              */
00777             BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2);
00778 
00779             /* We need to generate mipmaps up to 1x1 - compute the number
00780              * of levels we need.
00781              */
00782             int num_levels = log2i(MAX(bmp->w, bmp->h));
00783 
00784             int i, x, y;
00785 
00786             BITMAP *src, *dest;
00787 
00788             if (!temp) {
00789                 TRACE("** ERROR ** do_texture_upload: Unable to create "
00790                       "temporary bitmap sized %ix%ix%i for mipmap generation!",
00791                       w / 2, h / 2, depth);
00792                 tex = 0;
00793                 goto end;
00794             }
00795 
00796             src = bmp;
00797             dest = temp;
00798             
00799             for (i = 1; i <= num_levels; i++) {
00800 
00801                 for (y = 0; y < h; y += 2) {
00802                     for (x = 0; x < w; x += 2) {
00803 
00804                         int r, g, b, a;
00805                         int pix[4];
00806                         int avg;
00807                         
00808                         pix[0] = getpixel(src, x,     y);
00809                         pix[1] = getpixel(src, x + 1, y);
00810                         pix[2] = getpixel(src, x,     y + 1);
00811                         pix[3] = getpixel(src, x + 1, y + 1);
00812 
00813                         if (w == 1) {
00814                             pix[1] = pix[0];
00815                             pix[3] = pix[2];
00816                         }
00817                         if (h == 1) {
00818                             pix[2] = pix[0];
00819                             pix[3] = pix[1];
00820                         }
00821 
00822                         if (flags & AGL_TEXTURE_ALPHA_ONLY) {
00823                             avg = (pix[0] + pix[1] + pix[2] + pix[3] + 2) / 4;
00824                         }
00825                         else {
00826                             r = (getr_depth(depth, pix[0])
00827                                + getr_depth(depth, pix[1])
00828                                + getr_depth(depth, pix[2])
00829                                + getr_depth(depth, pix[3]) + 2) / 4;
00830                             g = (getg_depth(depth, pix[0])
00831                                + getg_depth(depth, pix[1])
00832                                + getg_depth(depth, pix[2])
00833                                + getg_depth(depth, pix[3]) + 2) / 4;
00834                             b = (getb_depth(depth, pix[0])
00835                                + getb_depth(depth, pix[1])
00836                                + getb_depth(depth, pix[2])
00837                                + getb_depth(depth, pix[3]) + 2) / 4;
00838                             a = (geta_depth(depth, pix[0])
00839                                + geta_depth(depth, pix[1])
00840                                + geta_depth(depth, pix[2])
00841                                + geta_depth(depth, pix[3]) + 2) / 4;
00842 
00843                             avg = makeacol_depth(depth, r, g, b, a);
00844                         }
00845 
00846                         putpixel(dest, x / 2, y / 2, avg);
00847                     }
00848                 }
00849                 src = temp;
00850 
00851                 /* Note - we round down; we're still compatible with
00852                  * ARB_texture_non_power_of_two.
00853                  */
00854                 w = MAX(w / 2, 1);
00855                 h = MAX(h / 2, 1);
00856 
00857                 glPixelStorei(GL_UNPACK_ROW_LENGTH,
00858                              (temp->line[1] - temp->line[0]) / bytes_per_pixel);
00859                 
00860                 glTexImage2D(GL_TEXTURE_2D, i, internal_format,
00861                     w, h, 0, format, type, temp->line[0]);
00862 
00863                 TRACE("* Note * do_texture_upload: Mipmap level: %i, "
00864                       "size: %i x %i\n", i, w, h);
00865             }
00866 
00867             destroy_bitmap(temp);
00868         }
00869     }
00870 
00871     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00872                                (bmp->line[1] - bmp->line[0]) / bytes_per_pixel);
00873 
00874     /* Upload the base texture */
00875     glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
00876         bmp->w, bmp->h, 0, format, type, bmp->line[0]);
00877 
00878     if (!(flags & AGL_TEXTURE_MIPMAP)) {
00879         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00880     }
00881     
00882 end:
00883     /* Restore state */
00884     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00885     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
00886 
00887     return tex;
00888 }   
00889 
00890 
00891 
00892 /* GLuint allegro_gl_make_texture_ex(int flag, BITMAP *bmp, GLint internal_format) */
00938 GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
00939 {
00940     GLuint tex = 0, ret = 0;
00941     BITMAP *temp = NULL;
00942     GLint type;
00943     GLint format;
00944     GLint old_tex;
00945 
00946     if (!__allegro_gl_valid_context)
00947         return 0;
00948 
00949     if (!bmp) {
00950         return 0;
00951     }
00952 
00953     glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_tex);
00954 
00955     /* Voodoo cards don't seem to support mipmaps for textures over 32x32...
00956      */
00957     if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) {
00958         /* Disable mipmapping if the user didn't allow us to rescale */
00959         if (!(flags & AGL_TEXTURE_RESCALE)) {
00960             flags &= ~AGL_TEXTURE_MIPMAP;
00961         }
00962     }
00963 
00964     /* Check the maximum texture size */
00965     if (bmp->w > allegro_gl_info.max_texture_size
00966      || bmp->h > allegro_gl_info.max_texture_size) {
00967         return 0;
00968     }
00969     
00970 
00971     /* Get OpenGL format and type for this pixel data */
00972     format = __allegro_gl_get_bitmap_color_format(bmp, flags);
00973     type = __allegro_gl_get_bitmap_type(bmp, flags);
00974     
00975     if (flags & AGL_TEXTURE_ALPHA_ONLY) {
00976         type   = GL_UNSIGNED_BYTE;
00977         format = GL_ALPHA;
00978 
00979         /* Alpha bitmaps must be 8-bpp */
00980         if (bitmap_color_depth(bmp) != 8) {
00981             return 0;
00982         }
00983     }
00984 
00985     if (flags & AGL_TEXTURE_MASKED) {
00986         flags |= AGL_TEXTURE_FORCE_ALPHA_INTERNAL;
00987     }
00988 
00989     /* Munge the bitmap if needed (rescaling, alpha channel, etc) */
00990     temp = __allegro_gl_munge_bitmap(flags, bmp, 0, 0, bmp->w, bmp->h,
00991                                      &type, &format);
00992     if (temp) {
00993         bmp = temp;
00994     }
00995 
00996     TRACE("* Note * make_texture_ex: Internal format specified: %x\n",
00997           (int)internal_format);
00998     if (internal_format == -1) {
00999         internal_format = __allegro_gl_get_texture_format_ex(bmp, flags);
01000     }
01001 
01002     if (internal_format == -1) {
01003         TRACE("** ERROR ** make_texture_ex: Invalid internal format!: "
01004               "0x%x\n", (int)internal_format);
01005         goto end;
01006     }
01007     
01008     TRACE("* Note * make_texture_ex: dest format=%04x, source format=%04x, "
01009           "type=%04x\n", (int)internal_format, (int)format, (int)type);
01010 
01011     
01012     /* ATI Radeon 7000 inverts R and B components when generating mipmaps and
01013      * the internal format is GL_RGB8, bt only on mipmaps. Instead, we'll use
01014      * GL_RGBA8. This works for bitmaps of depth <= 24. For 32-bpp bitmaps,
01015      * some additional tricks are needed: We must fill in alpha with 255.
01016      */
01017     if (allegro_gl_info.is_ati_radeon_7000 && (flags & AGL_TEXTURE_MIPMAP)
01018      && internal_format == GL_RGB8
01019      && allegro_gl_extensions_GL.SGIS_generate_mipmap) {
01020             
01021         int i, j;
01022         int depth = bitmap_color_depth(bmp);
01023 
01024         if (depth == 32) {
01025 
01026             /* Create temp bitmap if not already there */
01027             if (!temp) {
01028                 temp = create_bitmap_ex(depth, bmp->w, bmp->h);
01029                 if (!temp) {
01030                     TRACE("** ERROR ** make_texture_ex: Unable to allocate "
01031                           "memory for temporary bitmap (Radeon 7000 path)!\n");
01032                     goto end;
01033                 }
01034                 blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
01035                 bmp = temp;
01036             }
01037             
01038             /* Slow path, until ATI finally gets around to fixing their
01039              * drivers.
01040              *
01041              * Note: If destination internal format was GL_RGBx, then no masking
01042              * code is needed.
01043              */
01044             for (j = 0; j < bmp->h; j++) {
01045                 for (i = 0; i < bmp->w; i++) {
01046                     int pix = _getpixel32(bmp, i, j);
01047                     _putpixel32(bmp, i, j,
01048                         makeacol32(getr32(pix), getg32(pix), getb32(pix), 255));
01049                 }
01050             }
01051         }
01052         internal_format = GL_RGBA8;
01053     }
01054     
01055 
01056     /* Generate the texture */
01057     glGenTextures(1, &tex);
01058     if (!tex) {
01059         TRACE("** ERROR ** make_texture_ex: Unable to create GL texture!\n");
01060         goto end;
01061     }
01062 
01063     ret = do_texture_upload(bmp, tex, internal_format, format, type, flags);
01064 
01065 end:
01066     if (temp) {
01067         destroy_bitmap(temp);
01068     }
01069 
01070     if (!ret && tex) {
01071         glDeleteTextures(1, &tex);
01072     }
01073 
01074     glBindTexture(GL_TEXTURE_2D, old_tex);
01075 
01076     return tex;
01077 }
01078 
01079 
01080 
01081 
01082 
01083 /* GLuint allegro_gl_make_texture(BITMAP *bmp) */
01092 GLuint allegro_gl_make_texture(BITMAP *bmp) {
01093         
01094     int flags = __allegro_gl_convert_flags(0);
01095     
01096     return allegro_gl_make_texture_ex(flags, bmp,
01097                                      allegro_gl_opengl_internal_texture_format);
01098 }
01099 
01100 
01101 
01102 /* GLuint allegro_gl_make_masked_texture(BITMAP *bmp) */
01111 GLuint allegro_gl_make_masked_texture(BITMAP *bmp) {
01112         
01113     int flags = __allegro_gl_convert_flags(AGL_TEXTURE_MASKED);
01114 
01115     return allegro_gl_make_texture_ex(flags, bmp,
01116                                      allegro_gl_opengl_internal_texture_format);
01117 }
01118 
01119 
01120 
01121 
01122 /* GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) */
01143 GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) {
01144 
01145     int flags = __allegro_gl_convert_flags(0);
01146     return __allegro_gl_get_bitmap_type(bmp, flags);
01147 }
01148 
01149 
01150 
01151 /* GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) */
01166 GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) {
01167 
01168     int flags = __allegro_gl_convert_flags(0);
01169     return __allegro_gl_get_bitmap_color_format(bmp, flags);
01170 }
01171 

Generated on Wed Jun 30 23:59:52 2004 for AllegroGL by doxygen 1.3.5