AllegroGL: texture.c Source File

AllegroGL 0.4.4

- Main Page
- Related Pages
- Modules
- Files

- File List
- Globals

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) */
439 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) */
1456 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
AGL_TEXTURE_MASKED
#define AGL_TEXTURE_MASKED
Generate an alpha channel for this texture, based on the Allegro mask color.
Definition: alleggl.h:537
allegro_gl_make_texture_ex
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
allegro_gl_get_texture_format
GLint allegro_gl_get_texture_format(BITMAP *bmp)
Returns the OpenGL internal texture format for this bitmap.
Definition: texture.c:248
allegro_gl_use_alpha_channel
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
allegro_gl_use_mipmapping
int allegro_gl_use_mipmapping(int enable)
Tell AllegroGL to use Mipmapping or not when generating textures via its functions.
Definition: texture.c:415
AGL_TEXTURE_ALPHA_ONLY
#define AGL_TEXTURE_ALPHA_ONLY
Tell AllegroGL that the specified BITMAP is an 8-bpp alpha-only BITMAP.
Definition: alleggl.h:548
allegro_gl_extensions_GL
struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
List of OpenGL extensions supported by AllegroGL.
Definition: glext.c:55
allegro_gl_set_texture_format
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
allegro_gl_check_texture
int allegro_gl_check_texture(BITMAP *bmp)
Checks whether the specified bitmap is of the proper size for texturing.
Definition: texture.c:557
allegro_gl_flip_texture
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
allegro_gl_get_bitmap_color_format
GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp)
AllegroGL will generate mipmaps for this texture.
Definition: texture.c:1456
allegro_gl_make_masked_texture
GLuint allegro_gl_make_masked_texture(BITMAP *bmp)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1402
AGL_TEXTURE_MIPMAP
#define AGL_TEXTURE_MIPMAP
AllegroGL will generate mipmaps for this texture.
Definition: alleggl.h:521
alleggl.h
Main header file for AllegroGL.
allegro_gl_check_texture_ex
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
AGL_TEXTURE_FLIP
#define AGL_TEXTURE_FLIP
Flip the texture on the x-axis.
Definition: alleggl.h:532
allegro_gl_make_texture
GLuint allegro_gl_make_texture(BITMAP *bmp)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1383
AGL_TEXTURE_RESCALE
#define AGL_TEXTURE_RESCALE
Tell AllegroGL to allow rescaling of the bitmap.
Definition: alleggl.h:543
AGL_TEXTURE_HAS_ALPHA
#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
allegro_gl_get_bitmap_type
GLenum allegro_gl_get_bitmap_type(BITMAP *bmp)
AllegroGL will generate mipmaps for this texture.
Definition: texture.c:1433