1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_texture_format.cpp
27 #include "vogl_common.h"
28 #include "vogl_texture_format.h"
29 #include "vogl_ktx_texture.h"
31 //----------------------------------------------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------------------------------------------
34 vogl_internal_tex_format g_vogl_internal_texture_formats[] =
36 // TODO: Test ALL of these format mappings on AMD and Intel Mesa.
37 // TODO: This table mapping internal texture formats was composed by calling NVidia's driver.
38 // We should also compose tables for other drivers, and a generic table.
39 #include "vogl_internal_texture_formats.inc"
41 uint g_vogl_total_internal_texture_formats = VOGL_ARRAY_SIZE(g_vogl_internal_texture_formats);
43 typedef vogl::hash_map<GLenum, vogl_internal_tex_format *> vogl_internal_texture_format_hash_map;
45 vogl_internal_texture_format_hash_map g_internal_format_hash_map;
47 //----------------------------------------------------------------------------------------------------------------------
48 // vogl_devel_dump_internal_texture_formats
49 // This func is only for testing various internal GL format related API's
50 // This func is used to generate vogl_internal_texture_formats.inc
51 //----------------------------------------------------------------------------------------------------------------------
52 void vogl_devel_dump_internal_texture_formats(const vogl_context_info &context_info)
58 vogl_scoped_binding_state orig_texture;
59 orig_texture.save_textures();
61 vogl_scoped_state_saver state_saver(cGSTPixelStore, cGSTPixelTransfer);
63 vogl_reset_pixel_store_states();
64 vogl_reset_pixel_transfer_states();
70 ACTUAL_GL_ENTRYPOINT(glGenTextures)(1, &handle);
73 ACTUAL_GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle);
76 for (uint i = 0; i < 256; i++)
78 uint8 vals[4] = { i, 0, 0, 0 };
79 //ACTUAL_GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, GL_R8_SNORM, 1, 1, 0, GL_RED, GL_BYTE, vals);
81 //float vals[1] = { ( i - 128.0f) / 127.0f };
82 //float vals[1] = { i / 255.0f };
84 //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_SCALE, .5f);
85 //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_BIAS, 0.5f);
87 ACTUAL_GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, vals);
89 //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_SCALE, 1.0f);
90 //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_BIAS, 0.0f);
94 uint16 gvals[4] = { 0, 0, 0, 0 };
95 ACTUAL_GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, gvals);
98 printf("%u %u %u %u, %u %u %u %u\n", vals[0], vals[1], vals[2], vals[3],
99 gvals[0], gvals[1], gvals[2], gvals[3]);
103 ACTUAL_GL_ENTRYPOINT(glDeleteTextures)(1, &handle);
107 typedef vogl::map<GLenum, vogl_internal_tex_format> tex_format_map;
108 tex_format_map internal_formats;
110 // Iterate through the base internal fmts, which need some special handling (argh) because the actual internal fmt != the requested internal fmt
111 GLenum base_internal_formats[] =
129 for (uint i = 0; i < VOGL_ARRAY_SIZE(base_internal_formats); i++)
131 printf("%s\n", g_gl_enums.find_gl_name(base_internal_formats[i]));
134 GL_ENTRYPOINT(glGenTextures)(1, &handle);
137 GLenum target = GL_TEXTURE_2D;
139 GL_ENTRYPOINT(glBindTexture)(target, handle);
141 GLenum base_internal_fmt = base_internal_formats[i];
143 vogl_internal_tex_format f;
144 GL_ENTRYPOINT(glGetInternalformativ)(target, base_internal_fmt, GL_GET_TEXTURE_IMAGE_TYPE, sizeof(f.m_optimum_get_image_type), (GLint *)&f.m_optimum_get_image_type);
145 GL_ENTRYPOINT(glGetInternalformativ)(target, base_internal_fmt, GL_GET_TEXTURE_IMAGE_FORMAT, sizeof(f.m_optimum_get_image_fmt), (GLint *)&f.m_optimum_get_image_fmt);
148 GLenum &get_fmt = f.m_optimum_get_image_fmt;
149 GLenum &get_type = f.m_optimum_get_image_type;
151 // manual fixups, ARGH
152 switch (base_internal_fmt)
154 case GL_DEPTH_COMPONENT:
156 get_fmt = GL_DEPTH_COMPONENT;
163 get_type = GL_UNSIGNED_BYTE;
169 get_type = GL_UNSIGNED_BYTE;
175 get_type = GL_UNSIGNED_BYTE;
178 case GL_COMPRESSED_LUMINANCE:
180 get_fmt = GL_LUMINANCE;
181 get_type = GL_UNSIGNED_BYTE;
184 case GL_COMPRESSED_LUMINANCE_ALPHA:
186 get_fmt = GL_LUMINANCE_ALPHA;
187 get_type = GL_UNSIGNED_BYTE;
190 case GL_COMPRESSED_RGB:
193 get_type = GL_UNSIGNED_BYTE;
196 case GL_COMPRESSED_RGBA:
199 get_type = GL_UNSIGNED_BYTE;
202 case GL_LUMINANCE_ALPHA:
204 get_fmt = GL_LUMINANCE_ALPHA;
205 get_type = GL_UNSIGNED_BYTE;
208 case GL_SLUMINANCE_ALPHA:
210 get_fmt = GL_LUMINANCE_ALPHA;
211 get_type = GL_UNSIGNED_BYTE;
217 get_type = GL_UNSIGNED_BYTE;
223 get_type = GL_UNSIGNED_BYTE;
232 VOGL_VERIFY(get_fmt != GL_NONE);
233 VOGL_VERIFY(get_type != GL_NONE);
235 GL_ENTRYPOINT(glTexImage2D)(target, 0, base_internal_fmt, 32, 32, 0, get_fmt, get_type, NULL);
236 VOGL_VERIFY(!vogl_check_gl_error());
238 //bool any_gl_errors = false;
240 #define GET_INT(dst, gl_enum) \
244 utils::zero_object(values); \
245 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \
248 GLenum actual_internal_fmt;
249 GET_INT(actual_internal_fmt, GL_TEXTURE_INTERNAL_FORMAT);
251 f.m_tex_image_flags = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4));
252 f.m_fmt = base_internal_fmt;
253 f.m_actual_internal_fmt = actual_internal_fmt;
254 f.m_name = g_gl_enums.find_name(base_internal_fmt, "gl");
256 GET_INT(f.m_comp_sizes[cTCRed], GL_TEXTURE_RED_SIZE);
257 GET_INT(f.m_comp_sizes[cTCGreen], GL_TEXTURE_GREEN_SIZE);
258 GET_INT(f.m_comp_sizes[cTCBlue], GL_TEXTURE_BLUE_SIZE);
259 GET_INT(f.m_comp_sizes[cTCAlpha], GL_TEXTURE_ALPHA_SIZE);
260 GET_INT(f.m_comp_sizes[cTCStencil], GL_TEXTURE_STENCIL_SIZE);
261 GET_INT(f.m_comp_sizes[cTCDepth], GL_TEXTURE_DEPTH_SIZE);
262 GET_INT(f.m_comp_sizes[cTCIntensity], GL_TEXTURE_INTENSITY_SIZE);
263 GET_INT(f.m_comp_sizes[cTCLuminance], GL_TEXTURE_LUMINANCE_SIZE);
265 GET_INT(f.m_comp_types[cTCRed], GL_TEXTURE_RED_TYPE);
266 GET_INT(f.m_comp_types[cTCGreen], GL_TEXTURE_GREEN_TYPE);
267 GET_INT(f.m_comp_types[cTCBlue], GL_TEXTURE_BLUE_TYPE);
268 GET_INT(f.m_comp_types[cTCAlpha], GL_TEXTURE_ALPHA_TYPE);
269 GET_INT(f.m_comp_types[cTCDepth], GL_TEXTURE_DEPTH_TYPE);
270 GET_INT(f.m_comp_types[cTCIntensity], GL_TEXTURE_INTENSITY_TYPE);
271 GET_INT(f.m_comp_types[cTCLuminance], GL_TEXTURE_LUMINANCE_TYPE);
273 GET_INT(f.m_shared_size, GL_TEXTURE_SHARED_SIZE);
274 GET_INT(f.m_compressed, GL_TEXTURE_COMPRESSED);
276 printf("base_internal_fmt: %s get_fmt: %s get_type: %s, actual_internal_fmt: %s compressed: %u\n",
277 g_gl_enums.find_gl_name(base_internal_fmt), g_gl_enums.find_gl_name(get_fmt), g_gl_enums.find_gl_name(get_type),
278 g_gl_enums.find_gl_name(actual_internal_fmt),
282 //VOGL_ASSERT(!any_gl_errors);
284 VOGL_ASSERT(f.m_actual_internal_fmt != GL_NONE);
285 VOGL_ASSERT(f.m_optimum_get_image_fmt != GL_NONE);
286 VOGL_ASSERT(f.m_optimum_get_image_type != GL_NONE);
288 VOGL_ASSERT(!f.m_compressed);
289 VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(f.m_fmt) && !ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt));
290 VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_fmt) == 0 && ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) == 0);
292 if (!internal_formats.insert(base_internal_fmt, f).second)
294 internal_formats.find_value(base_internal_fmt)->m_tex_image_flags |= ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4));
297 GL_ENTRYPOINT(glBindTexture)(target, 0);
300 GL_ENTRYPOINT(glDeleteTextures)(1, &handle);
304 for (uint t = 0; t < 5; t++)
306 GLenum target = GL_NONE;
311 target = GL_TEXTURE_1D;
316 target = GL_TEXTURE_2D;
321 target = GL_TEXTURE_3D;
326 target = GL_TEXTURE_2D_MULTISAMPLE;
331 target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
341 for (uint fmt = 0; fmt <= 0xFFFF; fmt++)
344 GL_ENTRYPOINT(glGenTextures)(1, &handle);
347 GL_ENTRYPOINT(glBindTexture)(target, handle);
349 vogl_debug_message_control(context_info, GL_INVALID_ENUM, false);
350 vogl_debug_message_control(context_info, GL_INVALID_OPERATION, false);
358 GL_ENTRYPOINT(glTexStorage1D)(target, 1, fmt, 32);
359 failed = vogl_check_gl_error_suppress_message();
364 GL_ENTRYPOINT(glTexStorage2D)(target, 1, fmt, 32, 32);
365 failed = vogl_check_gl_error_suppress_message();
370 GL_ENTRYPOINT(glTexStorage3D)(target, 1, fmt, 32, 32, 32);
371 failed = vogl_check_gl_error_suppress_message();
376 GL_ENTRYPOINT(glTexStorage2DMultisample)(target, 2, fmt, 32, 32, GL_TRUE);
377 failed = vogl_check_gl_error_suppress_message();
382 GL_ENTRYPOINT(glTexStorage3DMultisample)(target, 2, fmt, 32, 32, 2, GL_TRUE);
383 failed = vogl_check_gl_error_suppress_message();
388 vogl_debug_message_control(context_info, GL_INVALID_ENUM, true);
389 vogl_debug_message_control(context_info, GL_INVALID_OPERATION, true);
394 bool any_gl_errors = false;
395 VOGL_NOTE_UNUSED(any_gl_errors);
397 vogl_internal_tex_format f;
398 f.m_tex_image_flags = (1 << t);
400 f.m_actual_internal_fmt = fmt; // this assumes the actual internal fmt will match here!
401 f.m_name = g_gl_enums.find_name(fmt, "gl");
403 #define GET_INT(dst, gl_enum) \
407 utils::zero_object(values); \
408 GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \
413 GET_INT(internal_fmt, GL_TEXTURE_INTERNAL_FORMAT);
414 VOGL_ASSERT(internal_fmt == fmt);
415 GET_INT(f.m_comp_sizes[cTCRed], GL_TEXTURE_RED_SIZE);
416 GET_INT(f.m_comp_sizes[cTCGreen], GL_TEXTURE_GREEN_SIZE);
417 GET_INT(f.m_comp_sizes[cTCBlue], GL_TEXTURE_BLUE_SIZE);
418 GET_INT(f.m_comp_sizes[cTCAlpha], GL_TEXTURE_ALPHA_SIZE);
419 GET_INT(f.m_comp_sizes[cTCStencil], GL_TEXTURE_STENCIL_SIZE);
420 GET_INT(f.m_comp_sizes[cTCDepth], GL_TEXTURE_DEPTH_SIZE);
421 GET_INT(f.m_comp_sizes[cTCIntensity], GL_TEXTURE_INTENSITY_SIZE);
422 GET_INT(f.m_comp_sizes[cTCLuminance], GL_TEXTURE_LUMINANCE_SIZE);
424 GET_INT(f.m_comp_types[cTCRed], GL_TEXTURE_RED_TYPE);
425 GET_INT(f.m_comp_types[cTCGreen], GL_TEXTURE_GREEN_TYPE);
426 GET_INT(f.m_comp_types[cTCBlue], GL_TEXTURE_BLUE_TYPE);
427 GET_INT(f.m_comp_types[cTCAlpha], GL_TEXTURE_ALPHA_TYPE);
428 GET_INT(f.m_comp_types[cTCDepth], GL_TEXTURE_DEPTH_TYPE);
429 GET_INT(f.m_comp_types[cTCIntensity], GL_TEXTURE_INTENSITY_TYPE);
430 GET_INT(f.m_comp_types[cTCLuminance], GL_TEXTURE_LUMINANCE_TYPE);
432 GET_INT(f.m_shared_size, GL_TEXTURE_SHARED_SIZE);
433 GET_INT(f.m_compressed, GL_TEXTURE_COMPRESSED);
436 VOGL_ASSERT(!any_gl_errors);
438 GL_ENTRYPOINT(glGetInternalformativ)(target, fmt, GL_GET_TEXTURE_IMAGE_TYPE, sizeof(f.m_optimum_get_image_type), (GLint *)&f.m_optimum_get_image_type);
439 GL_ENTRYPOINT(glGetInternalformativ)(target, fmt, GL_GET_TEXTURE_IMAGE_FORMAT, sizeof(f.m_optimum_get_image_fmt), (GLint *)&f.m_optimum_get_image_fmt);
444 f.m_optimum_get_image_fmt = GL_RGBA;
445 f.m_optimum_get_image_type = GL_UNSIGNED_BYTE;
449 #define HANDLE_FMT(gl_enum, fmt, type) \
452 f.m_optimum_get_image_fmt = fmt; \
453 f.m_optimum_get_image_type = type; \
456 bool unhandled = false;
459 HANDLE_FMT(GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV);
460 HANDLE_FMT(GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);
461 HANDLE_FMT(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
462 HANDLE_FMT(GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
463 HANDLE_FMT(GL_INTENSITY32F_ARB, GL_RED, GL_FLOAT);
465 HANDLE_FMT(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
466 HANDLE_FMT(3, GL_RGB, GL_UNSIGNED_BYTE);
467 HANDLE_FMT(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
468 HANDLE_FMT(GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
469 HANDLE_FMT(GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
470 HANDLE_FMT(GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT);
471 HANDLE_FMT(GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT);
472 HANDLE_FMT(GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT);
474 HANDLE_FMT(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE);
475 HANDLE_FMT(GL_RGB8I, GL_RGB_INTEGER, GL_BYTE);
476 HANDLE_FMT(GL_RGB10, GL_RGB, GL_UNSIGNED_SHORT);
477 HANDLE_FMT(GL_RGB12, GL_RGB, GL_UNSIGNED_SHORT);
478 HANDLE_FMT(GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT);
479 HANDLE_FMT(GL_RGBA12, GL_RGB, GL_UNSIGNED_SHORT);
480 HANDLE_FMT(GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
481 HANDLE_FMT(GL_RG16, GL_RG, GL_UNSIGNED_SHORT);
482 HANDLE_FMT(GL_RG16F, GL_RG, GL_HALF_FLOAT);
483 HANDLE_FMT(GL_RG32F, GL_RG, GL_FLOAT);
485 HANDLE_FMT(GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE);
486 HANDLE_FMT(GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE);
487 HANDLE_FMT(GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_BYTE);
489 HANDLE_FMT(GL_RGB32I, GL_RGB_INTEGER, GL_INT);
490 HANDLE_FMT(GL_RGB16I, GL_RGB_INTEGER, GL_SHORT);
492 HANDLE_FMT(GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT);
493 HANDLE_FMT(GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT);
494 HANDLE_FMT(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_INT);
495 HANDLE_FMT(GL_SIGNED_RGBA8_NV, GL_RGBA, GL_BYTE);
496 HANDLE_FMT(GL_SIGNED_RGB8_NV, GL_RGB, GL_BYTE);
497 HANDLE_FMT(GL_SIGNED_LUMINANCE8_ALPHA8_NV, GL_LUMINANCE_ALPHA, GL_BYTE);
498 HANDLE_FMT(GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV, GL_RGBA, GL_BYTE);
499 HANDLE_FMT(GL_RG8_SNORM, GL_RG, GL_BYTE);
500 HANDLE_FMT(GL_RGB8_SNORM, GL_RGB, GL_BYTE);
501 HANDLE_FMT(GL_RG16_SNORM, GL_RG, GL_SHORT);
502 HANDLE_FMT(GL_RGB16_SNORM, GL_RGB, GL_SHORT);
504 HANDLE_FMT(GL_RGB32F, GL_RGB, GL_FLOAT);
505 HANDLE_FMT(GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
507 // TODO: Research oddball formats
508 HANDLE_FMT(GL_PALETTE4_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE);
509 HANDLE_FMT(GL_PALETTE4_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_BYTE);
510 HANDLE_FMT(GL_PALETTE8_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE);
511 HANDLE_FMT(GL_PALETTE8_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_BYTE);
513 HANDLE_FMT(GL_HILO16_NV, GL_NONE, GL_NONE);
514 HANDLE_FMT(GL_SIGNED_HILO16_NV, GL_NONE, GL_NONE);
515 HANDLE_FMT(GL_DSDT8_MAG8_INTENSITY8_NV, GL_NONE, GL_NONE);
516 HANDLE_FMT(GL_HILO8_NV, GL_NONE, GL_NONE);
517 HANDLE_FMT(GL_SIGNED_HILO8_NV, GL_NONE, GL_NONE);
518 HANDLE_FMT(GL_DSDT8_NV, GL_NONE, GL_NONE);
519 HANDLE_FMT(GL_DSDT8_MAG8_NV, GL_NONE, GL_NONE);
526 if ((unhandled) && ((f.m_optimum_get_image_fmt == GL_NONE) || (f.m_optimum_get_image_type == GL_NONE)))
528 printf("INVALID: %s %s %s\n", f.m_name.get_ptr(), g_gl_enums.find_name(f.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(f.m_optimum_get_image_type, "gl"));
534 VOGL_ASSERT(f.m_actual_internal_fmt != GL_NONE);
536 if ((f.m_optimum_get_image_fmt == GL_NONE) || (f.m_optimum_get_image_type == GL_NONE))
537 vogl_warning_printf("%s: Don't have an optimal get format/type for internal format %s\n", VOGL_FUNCTION_NAME, g_gl_enums.find_gl_name(fmt));
539 VOGL_ASSERT(fmt != GL_LUMINANCE);
541 VOGL_ASSERT(f.m_fmt == f.m_actual_internal_fmt);
544 VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(f.m_fmt) && !ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt));
545 VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_fmt) == 0 && ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) == 0);
549 VOGL_ASSERT(ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt));
550 VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) != 0);
553 if (!internal_formats.insert(fmt, f).second)
555 internal_formats.find_value(fmt)->m_tex_image_flags |= (1 << t);
558 GL_ENTRYPOINT(glBindTexture)(target, 0);
561 GL_ENTRYPOINT(glDeleteTextures)(1, &handle);
566 const char *pOutput_filename = "internal_texture_formats.inc";
567 FILE *pFile = vogl_fopen(pOutput_filename, "w");
572 for (tex_format_map::const_iterator it = internal_formats.begin(); it != internal_formats.end(); ++it)
574 vogl_internal_tex_format fmt(it->second);
576 uint actual_size = 0;
578 if (!fmt.m_compressed)
580 VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(fmt.m_fmt));
581 VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(fmt.m_fmt) == 0);
585 VOGL_ASSERT(ktx_is_compressed_ogl_fmt(fmt.m_fmt));
586 VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(fmt.m_fmt) != 0);
589 if ((!fmt.m_compressed) && (fmt.m_optimum_get_image_fmt != GL_NONE) && (fmt.m_optimum_get_image_type != GL_NONE))
592 GL_ENTRYPOINT(glGenTextures)(1, &handle);
595 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle);
599 utils::zero_object(vals);
601 GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, fmt.m_fmt, 1, 1, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, vals);
602 if (vogl_check_gl_error())
604 printf("glTexImage2D FAILED: %s %s %s\n", fmt.m_name.get_ptr(), g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"));
608 memset(gvals, 0xCD, sizeof(gvals));
609 GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, gvals);
611 uint actual_size0 = 0;
612 for (actual_size0 = 0; actual_size0 < sizeof(gvals); actual_size0++)
613 if (gvals[actual_size0] == 0xCD)
616 memset(gvals, 0x12, sizeof(gvals));
617 GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, gvals);
619 uint actual_size1 = 0;
620 for (actual_size1 = 0; actual_size1 < sizeof(gvals); actual_size1++)
621 if (gvals[actual_size1] == 0x12)
624 VOGL_VERIFY(actual_size0 == actual_size1);
626 //printf("glGetTexImage() wrote %u bytes\n", actual_size0);
628 if (vogl_check_gl_error()) // || gvals[1] != vals[1])
630 printf("glGetTexImage() failed: %s %s %s\n", fmt.m_name.get_ptr(), g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"));
633 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, 0);
636 GL_ENTRYPOINT(glDeleteTextures)(1, &handle);
638 actual_size = actual_size0;
640 uint s = vogl_get_image_format_size_in_bytes(fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type);
642 if (s != actual_size0)
647 vogl::ktx_texture ktx_tex;
650 img_fmt = fmt.m_optimum_get_image_fmt;
651 img_type = fmt.m_optimum_get_image_type;
653 uint block_dim, bytes_per_block;
654 bool success = ktx_get_ogl_fmt_desc(img_fmt, img_type, block_dim, bytes_per_block);
655 VOGL_VERIFY(success);
656 VOGL_VERIFY(block_dim == 1);
657 VOGL_VERIFY(bytes_per_block == actual_size);
659 if (!ktx_tex.init_2D(1, 1, 1, fmt.m_fmt, img_fmt, img_type))
661 printf("ktx_texture::init_2D() failed: %s %s %s\n", fmt.m_name.get_ptr(), g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"));
664 else if (fmt.m_compressed)
667 GL_ENTRYPOINT(glGenTextures)(1, &handle);
670 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle);
673 GL_ENTRYPOINT(glTexStorage2D)(GL_TEXTURE_2D, 1, fmt.m_fmt, 1, 1);
676 GL_ENTRYPOINT(glGetTexLevelParameteriv)(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&actual_size);
679 GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, 0);
682 GL_ENTRYPOINT(glDeleteTextures)(1, &handle);
685 uint block_width = 0, block_height = 0, block_size = 0;
686 GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_WIDTH, sizeof(int), reinterpret_cast<GLint *>(&block_width));
687 GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT, sizeof(int), reinterpret_cast<GLint *>(&block_height));
688 GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_SIZE, sizeof(int), reinterpret_cast<GLint *>(&block_size));
691 if (block_size == actual_size * 8U)
694 uint block_dim, bytes_per_block;
695 bool success = ktx_get_ogl_fmt_desc(fmt.m_fmt, GL_UNSIGNED_BYTE, block_dim, bytes_per_block);
696 if ((!success) || (block_dim != block_width) || (block_dim != block_height) || (bytes_per_block != actual_size) || (bytes_per_block != block_size))
698 printf("ktx_get_ogl_fmt_desc on compressed format failed: %s %s %s %u %i %i %i\n", fmt.m_name.get_ptr(), g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"), actual_size, block_width, block_height, block_size);
701 fmt.m_block_width = block_width;
702 fmt.m_block_height = block_height;
704 vogl::ktx_texture ktx_tex;
705 if (!ktx_tex.init_2D(1, 1, 1, fmt.m_fmt, GL_NONE, GL_NONE))
707 printf("ktx_texture::init_2D() compressed failed: %s %s %s\n", fmt.m_name.get_ptr(), g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"), g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"));
711 fmt.m_image_bytes_per_pixel_or_block = actual_size;
713 fprintf(pFile, " vogl_internal_tex_format(0x%04X, \"%s\", 0x%04X,\n", fmt.m_fmt, fmt.m_name.get_ptr(), fmt.m_actual_internal_fmt);
716 for (uint i = 0; i < cTCTotalComponents; i++)
717 fprintf(pFile, "%u, ", fmt.m_comp_sizes[i]);
718 fprintf(pFile, "\n");
721 for (uint i = 0; i < cTCTotalComponents; i++)
722 fprintf(pFile, "%s, ", g_gl_enums.find_name(fmt.m_comp_types[i], "gl"));
723 fprintf(pFile, "\n");
725 fprintf(pFile, " %u, 0x%02X, %u, \n", fmt.m_shared_size, fmt.m_tex_image_flags, fmt.m_compressed);
726 fprintf(pFile, " %s, %s, %u, %u, %u),\n",
727 g_gl_enums.find_name(fmt.m_optimum_get_image_fmt, "gl"),
728 g_gl_enums.find_name(fmt.m_optimum_get_image_type, "gl"),
729 fmt.m_image_bytes_per_pixel_or_block,
730 fmt.m_block_width, fmt.m_block_height);
734 for (q = 0; q < g_vogl_total_internal_texture_formats; q++)
736 if (g_vogl_internal_texture_formats[q].m_fmt == fmt.m_fmt)
738 if (!g_vogl_internal_texture_formats[q].compare(fmt))
745 if (q == g_vogl_total_internal_texture_formats)
754 printf("Wrote file %s\n", pOutput_filename);
757 //----------------------------------------------------------------------------------------------------------------------
758 // vogl_internal_tex_format::vogl_internal_tex_format
759 //----------------------------------------------------------------------------------------------------------------------
760 vogl_internal_tex_format::vogl_internal_tex_format(
761 GLenum fmt, const char *pName, GLenum actual_fmt,
762 int s0, int s1, int s2, int s3, int s4, int s5, int s6, int s7,
763 GLenum t0, GLenum t1, GLenum t2, GLenum t3, GLenum t4, GLenum t5, GLenum t6, GLenum t7,
764 int shared_size, int tex_storage_type_flags, bool compressed, GLenum optimum_get_fmt, GLenum optimum_get_type,
765 uint image_bytes_per_pixel_or_block, uint block_width, uint block_height)
769 //VOGL_VERIFY(optimum_get_fmt != GL_NONE);
770 //VOGL_VERIFY(optimum_get_type != GL_NONE);
774 m_actual_internal_fmt = actual_fmt;
775 m_comp_sizes[0] = s0;
776 m_comp_sizes[1] = s1;
777 m_comp_sizes[2] = s2;
778 m_comp_sizes[3] = s3;
779 m_comp_sizes[4] = s4;
780 m_comp_sizes[5] = s5;
781 m_comp_sizes[6] = s6;
782 m_comp_sizes[7] = s7;
783 m_comp_types[0] = t0;
784 m_comp_types[1] = t1;
785 m_comp_types[2] = t2;
786 m_comp_types[3] = t3;
787 m_comp_types[4] = t4;
788 m_comp_types[5] = t5;
789 m_comp_types[6] = t6;
790 m_comp_types[7] = t7;
791 m_shared_size = shared_size;
792 m_tex_image_flags = tex_storage_type_flags;
793 m_compressed = compressed;
794 m_optimum_get_image_fmt = optimum_get_fmt;
795 m_optimum_get_image_type = optimum_get_type;
796 m_image_bytes_per_pixel_or_block = image_bytes_per_pixel_or_block;
797 m_block_width = block_width;
798 m_block_height = block_height;
801 //----------------------------------------------------------------------------------------------------------------------
802 // vogl_internal_tex_format::compare
803 //----------------------------------------------------------------------------------------------------------------------
804 bool vogl_internal_tex_format::compare(const vogl_internal_tex_format &rhs) const
813 CMP(m_actual_internal_fmt);
814 for (uint i = 0; i < cTCTotalComponents; i++)
816 CMP(m_comp_sizes[i]);
817 CMP(m_comp_types[i]);
820 CMP(m_tex_image_flags);
821 CMP(m_optimum_get_image_fmt);
822 CMP(m_optimum_get_image_type);
823 CMP(m_image_bytes_per_pixel_or_block);
832 //----------------------------------------------------------------------------------------------------------------------
833 // vogl_texture_format_init
834 //----------------------------------------------------------------------------------------------------------------------
835 void vogl_texture_format_init()
839 VOGL_ASSERT(g_vogl_internal_texture_formats[0].m_fmt);
841 g_internal_format_hash_map.reserve(g_vogl_total_internal_texture_formats);
843 for (uint i = 0; i < g_vogl_total_internal_texture_formats; i++)
845 bool success = g_internal_format_hash_map.insert(g_vogl_internal_texture_formats[i].m_fmt, &g_vogl_internal_texture_formats[i]).second;
846 VOGL_VERIFY(success);
850 //----------------------------------------------------------------------------------------------------------------------
851 // vogl_find_internal_texture_format
852 //----------------------------------------------------------------------------------------------------------------------
853 const vogl_internal_tex_format *vogl_find_internal_texture_format(GLenum internal_format)
857 VOGL_ASSERT(g_internal_format_hash_map.size());
859 vogl_internal_tex_format **ppFmt = g_internal_format_hash_map.find_value(internal_format);
860 return ppFmt ? *ppFmt : NULL;