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  */
4 /** \file texture.c
5   * \brief AllegroGL texture management.
6   */
7 
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 
33 /** \internal
34  *  \ingroup texture
35  *
36  *  Returns a string for the given OpenGL texture format.
37  */
__allegro_gl_get_format_description(GLint format)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) */
102 /** \internal
103  *  \ingroup texture
104  *
105  *  Returns the number of color components for the given color fromat.
106  *
107  *  \param format Internal color format.
108  *
109  *  \return The number of color components.
110  */
__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) */
180 /** \internal
181  *  \ingroup texture
182  *
183  *  Returns the OpenGL internal texture format for this bitmap.
184  *
185  *  \param bmp The bitmap to get the information of.
186  *  \param flags The flags to use. See allegro_gl_make_texture_ex() for details.
187  *
188  *  \return The OpenGL internal texture format.
189  */
__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) */
232 /** \ingroup texture
233  *  Returns the OpenGL internal texture format for this bitmap.
234  *  If left to default, it returns the number of color components
235  *  in the bitmap. Otherwise, it simply returns the user defined
236  *  value. If the bitmap parameter is NULL, then it returns the
237  *  currently set format, or -1 if none were previously set.
238  *  8 bpp bitmaps are assumed to be alpha channels only (GL_ALPHA8)
239  *  by default.
240  *
241  *  \sa allegro_gl_set_texture_format(), allegro_gl_make_texture()
242  *
243  *  \param bmp The bitmap to get the information of.
244  *  \return The OpenGL internal texture format.
245  *
246  *  \deprecated
247  */
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) */
261 /** \ingroup texture
262  *  Sets the color format you'd like OpenGL to use for its textures.
263  *  You can pass any of the available GL_* constants that describe
264  *  the internal format (GL_ALPHA4...GL_RGBA16). It is recommended
265  *  that you check for the availability of the format from the client,
266  *  using allegro_gl_opengl_version(). No checking will be done as to the
267  *  validity of the format. The format is a recommendation to the driver,
268  *  so there is no guarentee that the actual format used will be the one
269  *  you chose - this is implementation dependant. This call will affect
270  *  all subsequent calls to allegro_gl_make_texture() and
271  *  allegro_gl_make_masked_texture().
272  *
273  *  To revert to the default AllegroGL format, pass -1 as the format.
274  *
275  *  \sa allegro_gl_get_texture_format()
276  *
277  *  \param format The OpenGL internal texture format.
278  *  \return The previous value of the texture format.
279  *
280  *  \deprecated
281  */
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) */
292 /** \internal
293  *  \ingroup texture
294  *
295  *  Returns the pixel packing format of the selected bitmap in OpenGL
296  *  format. OpenGL 1.1 only understands color component sizes (bytes
297  *  per color), whereas OpenGL 1.2+ can understand Allegro's packed
298  *  formats (such as 16 bit color, with 5-6-5 bit components).
299  *
300  *  If the bitmap is not representable to the OpenGL implementation
301  *  (e.g. it cannot handle packed formats because it's earlier than
302  *  1.2 and does not have the extension) this function returns -1.
303  *
304  *  \sa allegro_gl_make_texture_ex()
305  *
306  *  \param bmp    The bitmap to get the OpenGL pixel type of.
307  *  \param flags The conversion flags
308  *
309  *  \return The pixel type of the bitmap.
310  */
__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) */
342 /** \internal
343  *  \ingroup texture
344  *
345  *  Returns the pixel color format of the selected Allegro bitmap in OpenGL
346  *  format, given the pixel type.
347  *
348  *  \sa allegro_gl_make_texture_ex()
349  *
350  *  \param bmp   The bitmap to get the OpenGL pixel format of.
351  *  \param flags The conversion flags
352  *
353  *  \return The pixel type of the bitmap.
354  */
__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) */
402 /** \ingroup texture
403  *  Tell AllegroGL to use Mipmapping or not when generating textures via
404  *  its functions. This will not affect outside OpenGL states.
405  *  Default is FALSE (off).
406  *
407  *  \sa allegro_gl_check_texture(), allegro_gl_make_texture()
408  *      allegro_gl_make_masked_texture()
409  *
410  *  \param enable Set to TRUE to enable mipmapping, FALSE otherwise.
411  *  \return       The previous mode (either TRUE or FALSE).
412  *
413  *  \deprecated
414  */
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) */
425 /** \ingroup texture
426  *  Tell AllegroGL to use Alpha channel or not when generating textures via
427  *  its functions. This will not affect outside OpenGL states.
428  *  Default is FALSE (off).
429  *
430  *  \sa allegro_gl_check_texture(), allegro_gl_make_texture(),
431  *      allegro_gl_make_masked_texture()
432  *
433  *  \param enable Set to TRUE to enable textures with alpha channel, FALSE
434  *                otherwise.
435  *  \return       The previous mode (either TRUE or FALSE).
436  *
437  *  \deprecated
438  */
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) */
449 /** \ingroup texture
450  *  Tell AllegroGL to flip the texture vertically or not when generating
451  *  textures via its functions, to conform to the usual OpenGL texture
452  *  coordinate system (increasing upwards).
453  *  Default is TRUE (on).
454  *
455  *  \sa allegro_gl_check_texture(), allegro_gl_make_texture(),
456  *      allegro_gl_make_masked_texture()
457  *
458  *  \param enable Set to TRUE to enable textures with alpha channel, FALSE
459  *                otherwise.
460  *  \return       The previous mode (either TRUE or FALSE).
461  *
462  *  \deprecated
463  */
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) */
474 /** \ingroup texture
475  *  Checks whether the specified bitmap is of the proper size for
476  *  texturing. This checks for the card's limit on texture sizes.
477  *
478  *  The parameters to this function are identical to those of
479  *  allegro_gl_make_texture_ex().
480  *
481  *  \b Important \b note: allegro_gl_check_texture does not depend on the
482  *  current state of the texture memory of the driver. This function may
483  *  return TRUE although there is not enough memory to currently make the
484  *  texture resident. You may check if the texture is actually resident with
485  *  glAreTexturesResident().
486  *
487  *  \sa allegro_gl_make_texture_ex()
488  *
489  *  \param flags           The bitmap conversion flags.
490  *  \param bmp             The bitmap to be converted to a texture.
491  *  \param internal_format The internal format to convert to.
492  *
493  *  \return TRUE if the bitmap can be made a texture of, FALSE otherwise.
494  */
allegro_gl_check_texture_ex(int flags,BITMAP * bmp,GLint 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+ */
__allegro_gl_convert_flags(int flags)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) */
539 /** \ingroup texture
540  *  Checks whether the specified bitmap is of the proper size for
541  *  texturing. This checks for the card's limit on texture sizes.
542  *
543  *  \b Important \b note: allegro_gl_check_texture does not depend on the
544  *  current state of the texture memory of the driver. This function may
545  *  return TRUE although there is not enough memory to currently make the
546  *  texture resident. You may check if the texture is actually resident with
547  *  glAreTexturesResident().
548  *
549  *  \sa allegro_gl_check_texture_ex(), allegro_gl_make_texture_ex()
550  *
551  *  \param bmp             The bitmap to be converted to a texture.
552  *
553  *  \return TRUE if the bitmap can be made a texture of, FALSE otherwise.
554  *
555  *  \deprecated
556  */
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. */
log2i(int n)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) */
587 /** \internal
588  *  \ingroup texture
589  *
590  *  Builds a bitmap to match the given flags. Adapts the type and format as
591  *  needed. Subbitmaps can be specified. Clipping must have already been
592  *  applied before calling this function.
593  *
594  *  If NULL is returned, then the original bitmap can be used directly.
595  */
__allegro_gl_munge_bitmap(int flags,BITMAP * bmp,int x,int y,int w,int h,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  */
do_texture_upload(BITMAP * bmp,GLuint tex,GLint internal_format,GLint format,GLint type,int flags)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) */
1120 /** \ingroup texture
1121  *  Uploads an Allegro BITMAP to the GL driver as a texture.
1122  *
1123  *  The bitmap must be a memory bitmap (note that it can be a subbitmap).
1124  *
1125  *  Each bitmap will be converted to a single texture object, with all its
1126  *  size limitations imposed by the video driver and hardware.
1127  *
1128  *  The bitmap should conform to the size limitations imposed by the video
1129  *  driver. That is, if ARB_texture_non_power_of_two is not supported,
1130  *  then the BITMAP must be power-of-two sized. Otherwise, AllegroGL
1131  *  will pick the best format for the bitmap.
1132  *
1133  *  The original bitmap will NOT be modified.
1134  *
1135  *  The flags parameter controls how the texture is generated. It can be a
1136  *  logical OR (|) of any of the following:
1137  *
1138  *    #AGL_TEXTURE_MIPMAP
1139  *    #AGL_TEXTURE_HAS_ALPHA
1140  *    #AGL_TEXTURE_FLIP
1141  *    #AGL_TEXTURE_MASKED
1142  *    #AGL_TEXTURE_RESCALE
1143  *
1144  *  AllegroGL will create a texture with the specified texel format.
1145  *  The texel format should be any of the valid formats that can be
1146  *  specified to glTexImage2D(). No validity checks will be performed
1147  *  by AllegroGL. If you want AllegroGL to automatically determine the
1148  *  format to use based on the BITMAP, use -1 as the format specifier.
1149  *
1150  *  A valid GL Rendering Context must have been established, which means you
1151  *  cannot use this function before having called set_gfx_mode() with a valid
1152  *  OpenGL mode.
1153  *
1154  *  \b Important \b note: on 32 bit bitmap in RGBA mode, the alpha channel
1155  *  created by Allegro is set to all 0 by default. This will cause the
1156  *  texture to not show up in 32bpp modes if alpha is set. You will need
1157  *  to fill in the alpha channel manually if you need an alpha channel.
1158  *
1159  *  \param bmp             The bitmap to be converted to a texture.
1160  *  \param flags           The conversion flags.
1161  *  \param internal_format The texture format to convert to.
1162  *
1163  *  \return GLuint The texture handle, or 0 on failure
1164  */
allegro_gl_make_texture_ex(int flags,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) */
1375 /** \ingroup texture
1376  *
1377  *  Uploads an Allegro BITMAP to the GL driver as a texture.
1378  *
1379  *  \deprecated
1380  *
1381  *  \sa allegro_gl_make_texture_ex()
1382  */
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) */
1394 /** \ingroup texture
1395  *
1396  *  Uploads an Allegro BITMAP to the GL driver as a texture.
1397  *
1398  *  \deprecated
1399  *
1400  *  \sa allegro_gl_make_texture_ex()
1401  */
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) */
1413 /** \internal
1414  *  \ingroup texture
1415  *
1416  *  Returns the pixel packing format of the selected bitmap in OpenGL
1417  *  format. OpenGL 1.1 only understands color component sizes (bytes
1418  *  per color), whereas OpenGL 1.2+ can understand Allegro's packed
1419  *  formats (such as 16 bit color, with 5-6-5 bit components).
1420  *
1421  *  If the bitmap is not representable to the OpenGL implementation
1422  *  (e.g. it cannot handle packed formats because it's earlier than
1423  *  1.2 and does not have the extension) this function returns -1.
1424  *
1425  *  \sa allegro_gl_make_texture_ex()
1426  *
1427  *  \param bmp    The bitmap to get the OpenGL pixel type of.
1428  *
1429  *  \return The pixel type of the bitmap.
1430  *
1431  *  \deprecated This function is deprecated and should no longer be used.
1432  */
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) */
1442 /** \internal
1443  *  \ingroup texture
1444  *
1445  *  Returns the pixel color format of the selected Allegro bitmap in OpenGL
1446  *  format, given the pixel type.
1447  *
1448  *  \sa allegro_gl_make_texture_ex()
1449  *
1450  *  \param bmp   The bitmap to get the OpenGL pixel format of.
1451  *
1452  *  \return The pixel type of the bitmap.
1453  *
1454  *  \deprecated This function is deprecated and should no longer be used.
1455  */
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 
1462