AllegroGL  0.4.4
texture.c
Go to the documentation of this file.
1 /* This code is (C) AllegroGL contributors, and double licensed under
2  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3  */
8 #include <string.h>
9 
10 #include "alleggl.h"
11 #include "allglint.h"
12 
13 #include <allegro/internal/aintern.h>
14 
15 #ifdef ALLEGRO_MACOSX
16 #include <OpenGL/glu.h>
17 #else
18 #include <GL/glu.h>
19 #endif
20 
21 static GLint allegro_gl_opengl_internal_texture_format = -1;
22 static int allegro_gl_use_mipmapping_for_textures = 0;
23 int __allegro_gl_use_alpha = FALSE;
24 int __allegro_gl_flip_texture = TRUE;
25 GLint __allegro_gl_texture_read_format[5];
26 GLint __allegro_gl_texture_components[5];
27 
28 #define PREFIX_I "agl-tex INFO: "
29 #define PREFIX_W "agl-tex WARNING: "
30 #define PREFIX_E "agl-tex ERROR: "
31 
32 
38 char const *__allegro_gl_get_format_description(GLint format)
39 {
40  static char str[256];
41 #define F(s) case s: return #s
42  switch (format) {
43  F(GL_ALPHA);
44  F(GL_ALPHA4);
45  F(GL_ALPHA8);
46  F(GL_ALPHA12);
47  F(GL_ALPHA16);
48  F(GL_ALPHA16F_ARB);
49  F(GL_ALPHA32F_ARB);
50  F(GL_INTENSITY);
51  F(GL_INTENSITY4);
52  F(GL_INTENSITY8);
53  F(GL_INTENSITY12);
54  F(GL_INTENSITY16);
55  F(GL_INTENSITY16F_ARB);
56  F(GL_INTENSITY32F_ARB);
57  F(GL_LUMINANCE);
58  F(GL_LUMINANCE4);
59  F(GL_LUMINANCE8);
60  F(GL_LUMINANCE12);
61  F(GL_LUMINANCE16);
62  F(GL_LUMINANCE16F_ARB);
63  F(GL_LUMINANCE32F_ARB);
64  F(GL_LUMINANCE_ALPHA);
65  F(GL_LUMINANCE4_ALPHA4);
66  F(GL_LUMINANCE12_ALPHA4);
67  F(GL_LUMINANCE8_ALPHA8);
68  F(GL_LUMINANCE6_ALPHA2);
69  F(GL_LUMINANCE12_ALPHA12);
70  F(GL_LUMINANCE16_ALPHA16);
71  F(GL_LUMINANCE_ALPHA16F_ARB);
72  F(GL_LUMINANCE_ALPHA32F_ARB);
73  F(GL_RGB);
74  F(GL_R3_G3_B2);
75  F(GL_RGB4);
76  F(GL_RGB5);
77  F(GL_RGB8);
78  F(GL_RGB10);
79  F(GL_RGB12);
80  F(GL_RGB16);
81  F(GL_RGB16F_ARB);
82  F(GL_RGB32F_ARB);
83  F(GL_RGBA);
84  F(GL_RGBA2);
85  F(GL_RGBA4);
86  F(GL_RGB5_A1);
87  F(GL_RGBA8);
88  F(GL_RGB10_A2);
89  F(GL_RGBA12);
90  F(GL_RGBA16);
91  F(GL_RGBA16F_ARB);
92  F(GL_RGBA32F_ARB);
93  }
94  uszprintf(str, sizeof str, "%x", format);
95  return str;
96 #undef F
97 }
98 
99 
100 
101 /* int __allegro_gl_get_num_channels(GLenum format) */
111 int __allegro_gl_get_num_channels(GLenum format) {
112 
113  switch (format) {
114  case 1:
115  case GL_ALPHA:
116  case GL_ALPHA4:
117  case GL_ALPHA8:
118  case GL_ALPHA12:
119  case GL_ALPHA16:
120  case GL_ALPHA16F_ARB:
121  case GL_ALPHA32F_ARB:
122  case GL_INTENSITY:
123  case GL_INTENSITY4:
124  case GL_INTENSITY8:
125  case GL_INTENSITY12:
126  case GL_INTENSITY16:
127  case GL_INTENSITY16F_ARB:
128  case GL_INTENSITY32F_ARB:
129  case GL_LUMINANCE:
130  case GL_LUMINANCE4:
131  case GL_LUMINANCE8:
132  case GL_LUMINANCE12:
133  case GL_LUMINANCE16:
134  case GL_LUMINANCE16F_ARB:
135  case GL_LUMINANCE32F_ARB:
136  return 1;
137  case 2:
138  case GL_LUMINANCE_ALPHA:
139  case GL_LUMINANCE4_ALPHA4:
140  case GL_LUMINANCE12_ALPHA4:
141  case GL_LUMINANCE8_ALPHA8:
142  case GL_LUMINANCE6_ALPHA2:
143  case GL_LUMINANCE12_ALPHA12:
144  case GL_LUMINANCE16_ALPHA16:
145  case GL_LUMINANCE_ALPHA16F_ARB:
146  case GL_LUMINANCE_ALPHA32F_ARB:
147  return 2;
148  case 3:
149  case GL_RGB:
150  case GL_R3_G3_B2:
151  case GL_RGB4:
152  case GL_RGB5:
153  case GL_RGB8:
154  case GL_RGB10:
155  case GL_RGB12:
156  case GL_RGB16:
157  case GL_RGB16F_ARB:
158  case GL_RGB32F_ARB:
159  return 3;
160  case 4:
161  case GL_RGBA:
162  case GL_RGBA2:
163  case GL_RGBA4:
164  case GL_RGB5_A1:
165  case GL_RGBA8:
166  case GL_RGB10_A2:
167  case GL_RGBA12:
168  case GL_RGBA16:
169  case GL_RGBA16F_ARB:
170  case GL_RGBA32F_ARB:
171  return 4;
172  default:
173  return 0;
174  }
175 }
176 
177 
178 
179 /* GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) */
190 GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) {
191 
192  if (!bmp) {
193  return -1;
194  }
195 
196  switch (bitmap_color_depth(bmp)) {
197  case 32:
198  if (flags
199  & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
200  return GL_RGBA8;
201  }
202  else {
203  return GL_RGB8;
204  }
205  case 8:
206  return GL_INTENSITY8;
207  case 15:
208  if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
209  return GL_RGB5_A1;
210  }
211  else {
212  return GL_RGB5;
213  }
214  case 16:
215  case 24:
216  if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
217  return GL_RGBA8;
218  }
219  else {
220  return GL_RGB8;
221  }
222  default:
223  return -1;
224  }
225 
226  return -1;
227 }
228 
229 
230 
231 /* GLint allegro_gl_get_texture_format(BITMAP *bmp) */
248 GLint allegro_gl_get_texture_format(BITMAP *bmp) {
249 
250  if (bmp && allegro_gl_opengl_internal_texture_format == -1) {
251  return __allegro_gl_get_texture_format_ex(bmp,
252  __allegro_gl_use_alpha ? AGL_TEXTURE_FORCE_ALPHA_INTERNAL : 0);
253  }
254 
255  return allegro_gl_opengl_internal_texture_format;
256 }
257 
258 
259 
260 /* GLint allegro_gl_set_texture_format(GLint format) */
282 GLint allegro_gl_set_texture_format(GLint format) {
283 
284  GLint old = allegro_gl_opengl_internal_texture_format;
285  allegro_gl_opengl_internal_texture_format = format;
286  return old;
287 }
288 
289 
290 
291 /* GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) */
311 GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) {
312 
313  int c = bitmap_color_depth(bmp);
314 
315  switch (c) {
316 
317  case 8:
318  return __allegro_gl_texture_read_format[0];
319 
320  case 15:
321  return __allegro_gl_texture_read_format[1];
322 
323  case 16:
324  return __allegro_gl_texture_read_format[2];
325 
326  case 24:
327  return __allegro_gl_texture_read_format[3];
328 
329  case 32:
330  return __allegro_gl_texture_read_format[4];
331 
332  default:
333  TRACE(PREFIX_E "get_bitmap_type: unhandled bitmap depth: %d\n",
334  c);
335  return -1;
336  }
337 }
338 
339 
340 
341 /* GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) */
355 GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) {
356 
357  int c = bitmap_color_depth(bmp);
358 
359  switch (c) {
360 
361  case 8:
362  if (flags & AGL_TEXTURE_ALPHA_ONLY) {
363  return GL_ALPHA;
364  }
365  else {
366  return __allegro_gl_texture_components[0];
367  }
368 
369  case 15:
370  if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
371  return GL_RGBA;
372  }
373  else {
374  return __allegro_gl_texture_components[1];
375  }
376 
377  case 16:
378  return __allegro_gl_texture_components[2];
379 
380  case 24:
381  return __allegro_gl_texture_components[3];
382 
383  case 32:
384  if (flags & (AGL_TEXTURE_HAS_ALPHA
385  | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
386  return GL_RGBA;
387  }
388  else {
389  return __allegro_gl_texture_components[4];
390  }
391 
392  default:
393  TRACE(PREFIX_E "get_bitmap_color_format: unhandled bitmap "
394  "depth: %d\n", c);
395  return -1;
396  }
397 }
398 
399 
400 
401 /* int allegro_gl_use_mipmapping(int enable) */
415 int allegro_gl_use_mipmapping(int enable) {
416 
417  int old = allegro_gl_use_mipmapping_for_textures;
418  allegro_gl_use_mipmapping_for_textures = enable;
419  return old;
420 }
421 
422 
423 
424 /* int allegro_gl_use_alpha_channel(int enable) */
440 
441  int old = __allegro_gl_use_alpha;
442  __allegro_gl_use_alpha = enable;
443  return old;
444 }
445 
446 
447 
448 /* int allegro_gl_flip_texture(int enable) */
464 int allegro_gl_flip_texture(int enable) {
465 
466  int old = __allegro_gl_flip_texture;
467  __allegro_gl_flip_texture = enable;
468  return old;
469 }
470 
471 
472 
473 /* int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLuint internal_format) */
495 int allegro_gl_check_texture_ex(int flags, BITMAP *bmp,
496  GLint internal_format) {
497 
498  return (allegro_gl_make_texture_ex(flags | AGL_TEXTURE_CHECK_VALID_INTERNAL,
499  bmp, internal_format) ? TRUE : FALSE);
500 }
501 
502 
503 
504 /* Convert flags from pre-0.2.0 to 0.2.0+ */
505 static int __allegro_gl_convert_flags(int flags) {
506 
507  flags |= AGL_TEXTURE_RESCALE;
508 
509  if (allegro_gl_use_mipmapping_for_textures) {
510  flags |= AGL_TEXTURE_MIPMAP;
511  }
512  if (__allegro_gl_use_alpha) {
513  flags |= AGL_TEXTURE_HAS_ALPHA;
514  }
515  if (__allegro_gl_flip_texture) {
516  flags |= AGL_TEXTURE_FLIP;
517  }
518 
519  if (allegro_gl_opengl_internal_texture_format == GL_ALPHA4
520  || allegro_gl_opengl_internal_texture_format == GL_ALPHA8
521  || allegro_gl_opengl_internal_texture_format == GL_ALPHA12
522  || allegro_gl_opengl_internal_texture_format == GL_ALPHA16
523  || allegro_gl_opengl_internal_texture_format == GL_ALPHA
524  || allegro_gl_opengl_internal_texture_format == GL_INTENSITY4
525  || allegro_gl_opengl_internal_texture_format == GL_INTENSITY8
526  || allegro_gl_opengl_internal_texture_format == GL_INTENSITY12
527  || allegro_gl_opengl_internal_texture_format == GL_INTENSITY16
528  || allegro_gl_opengl_internal_texture_format == GL_INTENSITY
529  || allegro_gl_opengl_internal_texture_format == 1) {
530  flags |= AGL_TEXTURE_ALPHA_ONLY;
531  }
532 
533  return flags;
534 }
535 
536 
537 
538 /* int allegro_gl_check_texture(BITMAP *bmp) */
557 int allegro_gl_check_texture(BITMAP *bmp) {
558 
559  int flags = __allegro_gl_convert_flags(0);
560 
561  return allegro_gl_check_texture_ex(flags, bmp,
562  allegro_gl_opengl_internal_texture_format);
563 }
564 
565 
566 
567 /* Integer log2 function. Not optimized for speed. */
568 static int log2i(int n) {
569 
570  int k;
571 
572  if (n < 1) {
573  return -1;
574  }
575 
576  k = 0;
577  while (n >>= 1) {
578  k++;
579  }
580 
581  return k;
582 }
583 
584 
585 
586 /* BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, GLint *type, GLint *format) */
596 BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y,
597  int w, int h, GLint *type, GLint *format) {
598 
599  BITMAP *ret = 0, *temp = 0;
600 
601  int need_rescale = 0;
602  int need_alpha = 0;
603  int need_flip = 0;
604  int depth = bitmap_color_depth(bmp);
605  int force_copy = 0;
606 
607  const int old_w = w, old_h = h;
608 
609  if (flags & AGL_TEXTURE_RESCALE) {
610 
611  /* Check if rescaling is needed */
612 
613  /* NP2 is not supported, and the texture isn't a power-of-two.
614  * Resize the next power of 2
615  */
616  if (!allegro_gl_extensions_GL.ARB_texture_non_power_of_two
617  && ((w & (w - 1)) || (h & (h - 1)))) {
618  w = __allegro_gl_make_power_of_2(w);
619  h = __allegro_gl_make_power_of_2(h);
620  TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
621  "%ix%i to %ix%i due to non-power-of-2 source size.\n",
622  old_w, old_h, w, h);
623  need_rescale = 1;
624  }
625 
626  /* Don't go over the max texture size */
627  if (w > allegro_gl_info.max_texture_size) {
628  w = allegro_gl_info.max_texture_size;
629  TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
630  "%ix%i to %ix%i due to max supported size exceed.\n",
631  old_w, old_h, w, h);
632  need_rescale = 1;
633  }
634 
635  if (h > allegro_gl_info.max_texture_size) {
636  h = allegro_gl_info.max_texture_size;
637  TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
638  "%ix%i to %ix%i due to max supported size exceed.\n",
639  old_w, old_h, w, h);
640  need_rescale = 1;
641  }
642 
643  /* Voodoos don't support mipmaps for textures greater than 32x32.
644  * If we're allowed to rescale, rescale the bitmap to 32x32.
645  * XXX <rohannessian> Apparently, this is a bug in one version
646  * of the Voodoo GL driver. Need to figure out a workaround
647  * for that.
648  */
649  if (allegro_gl_info.is_voodoo && (flags & AGL_TEXTURE_MIPMAP)
650  && (w > 32 || h > 32)) {
651 
652  w = MIN(32, w);
653  h = MIN(32, h);
654 
655  TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
656  "%ix%i to %ix%i due to Voodoo driver bug.\n",
657  old_w, old_h, w, h);
658  need_rescale = 1;
659  }
660  }
661 
662  /* Matrox G200 cards have a bug where rectangular textures can't have
663  * more than 4 levels of mipmaps (max_mip == 3). This doesn't seem
664  * to affect square textures.
665  *
666  * Note: Using GLU to build the mipmaps seems to work. Maybe AGL is
667  * doing something wrong?
668  *
669  * Workaround: Use GLU to build the mipmaps, and force depth to 24 or
670  * 32.
671  */
672  if ( allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP)) {
673  int wl = log2i(w);
674  int hl = log2i(h);
675 
676  if (w != h && MAX(wl, hl) > 3 && depth < 24
677  && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
678  TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n");
679  depth = 24;
680  }
681  }
682 
683  /* Do we need to flip the texture on the t axis? */
684  if (flags & AGL_TEXTURE_FLIP) {
685  need_flip = 1;
686  }
687 
688 
689  /* If not supported, blit to a 24 bpp bitmap and try again
690  */
691  if (*type == -1) {
692  TRACE(PREFIX_W "munge_bitmap: using temporary 24bpp bitmap\n");
693  depth = 24;
694  }
695 
696  /* We need a texture that can be used for masked blits.
697  * Insert an alpha channel if one is not there.
698  * If it's already there, replace it by 0/1 as needed.
699  */
700  if ((flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
701  need_alpha = 1;
702 
703  switch (depth) {
704  case 15:
705  if (!allegro_gl_extensions_GL.EXT_packed_pixels) {
706  depth = 32;
707  }
708  break;
709  case 8:
710  case 16:
711  case 24:
712  case 32:
713  depth = 32;
714  break;
715  }
716  force_copy = 1;
717  }
718 
719  /* Allegro fills in 0 for the alpha channel. Matrox G200 seems to ignore
720  * the internal format; so we need to drop down to 24-bpp if no alpha
721  * will be needed.
722  */
723  if (allegro_gl_info.is_matrox_g200 && !(flags & AGL_TEXTURE_MASKED)
724  && !(flags & AGL_TEXTURE_HAS_ALPHA) && depth == 32) {
725  TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n");
726  depth = 24;
727  force_copy = 1;
728  }
729 
730 
731  /* Do we need to do a color depth conversion or bitmap copy? */
732  if (depth != bitmap_color_depth(bmp) || force_copy) {
733 
734  TRACE(PREFIX_I "munge_bitmap: Need to perform depth conversion from %i "
735  "to %i bpp.\n", bitmap_color_depth(bmp), depth);
736 
737  temp = create_bitmap_ex(depth, bmp->w, bmp->h);
738 
739  if (!temp) {
740  TRACE(PREFIX_E "munge_bitmap: Unable to create temporary bitmap "
741  "%ix%ix%i\n", bmp->w, bmp->h, depth);
742  return NULL;
743  }
744 
745  /* XXX <rohannessian> Use palette conversion?
746  */
747  if (bitmap_color_depth(bmp) == 8 && depth > 8) {
748  int i, j;
749  for (j = 0; j < bmp->h; j++) {
750  for (i = 0; i < bmp->w; i++) {
751  int c = _getpixel(bmp, i, j);
752  putpixel(temp, i, j, makecol_depth(depth, c, c, c));
753  }
754  }
755  }
756  else {
757  blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
758  }
759  bmp = temp;
760 
761  *format = __allegro_gl_get_bitmap_color_format(bmp, flags);
762  *type = __allegro_gl_get_bitmap_type(bmp, flags);
763  }
764 
765 
766 
767  /* Nothing to do? */
768  if (!need_rescale && !need_alpha && !need_flip) {
769 
770  TRACE(PREFIX_I "munge_bitmap: No need for munging - returning %p\n",
771  temp);
772 
773  /* Return depth-converte bitmap, if present */
774  if (temp) {
775  return temp;
776  }
777  return NULL;
778  }
779 
780  ret = create_bitmap_ex(depth, w, h);
781 
782  if (!ret) {
783  TRACE(PREFIX_E "munge_bitmap: Unable to create result bitmap "
784  "%ix%ix%i\n", w, h, depth);
785  goto error;
786  }
787 
788 
789  /* No need to fill in bitmap if we're just making a query */
790  if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
791  if (temp) {
792  destroy_bitmap(temp);
793  }
794  return ret;
795  }
796 
797 
798  /* Perform flip
799  * I don't want to have to deal with *yet another* temporary bitmap
800  * so instead, I fugde the line pointers around.
801  * This will work because we require Allegro memory bitmaps anyway.
802  */
803  if (need_flip) {
804  int i;
805  TRACE(PREFIX_I "munge_bitmap: Flipping bitmap.\n");
806  for (i = 0; i < bmp->h/2; i++) {
807  unsigned char *l = bmp->line[i];
808  bmp->line[i] = bmp->line[bmp->h - i - 1];
809  bmp->line[bmp->h - i - 1] = l;
810  }
811  }
812 
813  /* Rescale bitmap */
814  if (need_rescale) {
815  TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap.\n");
816  stretch_blit(bmp, ret, x, y, old_w, old_h, 0, 0, ret->w, ret->h);
817  }
818  else {
819  TRACE(PREFIX_I "munge_bitmap: Copying bitmap.\n");
820  blit(bmp, ret, x, y, 0, 0, w, h);
821  }
822 
823  /* Restore the original bitmap, if needed */
824  if (need_flip && !temp) {
825  int i;
826  TRACE(PREFIX_I "munge_bitmap: Unflipping bitmap.\n");
827  for (i = 0; i < bmp->h/2; i++) {
828  unsigned char *l = bmp->line[i];
829  bmp->line[i] = bmp->line[bmp->h - i - 1];
830  bmp->line[bmp->h - i - 1] = l;
831  }
832  }
833 
834  /* Insert alpha channel */
835  if (need_alpha) {
836  int i, j;
837  int mask = bitmap_mask_color(ret);
838 
839  /* alpha mask for 5.5.5.1 pixels */
840  int alpha = (-1) ^ makecol_depth(depth, 255, 255, 255);
841 
842  TRACE(PREFIX_I "munge_bitmap: Inserting alpha channel.\n");
843 
844  for (j = 0; j < h; j++) {
845  for (i = 0; i < w; i++) {
846  int pix;
847 
848  switch (depth) {
849  case 32:
850  pix = _getpixel32(ret, i, j);
851 
852  if (pix == mask) {
853  pix = 0;
854  }
855  else if ((flags & AGL_TEXTURE_HAS_ALPHA) == 0) {
856  int r, g, b;
857  r = getr32(pix);
858  g = getg32(pix);
859  b = getb32(pix);
860  pix = makeacol32(r, g, b, 255);
861  }
862  _putpixel32(ret, i, j, pix);
863  break;
864  case 15:
865  pix = _getpixel16(ret, i, j);
866 
867  if (pix == mask) {
868  pix = 0;
869  }
870  else {
871  pix |= alpha;
872  }
873 
874  _putpixel16(temp, i, j, pix);
875  break;
876  default:
877  /* Shouldn't actually come here */
878  ASSERT(0);
879  }
880  }
881  }
882  }
883 
884 
885 error:
886  if (temp) {
887  destroy_bitmap(temp);
888  }
889 
890  return ret;
891 }
892 
893 
894 
895 /* Perform the actual texture upload. Helper for agl_make_texture_ex().
896  */
897 static GLuint do_texture_upload(BITMAP *bmp, GLuint tex, GLint internal_format,
898  GLint format, GLint type, int flags) {
899 
900  int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(bmp));
901  GLint saved_row_length;
902  GLint saved_alignment;
903  GLenum target = GL_TEXTURE_2D;
904 
905  glBindTexture(target, tex);
906 
907 
908  /* Handle proxy texture checks */
909  if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
910  /* <bcoconni> allegro_gl_check_texture is broken with GL drivers based
911  * on Mesa. It seems this is a Mesa bug...
912  */
913  if (allegro_gl_info.is_mesa_driver) {
914  AGL_LOG(1, "* Note * check_texture: Mesa driver detected: "
915  "PROXY_TEXTURE_2D tests are skipped\n");
916  return tex;
917  }
918  else {
919  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internal_format,
920  bmp->w, bmp->h, 0, format, type, NULL);
921 
922  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
923  GL_TEXTURE_COMPONENTS, &internal_format);
924 
925  return (internal_format ? tex : 0);
926  }
927  }
928 
929 
930  /* Set up pixel transfer mode */
931  glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
932  glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
933  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
934 
935  TRACE(PREFIX_I "do_texture_upload: Making texture: bpp: %i\n",
936  bitmap_color_depth(bmp));
937 
938  /* Generate mipmaps, if needed */
939  if (flags & AGL_TEXTURE_MIPMAP) {
940 
941  if (allegro_gl_extensions_GL.SGIS_generate_mipmap) {
942  /* Easy way out - let the driver do it ;)
943  * We do need to set high-qual mipmap generation though.
944  */
945  glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
946  glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
947  TRACE(PREFIX_I "do_texture_upload: Using SGIS_generate_mipmap for "
948  "mipmap generation.\n");
949  }
950  else if (allegro_gl_info.is_matrox_g200
951  && (flags & AGL_TEXTURE_MIPMAP) && (bitmap_color_depth(bmp) >= 24
952  || bitmap_color_depth(bmp) == 8)
953  && (bmp->w != bmp->h)) {
954 
955  /* Matrox G200 has issues with our mipmapping code. Use GLU if we
956  * can.
957  */
958  TRACE(PREFIX_I "do_texture_upload: Using GLU for mipmaps.\n");
959  glPixelStorei(GL_UNPACK_ROW_LENGTH, bmp->h > 1
960  ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel
961  : bmp->w);
962  glPixelStorei(GL_UNPACK_ROW_LENGTH,
963  (bmp->line[1] - bmp->line[0]) / bytes_per_pixel);
964  gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format, bmp->w, bmp->h,
965  format, type, bmp->line[0]);
966  }
967  else {
968  int w = bmp->w;
969  int h = bmp->h;
970  int depth = bitmap_color_depth(bmp);
971 
972  /* The driver can't generate mipmaps for us. We can't rely on GLU
973  * since the Win32 version doesn't support any of the new pixel
974  * formats. Instead, we'll use our own downsampler (which only
975  * has to work on Allegro BITMAPs)
976  */
977  BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2);
978 
979  /* We need to generate mipmaps up to 1x1 - compute the number
980  * of levels we need.
981  */
982  int num_levels = log2i(MAX(bmp->w, bmp->h));
983 
984  int i, x, y;
985 
986  BITMAP *src, *dest;
987 
988  TRACE(PREFIX_I "do_texture_upload: Using Allegro for "
989  "mipmap generation.\n");
990 
991  if (!temp) {
992  TRACE(PREFIX_E "do_texture_upload: Unable to create "
993  "temporary bitmap sized %ix%ix%i for mipmap generation!",
994  w / 2, h / 2, depth);
995  tex = 0;
996  goto end;
997  }
998 
999  src = bmp;
1000  dest = temp;
1001 
1002  for (i = 1; i <= num_levels; i++) {
1003 
1004  for (y = 0; y < h; y += 2) {
1005  for (x = 0; x < w; x += 2) {
1006 
1007  int r, g, b, a;
1008  int pix[4];
1009  int avg;
1010 
1011  pix[0] = getpixel(src, x, y);
1012  pix[1] = getpixel(src, x + 1, y);
1013  pix[2] = getpixel(src, x, y + 1);
1014  pix[3] = getpixel(src, x + 1, y + 1);
1015 
1016  if (w == 1) {
1017  pix[1] = pix[0];
1018  pix[3] = pix[2];
1019  }
1020  if (h == 1) {
1021  pix[2] = pix[0];
1022  pix[3] = pix[1];
1023  }
1024 
1025  if (flags & AGL_TEXTURE_ALPHA_ONLY) {
1026  avg = (pix[0] + pix[1] + pix[2] + pix[3] + 2) / 4;
1027  }
1028  else {
1029  r = (getr_depth(depth, pix[0])
1030  + getr_depth(depth, pix[1])
1031  + getr_depth(depth, pix[2])
1032  + getr_depth(depth, pix[3]) + 2) / 4;
1033  g = (getg_depth(depth, pix[0])
1034  + getg_depth(depth, pix[1])
1035  + getg_depth(depth, pix[2])
1036  + getg_depth(depth, pix[3]) + 2) / 4;
1037  b = (getb_depth(depth, pix[0])
1038  + getb_depth(depth, pix[1])
1039  + getb_depth(depth, pix[2])
1040  + getb_depth(depth, pix[3]) + 2) / 4;
1041  a = (geta_depth(depth, pix[0])
1042  + geta_depth(depth, pix[1])
1043  + geta_depth(depth, pix[2])
1044  + geta_depth(depth, pix[3]) + 2) / 4;
1045 
1046  avg = makeacol_depth(depth, r, g, b, a);
1047  }
1048 
1049  putpixel(dest, x / 2, y / 2, avg);
1050  }
1051  }
1052  src = temp;
1053 
1054  /* Note - we round down; we're still compatible with
1055  * ARB_texture_non_power_of_two.
1056  */
1057  w = MAX(w / 2, 1);
1058  h = MAX(h / 2, 1);
1059 
1060  TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n",
1061  (temp->h > 1)
1062  ? (long int)((temp->line[1] - temp->line[0]) / bytes_per_pixel)
1063  : temp->w);
1064 
1065  glPixelStorei(GL_UNPACK_ROW_LENGTH, temp->h > 1
1066  ? (temp->line[1] - temp->line[0]) / bytes_per_pixel
1067  : temp->w);
1068 
1069  glTexImage2D(GL_TEXTURE_2D, i, internal_format,
1070  w, h, 0, format, type, temp->line[0]);
1071 
1072  TRACE(PREFIX_I "do_texture_upload: Mipmap level: %i, "
1073  "size: %i x %i\n", i, w, h);
1074 
1075  TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level %i, "
1076  "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x."
1077  "\n", i, __allegro_gl_get_format_description(internal_format),
1078  bmp->w, bmp->h, format, type);
1079  }
1080 
1081  destroy_bitmap(temp);
1082  }
1083  }
1084 
1085  glPixelStorei(GL_UNPACK_ROW_LENGTH, (bmp->h > 1)
1086  ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel
1087  : bmp->w);
1088 
1089  TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n",
1090  (bmp->h > 1) ? (long int)((bmp->line[1] - bmp->line[0]) / bytes_per_pixel)
1091  : bmp->w);
1092 
1093  /* Upload the base texture */
1094  glGetError();
1095  glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
1096  bmp->w, bmp->h, 0, format, type, bmp->line[0]);
1097 
1098  TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level 0, "
1099  "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x.\n",
1100  __allegro_gl_get_format_description(internal_format),
1101  bmp->w, bmp->h, format, type);
1102 
1103  TRACE(PREFIX_I "do_texture_upload: GL Error code: 0x%x\n", glGetError());
1104 
1105  if (!(flags & AGL_TEXTURE_MIPMAP)) {
1106  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1107  }
1108 
1109 end:
1110  /* Restore state */
1111  glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
1112  glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment);
1113 
1114  return tex;
1115 }
1116 
1117 
1118 
1119 /* GLuint allegro_gl_make_texture_ex(int flag, BITMAP *bmp, GLint internal_format) */
1165 GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
1166 {
1167  GLuint tex = 0, ret = 0;
1168  BITMAP *temp = NULL;
1169  GLint type;
1170  GLint format;
1171  GLint old_tex;
1172 
1173  /* Print the parameters */
1174 #ifdef DEBUGMODE
1175  char buf[1024] = "";
1176 # define PFLAG(name) if (flags & name) strcat(buf, #name "|");
1177  PFLAG(AGL_TEXTURE_MIPMAP);
1178  PFLAG(AGL_TEXTURE_HAS_ALPHA);
1179  PFLAG(AGL_TEXTURE_FLIP);
1180  PFLAG(AGL_TEXTURE_MASKED);
1181  PFLAG(AGL_TEXTURE_RESCALE);
1182  PFLAG(AGL_TEXTURE_ALPHA_ONLY);
1183 # undef PFLAG
1184 
1185  TRACE(PREFIX_I "make_texture_ex: flags: %s, bitmap %ix%i, %i bpp.\n", buf,
1186  bmp ? bmp->w : 0, bmp ? bmp->h : 0,
1187  bmp ? bitmap_color_depth(bmp) : 0);
1188  if (internal_format == -1) {
1189  TRACE(PREFIX_I "internalformat: AUTO\n");
1190  }
1191  else {
1192  TRACE(PREFIX_I "internalformat: %s\n",
1193  __allegro_gl_get_format_description(internal_format));
1194  }
1195 #endif
1196 
1197  /* Basic parameter checks */
1198  if (!__allegro_gl_valid_context)
1199  return 0;
1200 
1201  if (!bmp) {
1202  return 0;
1203  }
1204 
1205  glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_tex);
1206 
1207  /* Voodoo cards don't seem to support mipmaps for textures over 32x32...
1208  */
1209  if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) {
1210  /* Disable mipmapping if the user didn't allow us to rescale */
1211  if (!(flags & AGL_TEXTURE_RESCALE)) {
1212  TRACE(PREFIX_I "make_texture_ex: Voodoo card detected && texture "
1213  "size > 32 texels && no rescaling. Disabling mipmaps.\n");
1214  flags &= ~AGL_TEXTURE_MIPMAP;
1215  }
1216  }
1217 
1218  /* Check the maximum texture size */
1219  if (bmp->w > allegro_gl_info.max_texture_size
1220  || bmp->h > allegro_gl_info.max_texture_size) {
1221  if ((flags & AGL_TEXTURE_RESCALE) == 0) {
1222  TRACE(PREFIX_I "make_texture_ex: Max texture size exceeded but no "
1223  "rescaling allowed. Returning 0 (unsupported).\n");
1224  return 0;
1225  }
1226  }
1227 
1228  /* Check power-of-2 */
1229  if (((bmp->w & (bmp->w - 1)) || (bmp->h & (bmp->h - 1)))
1230  && !(flags & AGL_TEXTURE_RESCALE)
1231  && !allegro_gl_extensions_GL.ARB_texture_non_power_of_two) {
1232  TRACE(PREFIX_I "make_texture_ex: Non-power-of-2 sized bitmap provided, "
1233  "no rescaling allowed, and ARB_texture_non_power_of_two "
1234  "unsupported. Returning 0 (unsupported).\n");
1235  return 0;
1236  }
1237 
1238 
1239  /* Get OpenGL format and type for this pixel data */
1240  format = __allegro_gl_get_bitmap_color_format(bmp, flags);
1241  type = __allegro_gl_get_bitmap_type(bmp, flags);
1242 
1243  if (flags & AGL_TEXTURE_ALPHA_ONLY) {
1244  type = GL_UNSIGNED_BYTE;
1245  if (internal_format == GL_ALPHA || internal_format == GL_ALPHA4
1246  || internal_format == GL_ALPHA8) {
1247  format = GL_ALPHA;
1248  }
1249  else if (internal_format == GL_INTENSITY
1250  || internal_format == GL_INTENSITY4
1251  || internal_format == GL_INTENSITY8) {
1252  format = GL_RED;
1253  }
1254  else if (internal_format == GL_LUMINANCE
1255  || internal_format == GL_LUMINANCE4
1256  || internal_format == GL_LUMINANCE8) {
1257  format = GL_LUMINANCE;
1258  }
1259 
1260  /* Alpha bitmaps must be 8-bpp */
1261  if (bitmap_color_depth(bmp) != 8) {
1262  return 0;
1263  }
1264  }
1265 
1266  if (flags & AGL_TEXTURE_MASKED) {
1267  flags |= AGL_TEXTURE_FORCE_ALPHA_INTERNAL;
1268  }
1269 
1270  TRACE(PREFIX_I "make_texture_ex: Preselected texture format: %s, "
1271  "type: 0x%x\n", __allegro_gl_get_format_description(format), type);
1272 
1273  /* Munge the bitmap if needed (rescaling, alpha channel, etc) */
1274  temp = __allegro_gl_munge_bitmap(flags, bmp, 0, 0, bmp->w, bmp->h,
1275  &type, &format);
1276  if (temp) {
1277  bmp = temp;
1278  }
1279 
1280  if (internal_format == -1) {
1281  internal_format = __allegro_gl_get_texture_format_ex(bmp, flags);
1282  TRACE(PREFIX_I "make_texture_ex: Picked internalformat: %s\n",
1283  __allegro_gl_get_format_description(internal_format));
1284  }
1285 
1286  if (internal_format == -1) {
1287  TRACE(PREFIX_E "make_texture_ex: Invalid internal format!: "
1288  "%s\n", __allegro_gl_get_format_description(internal_format));
1289  goto end;
1290  }
1291 
1292  TRACE(PREFIX_I "make_texture_ex: dest format=%s, source format=%s, "
1293  "type=0x%x\n", __allegro_gl_get_format_description(internal_format),
1294  __allegro_gl_get_format_description(format), (int)type);
1295 
1296 
1297  /* ATI Radeon 7000 inverts R and B components when generating mipmaps and
1298  * the internal format is GL_RGB8, but only on mipmaps. Instead, we'll use
1299  * GL_RGBA8. This works for bitmaps of depth <= 24. For 32-bpp bitmaps,
1300  * some additional tricks are needed: We must fill in alpha with 255.
1301  */
1302  if (allegro_gl_info.is_ati_radeon_7000 && (flags & AGL_TEXTURE_MIPMAP)
1303  && internal_format == GL_RGB8
1304  && allegro_gl_extensions_GL.SGIS_generate_mipmap) {
1305 
1306  int i, j;
1307  int depth = bitmap_color_depth(bmp);
1308 
1309  TRACE(PREFIX_I "make_texture_ex: ATI Radeon 7000 detected, mipmapping "
1310  "used, SGIS_generate_mipmap available and selected "
1311  "internalformat is GL_RGB8 but format is GL_RGBA. Working around "
1312  "ATI driver bug by upgrading bitmap to 32-bpp and using GL_RGBA8 "
1313  "instead.\n");
1314 
1315  if (depth == 32) {
1316 
1317  /* Create temp bitmap if not already there */
1318  if (!temp) {
1319  temp = create_bitmap_ex(depth, bmp->w, bmp->h);
1320  if (!temp) {
1321  TRACE(PREFIX_E "make_texture_ex: Unable to allocate "
1322  "memory for temporary bitmap (Radeon 7000 path)!\n");
1323  goto end;
1324  }
1325  blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
1326  bmp = temp;
1327  }
1328 
1329  /* Slow path, until ATI finally gets around to fixing their
1330  * drivers.
1331  *
1332  * Note: If destination internal format was GL_RGBx, then no masking
1333  * code is needed.
1334  */
1335  for (j = 0; j < bmp->h; j++) {
1336  for (i = 0; i < bmp->w; i++) {
1337  int pix = _getpixel32(bmp, i, j);
1338  _putpixel32(bmp, i, j,
1339  makeacol32(getr32(pix), getg32(pix), getb32(pix), 255));
1340  }
1341  }
1342  }
1343  internal_format = GL_RGBA8;
1344  }
1345 
1346 
1347  /* Generate the texture */
1348  glGenTextures(1, &tex);
1349  if (!tex) {
1350  TRACE(PREFIX_E "make_texture_ex: Unable to create GL texture!\n");
1351  goto end;
1352  }
1353 
1354  ret = do_texture_upload(bmp, tex, internal_format, format, type, flags);
1355 
1356 end:
1357  if (temp) {
1358  destroy_bitmap(temp);
1359  }
1360 
1361  if (!ret && tex) {
1362  glDeleteTextures(1, &tex);
1363  }
1364 
1365  glBindTexture(GL_TEXTURE_2D, old_tex);
1366 
1367  return tex;
1368 }
1369 
1370 
1371 
1372 
1373 
1374 /* GLuint allegro_gl_make_texture(BITMAP *bmp) */
1383 GLuint allegro_gl_make_texture(BITMAP *bmp) {
1384 
1385  int flags = __allegro_gl_convert_flags(0);
1386 
1387  return allegro_gl_make_texture_ex(flags, bmp,
1388  allegro_gl_opengl_internal_texture_format);
1389 }
1390 
1391 
1392 
1393 /* GLuint allegro_gl_make_masked_texture(BITMAP *bmp) */
1402 GLuint allegro_gl_make_masked_texture(BITMAP *bmp) {
1403 
1404  int flags = __allegro_gl_convert_flags(AGL_TEXTURE_MASKED);
1405 
1406  return allegro_gl_make_texture_ex(flags, bmp,
1407  allegro_gl_opengl_internal_texture_format);
1408 }
1409 
1410 
1411 
1412 /* GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) */
1433 GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) {
1434 
1435  int flags = __allegro_gl_convert_flags(0);
1436  return __allegro_gl_get_bitmap_type(bmp, flags);
1437 }
1438 
1439 
1440 
1441 /* GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) */
1457 
1458  int flags = __allegro_gl_convert_flags(0);
1459  return __allegro_gl_get_bitmap_color_format(bmp, flags);
1460 }
1461 
#define AGL_TEXTURE_MASKED
Generate an alpha channel for this texture, based on the Allegro mask color.
Definition: alleggl.h:537
GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1165
GLint allegro_gl_get_texture_format(BITMAP *bmp)
Returns the OpenGL internal texture format for this bitmap.
Definition: texture.c:248
int allegro_gl_use_alpha_channel(int enable)
Tell AllegroGL to use Alpha channel or not when generating textures via its functions.
Definition: texture.c:439
int allegro_gl_use_mipmapping(int enable)
Tell AllegroGL to use Mipmapping or not when generating textures via its functions.
Definition: texture.c:415
#define AGL_TEXTURE_ALPHA_ONLY
Tell AllegroGL that the specified BITMAP is an 8-bpp alpha-only BITMAP.
Definition: alleggl.h:548
struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
List of OpenGL extensions supported by AllegroGL.
Definition: glext.c:55
GLint allegro_gl_set_texture_format(GLint format)
Sets the color format you&#39;d like OpenGL to use for its textures.
Definition: texture.c:282
int allegro_gl_check_texture(BITMAP *bmp)
Checks whether the specified bitmap is of the proper size for texturing.
Definition: texture.c:557
int allegro_gl_flip_texture(int enable)
Tell AllegroGL to flip the texture vertically or not when generating textures via its functions...
Definition: texture.c:464
GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp)
AllegroGL will generate mipmaps for this texture.
Definition: texture.c:1456
GLuint allegro_gl_make_masked_texture(BITMAP *bmp)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1402
#define AGL_TEXTURE_MIPMAP
AllegroGL will generate mipmaps for this texture.
Definition: alleggl.h:521
Main header file for AllegroGL.
int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
Checks whether the specified bitmap is of the proper size for texturing.
Definition: texture.c:495
#define AGL_TEXTURE_FLIP
Flip the texture on the x-axis.
Definition: alleggl.h:532
GLuint allegro_gl_make_texture(BITMAP *bmp)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1383
#define AGL_TEXTURE_RESCALE
Tell AllegroGL to allow rescaling of the bitmap.
Definition: alleggl.h:543
#define AGL_TEXTURE_HAS_ALPHA
Tell AllegroGL that the bitmap had an alpha channel, so it should be preserved when generating the te...
Definition: alleggl.h:526
GLenum allegro_gl_get_bitmap_type(BITMAP *bmp)
AllegroGL will generate mipmaps for this texture.
Definition: texture.c:1433