virtualx-engine/thirdparty/libktx/lib/dfdutils/printdfd.c
2024-02-22 12:25:27 +01:00

1025 lines
38 KiB
C

/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/* Copyright 2019-2020 The Khronos Group Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @~English
* @brief Utilities for printing data format descriptors.
*/
/*
* Author: Andrew Garrard
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <KHR/khr_df.h>
#include "dfd.h"
enum {
// These constraints are not mandated by the spec and only used as a
// reasonable upper limit to stop parsing garbage data during print
MAX_NUM_BDFD_SAMPLES = 16,
MAX_NUM_DFD_BLOCKS = 10,
};
const char* dfdToStringVendorID(khr_df_vendorid_e value) {
switch (value) {
case KHR_DF_VENDORID_KHRONOS:
return "KHR_DF_VENDORID_KHRONOS";
case KHR_DF_VENDORID_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringDescriptorType(khr_df_khr_descriptortype_e value) {
switch (value) {
case KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT:
return "KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT";
case KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES:
return "KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES";
case KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS:
return "KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS";
case KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT:
case KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT:
case KHR_DF_KHR_DESCRIPTORTYPE_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringVersionNumber(khr_df_versionnumber_e value) {
switch (value) {
case KHR_DF_VERSIONNUMBER_1_1:
// case KHR_DF_VERSIONNUMBER_1_0: // Fallthrough, Matching values
return "KHR_DF_VERSIONNUMBER_1_1";
case KHR_DF_VERSIONNUMBER_1_2:
return "KHR_DF_VERSIONNUMBER_1_2";
case KHR_DF_VERSIONNUMBER_1_3:
return "KHR_DF_VERSIONNUMBER_1_3";
// case KHR_DF_VERSIONNUMBER_LATEST: // Fallthrough, Matching values
case KHR_DF_VERSIONNUMBER_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringFlagsBit(uint32_t bit_index, bool bit_value) {
switch (bit_index) {
case 0:
return bit_value ? "KHR_DF_FLAG_ALPHA_PREMULTIPLIED" : "KHR_DF_FLAG_ALPHA_STRAIGHT";
default:
return NULL;
}
}
const char* dfdToStringTransferFunction(khr_df_transfer_e value) {
switch (value) {
case KHR_DF_TRANSFER_UNSPECIFIED:
return "KHR_DF_TRANSFER_UNSPECIFIED";
case KHR_DF_TRANSFER_LINEAR:
return "KHR_DF_TRANSFER_LINEAR";
case KHR_DF_TRANSFER_SRGB:
return "KHR_DF_TRANSFER_SRGB";
case KHR_DF_TRANSFER_ITU:
return "KHR_DF_TRANSFER_ITU";
case KHR_DF_TRANSFER_NTSC:
// case KHR_DF_TRANSFER_SMTPE170M: // Fallthrough, Matching values
return "KHR_DF_TRANSFER_NTSC";
case KHR_DF_TRANSFER_SLOG:
return "KHR_DF_TRANSFER_SLOG";
case KHR_DF_TRANSFER_SLOG2:
return "KHR_DF_TRANSFER_SLOG2";
case KHR_DF_TRANSFER_BT1886:
return "KHR_DF_TRANSFER_BT1886";
case KHR_DF_TRANSFER_HLG_OETF:
return "KHR_DF_TRANSFER_HLG_OETF";
case KHR_DF_TRANSFER_HLG_EOTF:
return "KHR_DF_TRANSFER_HLG_EOTF";
case KHR_DF_TRANSFER_PQ_EOTF:
return "KHR_DF_TRANSFER_PQ_EOTF";
case KHR_DF_TRANSFER_PQ_OETF:
return "KHR_DF_TRANSFER_PQ_OETF";
case KHR_DF_TRANSFER_DCIP3:
return "KHR_DF_TRANSFER_DCIP3";
case KHR_DF_TRANSFER_PAL_OETF:
return "KHR_DF_TRANSFER_PAL_OETF";
case KHR_DF_TRANSFER_PAL625_EOTF:
return "KHR_DF_TRANSFER_PAL625_EOTF";
case KHR_DF_TRANSFER_ST240:
return "KHR_DF_TRANSFER_ST240";
case KHR_DF_TRANSFER_ACESCC:
return "KHR_DF_TRANSFER_ACESCC";
case KHR_DF_TRANSFER_ACESCCT:
return "KHR_DF_TRANSFER_ACESCCT";
case KHR_DF_TRANSFER_ADOBERGB:
return "KHR_DF_TRANSFER_ADOBERGB";
case KHR_DF_TRANSFER_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringColorPrimaries(khr_df_primaries_e value) {
switch (value) {
case KHR_DF_PRIMARIES_UNSPECIFIED:
return "KHR_DF_PRIMARIES_UNSPECIFIED";
case KHR_DF_PRIMARIES_BT709:
// case KHR_DF_PRIMARIES_SRGB: // Fallthrough, Matching values
return "KHR_DF_PRIMARIES_BT709";
case KHR_DF_PRIMARIES_BT601_EBU:
return "KHR_DF_PRIMARIES_BT601_EBU";
case KHR_DF_PRIMARIES_BT601_SMPTE:
return "KHR_DF_PRIMARIES_BT601_SMPTE";
case KHR_DF_PRIMARIES_BT2020:
return "KHR_DF_PRIMARIES_BT2020";
case KHR_DF_PRIMARIES_CIEXYZ:
return "KHR_DF_PRIMARIES_CIEXYZ";
case KHR_DF_PRIMARIES_ACES:
return "KHR_DF_PRIMARIES_ACES";
case KHR_DF_PRIMARIES_ACESCC:
return "KHR_DF_PRIMARIES_ACESCC";
case KHR_DF_PRIMARIES_NTSC1953:
return "KHR_DF_PRIMARIES_NTSC1953";
case KHR_DF_PRIMARIES_PAL525:
return "KHR_DF_PRIMARIES_PAL525";
case KHR_DF_PRIMARIES_DISPLAYP3:
return "KHR_DF_PRIMARIES_DISPLAYP3";
case KHR_DF_PRIMARIES_ADOBERGB:
return "KHR_DF_PRIMARIES_ADOBERGB";
case KHR_DF_PRIMARIES_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringColorModel(khr_df_model_e value) {
switch (value) {
case KHR_DF_MODEL_UNSPECIFIED:
return "KHR_DF_MODEL_UNSPECIFIED";
case KHR_DF_MODEL_RGBSDA:
return "KHR_DF_MODEL_RGBSDA";
case KHR_DF_MODEL_YUVSDA:
return "KHR_DF_MODEL_YUVSDA";
case KHR_DF_MODEL_YIQSDA:
return "KHR_DF_MODEL_YIQSDA";
case KHR_DF_MODEL_LABSDA:
return "KHR_DF_MODEL_LABSDA";
case KHR_DF_MODEL_CMYKA:
return "KHR_DF_MODEL_CMYKA";
case KHR_DF_MODEL_XYZW:
return "KHR_DF_MODEL_XYZW";
case KHR_DF_MODEL_HSVA_ANG:
return "KHR_DF_MODEL_HSVA_ANG";
case KHR_DF_MODEL_HSLA_ANG:
return "KHR_DF_MODEL_HSLA_ANG";
case KHR_DF_MODEL_HSVA_HEX:
return "KHR_DF_MODEL_HSVA_HEX";
case KHR_DF_MODEL_HSLA_HEX:
return "KHR_DF_MODEL_HSLA_HEX";
case KHR_DF_MODEL_YCGCOA:
return "KHR_DF_MODEL_YCGCOA";
case KHR_DF_MODEL_YCCBCCRC:
return "KHR_DF_MODEL_YCCBCCRC";
case KHR_DF_MODEL_ICTCP:
return "KHR_DF_MODEL_ICTCP";
case KHR_DF_MODEL_CIEXYZ:
return "KHR_DF_MODEL_CIEXYZ";
case KHR_DF_MODEL_CIEXYY:
return "KHR_DF_MODEL_CIEXYY";
case KHR_DF_MODEL_BC1A:
// case KHR_DF_MODEL_DXT1A: // Fallthrough, Matching values
return "KHR_DF_MODEL_BC1A";
case KHR_DF_MODEL_BC2:
// case KHR_DF_MODEL_DXT2: // Fallthrough, Matching values
// case KHR_DF_MODEL_DXT3: // Fallthrough, Matching values
return "KHR_DF_MODEL_BC2";
case KHR_DF_MODEL_BC3:
// case KHR_DF_MODEL_DXT4: // Fallthrough, Matching values
// case KHR_DF_MODEL_DXT5: // Fallthrough, Matching values
return "KHR_DF_MODEL_BC3";
case KHR_DF_MODEL_BC4:
return "KHR_DF_MODEL_BC4";
case KHR_DF_MODEL_BC5:
return "KHR_DF_MODEL_BC5";
case KHR_DF_MODEL_BC6H:
return "KHR_DF_MODEL_BC6H";
case KHR_DF_MODEL_BC7:
return "KHR_DF_MODEL_BC7";
case KHR_DF_MODEL_ETC1:
return "KHR_DF_MODEL_ETC1";
case KHR_DF_MODEL_ETC2:
return "KHR_DF_MODEL_ETC2";
case KHR_DF_MODEL_ASTC:
return "KHR_DF_MODEL_ASTC";
case KHR_DF_MODEL_ETC1S:
return "KHR_DF_MODEL_ETC1S";
case KHR_DF_MODEL_PVRTC:
return "KHR_DF_MODEL_PVRTC";
case KHR_DF_MODEL_PVRTC2:
return "KHR_DF_MODEL_PVRTC2";
case KHR_DF_MODEL_UASTC:
return "KHR_DF_MODEL_UASTC";
case KHR_DF_MODEL_MAX:
// These enum values are not meant for string representation. Ignore
break;
}
return NULL;
}
const char* dfdToStringSampleDatatypeQualifiers(uint32_t bit_index, bool bit_value) {
if (!bit_value)
return NULL;
switch (1u << bit_index) {
case KHR_DF_SAMPLE_DATATYPE_LINEAR:
return "KHR_DF_SAMPLE_DATATYPE_LINEAR";
case KHR_DF_SAMPLE_DATATYPE_EXPONENT:
return "KHR_DF_SAMPLE_DATATYPE_EXPONENT";
case KHR_DF_SAMPLE_DATATYPE_SIGNED:
return "KHR_DF_SAMPLE_DATATYPE_SIGNED";
case KHR_DF_SAMPLE_DATATYPE_FLOAT:
return "KHR_DF_SAMPLE_DATATYPE_FLOAT";
}
return NULL;
}
const char* dfdToStringChannelId(khr_df_model_e model, khr_df_model_channels_e value) {
switch (model) {
case KHR_DF_MODEL_RGBSDA:
switch (value) {
case KHR_DF_CHANNEL_RGBSDA_RED:
return "KHR_DF_CHANNEL_RGBSDA_RED";
case KHR_DF_CHANNEL_RGBSDA_GREEN:
return "KHR_DF_CHANNEL_RGBSDA_GREEN";
case KHR_DF_CHANNEL_RGBSDA_BLUE:
return "KHR_DF_CHANNEL_RGBSDA_BLUE";
case KHR_DF_CHANNEL_RGBSDA_STENCIL:
return "KHR_DF_CHANNEL_RGBSDA_STENCIL";
case KHR_DF_CHANNEL_RGBSDA_DEPTH:
return "KHR_DF_CHANNEL_RGBSDA_DEPTH";
case KHR_DF_CHANNEL_RGBSDA_ALPHA:
return "KHR_DF_CHANNEL_RGBSDA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_YUVSDA:
switch (value) {
case KHR_DF_CHANNEL_YUVSDA_Y:
return "KHR_DF_CHANNEL_YUVSDA_Y";
case KHR_DF_CHANNEL_YUVSDA_U:
return "KHR_DF_CHANNEL_YUVSDA_U";
case KHR_DF_CHANNEL_YUVSDA_V:
return "KHR_DF_CHANNEL_YUVSDA_V";
case KHR_DF_CHANNEL_YUVSDA_STENCIL:
return "KHR_DF_CHANNEL_YUVSDA_STENCIL";
case KHR_DF_CHANNEL_YUVSDA_DEPTH:
return "KHR_DF_CHANNEL_YUVSDA_DEPTH";
case KHR_DF_CHANNEL_YUVSDA_ALPHA:
return "KHR_DF_CHANNEL_YUVSDA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_YIQSDA:
switch (value) {
case KHR_DF_CHANNEL_YIQSDA_Y:
return "KHR_DF_CHANNEL_YIQSDA_Y";
case KHR_DF_CHANNEL_YIQSDA_I:
return "KHR_DF_CHANNEL_YIQSDA_I";
case KHR_DF_CHANNEL_YIQSDA_Q:
return "KHR_DF_CHANNEL_YIQSDA_Q";
case KHR_DF_CHANNEL_YIQSDA_STENCIL:
return "KHR_DF_CHANNEL_YIQSDA_STENCIL";
case KHR_DF_CHANNEL_YIQSDA_DEPTH:
return "KHR_DF_CHANNEL_YIQSDA_DEPTH";
case KHR_DF_CHANNEL_YIQSDA_ALPHA:
return "KHR_DF_CHANNEL_YIQSDA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_LABSDA:
switch (value) {
case KHR_DF_CHANNEL_LABSDA_L:
return "KHR_DF_CHANNEL_LABSDA_L";
case KHR_DF_CHANNEL_LABSDA_A:
return "KHR_DF_CHANNEL_LABSDA_A";
case KHR_DF_CHANNEL_LABSDA_B:
return "KHR_DF_CHANNEL_LABSDA_B";
case KHR_DF_CHANNEL_LABSDA_STENCIL:
return "KHR_DF_CHANNEL_LABSDA_STENCIL";
case KHR_DF_CHANNEL_LABSDA_DEPTH:
return "KHR_DF_CHANNEL_LABSDA_DEPTH";
case KHR_DF_CHANNEL_LABSDA_ALPHA:
return "KHR_DF_CHANNEL_LABSDA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_CMYKA:
switch (value) {
case KHR_DF_CHANNEL_CMYKSDA_CYAN:
return "KHR_DF_CHANNEL_CMYKSDA_CYAN";
case KHR_DF_CHANNEL_CMYKSDA_MAGENTA:
return "KHR_DF_CHANNEL_CMYKSDA_MAGENTA";
case KHR_DF_CHANNEL_CMYKSDA_YELLOW:
return "KHR_DF_CHANNEL_CMYKSDA_YELLOW";
case KHR_DF_CHANNEL_CMYKSDA_BLACK:
return "KHR_DF_CHANNEL_CMYKSDA_BLACK";
case KHR_DF_CHANNEL_CMYKSDA_ALPHA:
return "KHR_DF_CHANNEL_CMYKSDA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_XYZW:
switch (value) {
case KHR_DF_CHANNEL_XYZW_X:
return "KHR_DF_CHANNEL_XYZW_X";
case KHR_DF_CHANNEL_XYZW_Y:
return "KHR_DF_CHANNEL_XYZW_Y";
case KHR_DF_CHANNEL_XYZW_Z:
return "KHR_DF_CHANNEL_XYZW_Z";
case KHR_DF_CHANNEL_XYZW_W:
return "KHR_DF_CHANNEL_XYZW_W";
default:
return NULL;
}
case KHR_DF_MODEL_HSVA_ANG:
switch (value) {
case KHR_DF_CHANNEL_HSVA_ANG_VALUE:
return "KHR_DF_CHANNEL_HSVA_ANG_VALUE";
case KHR_DF_CHANNEL_HSVA_ANG_SATURATION:
return "KHR_DF_CHANNEL_HSVA_ANG_SATURATION";
case KHR_DF_CHANNEL_HSVA_ANG_HUE:
return "KHR_DF_CHANNEL_HSVA_ANG_HUE";
case KHR_DF_CHANNEL_HSVA_ANG_ALPHA:
return "KHR_DF_CHANNEL_HSVA_ANG_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_HSLA_ANG:
switch (value) {
case KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS:
return "KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS";
case KHR_DF_CHANNEL_HSLA_ANG_SATURATION:
return "KHR_DF_CHANNEL_HSLA_ANG_SATURATION";
case KHR_DF_CHANNEL_HSLA_ANG_HUE:
return "KHR_DF_CHANNEL_HSLA_ANG_HUE";
case KHR_DF_CHANNEL_HSLA_ANG_ALPHA:
return "KHR_DF_CHANNEL_HSLA_ANG_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_HSVA_HEX:
switch (value) {
case KHR_DF_CHANNEL_HSVA_HEX_VALUE:
return "KHR_DF_CHANNEL_HSVA_HEX_VALUE";
case KHR_DF_CHANNEL_HSVA_HEX_SATURATION:
return "KHR_DF_CHANNEL_HSVA_HEX_SATURATION";
case KHR_DF_CHANNEL_HSVA_HEX_HUE:
return "KHR_DF_CHANNEL_HSVA_HEX_HUE";
case KHR_DF_CHANNEL_HSVA_HEX_ALPHA:
return "KHR_DF_CHANNEL_HSVA_HEX_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_HSLA_HEX:
switch (value) {
case KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS:
return "KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS";
case KHR_DF_CHANNEL_HSLA_HEX_SATURATION:
return "KHR_DF_CHANNEL_HSLA_HEX_SATURATION";
case KHR_DF_CHANNEL_HSLA_HEX_HUE:
return "KHR_DF_CHANNEL_HSLA_HEX_HUE";
case KHR_DF_CHANNEL_HSLA_HEX_ALPHA:
return "KHR_DF_CHANNEL_HSLA_HEX_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_YCGCOA:
switch (value) {
case KHR_DF_CHANNEL_YCGCOA_Y:
return "KHR_DF_CHANNEL_YCGCOA_Y";
case KHR_DF_CHANNEL_YCGCOA_CG:
return "KHR_DF_CHANNEL_YCGCOA_CG";
case KHR_DF_CHANNEL_YCGCOA_CO:
return "KHR_DF_CHANNEL_YCGCOA_CO";
case KHR_DF_CHANNEL_YCGCOA_ALPHA:
return "KHR_DF_CHANNEL_YCGCOA_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_CIEXYZ:
switch (value) {
case KHR_DF_CHANNEL_CIEXYZ_X:
return "KHR_DF_CHANNEL_CIEXYZ_X";
case KHR_DF_CHANNEL_CIEXYZ_Y:
return "KHR_DF_CHANNEL_CIEXYZ_Y";
case KHR_DF_CHANNEL_CIEXYZ_Z:
return "KHR_DF_CHANNEL_CIEXYZ_Z";
default:
return NULL;
}
case KHR_DF_MODEL_CIEXYY:
switch (value) {
case KHR_DF_CHANNEL_CIEXYY_X:
return "KHR_DF_CHANNEL_CIEXYY_X";
case KHR_DF_CHANNEL_CIEXYY_YCHROMA:
return "KHR_DF_CHANNEL_CIEXYY_YCHROMA";
case KHR_DF_CHANNEL_CIEXYY_YLUMA:
return "KHR_DF_CHANNEL_CIEXYY_YLUMA";
default:
return NULL;
}
case KHR_DF_MODEL_BC1A:
switch (value) {
case KHR_DF_CHANNEL_BC1A_COLOR:
return "KHR_DF_CHANNEL_BC1A_COLOR";
case KHR_DF_CHANNEL_BC1A_ALPHA:
return "KHR_DF_CHANNEL_BC1A_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_BC2:
switch (value) {
case KHR_DF_CHANNEL_BC2_COLOR:
return "KHR_DF_CHANNEL_BC2_COLOR";
case KHR_DF_CHANNEL_BC2_ALPHA:
return "KHR_DF_CHANNEL_BC2_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_BC3:
switch (value) {
case KHR_DF_CHANNEL_BC3_COLOR:
return "KHR_DF_CHANNEL_BC3_COLOR";
case KHR_DF_CHANNEL_BC3_ALPHA:
return "KHR_DF_CHANNEL_BC3_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_BC4:
switch (value) {
case KHR_DF_CHANNEL_BC4_DATA:
return "KHR_DF_CHANNEL_BC4_DATA";
default:
return NULL;
}
case KHR_DF_MODEL_BC5:
switch (value) {
case KHR_DF_CHANNEL_BC5_RED:
return "KHR_DF_CHANNEL_BC5_RED";
case KHR_DF_CHANNEL_BC5_GREEN:
return "KHR_DF_CHANNEL_BC5_GREEN";
default:
return NULL;
}
case KHR_DF_MODEL_BC6H:
switch (value) {
case KHR_DF_CHANNEL_BC6H_COLOR:
return "KHR_DF_CHANNEL_BC6H_COLOR";
default:
return NULL;
}
case KHR_DF_MODEL_BC7:
switch (value) {
case KHR_DF_CHANNEL_BC7_COLOR:
return "KHR_DF_CHANNEL_BC7_COLOR";
default:
return NULL;
}
case KHR_DF_MODEL_ETC1:
switch (value) {
case KHR_DF_CHANNEL_ETC1_COLOR:
return "KHR_DF_CHANNEL_ETC1_COLOR";
default:
return NULL;
}
case KHR_DF_MODEL_ETC2:
switch (value) {
case KHR_DF_CHANNEL_ETC2_RED:
return "KHR_DF_CHANNEL_ETC2_RED";
case KHR_DF_CHANNEL_ETC2_GREEN:
return "KHR_DF_CHANNEL_ETC2_GREEN";
case KHR_DF_CHANNEL_ETC2_COLOR:
return "KHR_DF_CHANNEL_ETC2_COLOR";
case KHR_DF_CHANNEL_ETC2_ALPHA:
return "KHR_DF_CHANNEL_ETC2_ALPHA";
default:
return NULL;
}
case KHR_DF_MODEL_ASTC:
switch (value) {
case KHR_DF_CHANNEL_ASTC_DATA:
return "KHR_DF_CHANNEL_ASTC_DATA";
default:
return NULL;
}
case KHR_DF_MODEL_ETC1S:
switch (value) {
case KHR_DF_CHANNEL_ETC1S_RGB:
return "KHR_DF_CHANNEL_ETC1S_RGB";
case KHR_DF_CHANNEL_ETC1S_RRR:
return "KHR_DF_CHANNEL_ETC1S_RRR";
case KHR_DF_CHANNEL_ETC1S_GGG:
return "KHR_DF_CHANNEL_ETC1S_GGG";
case KHR_DF_CHANNEL_ETC1S_AAA:
return "KHR_DF_CHANNEL_ETC1S_AAA";
default:
return NULL;
}
case KHR_DF_MODEL_PVRTC:
switch (value) {
case KHR_DF_CHANNEL_PVRTC_COLOR:
return "KHR_DF_CHANNEL_PVRTC_COLOR";
default:
return NULL;
}
case KHR_DF_MODEL_PVRTC2:
switch (value) {
case KHR_DF_CHANNEL_PVRTC2_COLOR:
return "KHR_DF_CHANNEL_PVRTC2_COLOR";
default:
return NULL;
}
case KHR_DF_MODEL_UASTC:
switch (value) {
case KHR_DF_CHANNEL_UASTC_RGB:
return "KHR_DF_CHANNEL_UASTC_RGB";
case KHR_DF_CHANNEL_UASTC_RGBA:
return "KHR_DF_CHANNEL_UASTC_RGBA";
case KHR_DF_CHANNEL_UASTC_RRR:
return "KHR_DF_CHANNEL_UASTC_RRR";
case KHR_DF_CHANNEL_UASTC_RRRG:
return "KHR_DF_CHANNEL_UASTC_RRRG";
case KHR_DF_CHANNEL_UASTC_RG:
return "KHR_DF_CHANNEL_UASTC_RG";
default:
return NULL;
}
default:
break;
}
switch (value) {
case KHR_DF_CHANNEL_UNSPECIFIED_0:
return "KHR_DF_CHANNEL_UNSPECIFIED_0";
case KHR_DF_CHANNEL_UNSPECIFIED_1:
return "KHR_DF_CHANNEL_UNSPECIFIED_1";
case KHR_DF_CHANNEL_UNSPECIFIED_2:
return "KHR_DF_CHANNEL_UNSPECIFIED_2";
case KHR_DF_CHANNEL_UNSPECIFIED_3:
return "KHR_DF_CHANNEL_UNSPECIFIED_3";
case KHR_DF_CHANNEL_UNSPECIFIED_4:
return "KHR_DF_CHANNEL_UNSPECIFIED_4";
case KHR_DF_CHANNEL_UNSPECIFIED_5:
return "KHR_DF_CHANNEL_UNSPECIFIED_5";
case KHR_DF_CHANNEL_UNSPECIFIED_6:
return "KHR_DF_CHANNEL_UNSPECIFIED_6";
case KHR_DF_CHANNEL_UNSPECIFIED_7:
return "KHR_DF_CHANNEL_UNSPECIFIED_7";
case KHR_DF_CHANNEL_UNSPECIFIED_8:
return "KHR_DF_CHANNEL_UNSPECIFIED_8";
case KHR_DF_CHANNEL_UNSPECIFIED_9:
return "KHR_DF_CHANNEL_UNSPECIFIED_9";
case KHR_DF_CHANNEL_UNSPECIFIED_10:
return "KHR_DF_CHANNEL_UNSPECIFIED_10";
case KHR_DF_CHANNEL_UNSPECIFIED_11:
return "KHR_DF_CHANNEL_UNSPECIFIED_11";
case KHR_DF_CHANNEL_UNSPECIFIED_12:
return "KHR_DF_CHANNEL_UNSPECIFIED_12";
case KHR_DF_CHANNEL_UNSPECIFIED_13:
return "KHR_DF_CHANNEL_UNSPECIFIED_13";
case KHR_DF_CHANNEL_UNSPECIFIED_14:
return "KHR_DF_CHANNEL_UNSPECIFIED_14";
case KHR_DF_CHANNEL_UNSPECIFIED_15:
return "KHR_DF_CHANNEL_UNSPECIFIED_15";
default:
break;
}
return NULL;
}
/**
* @internal
*/
static void printFlagBits(uint32_t flags, const char*(*toStringFn)(uint32_t, bool)) {
bool first = true;
for (uint32_t bit_index = 0; bit_index < 32; ++bit_index) {
uint32_t bit_mask = 1u << bit_index;
bool bit_value = (bit_mask & (uint32_t) flags) != 0;
const char* comma = first ? "" : ", ";
const char* str = toStringFn(bit_index, bit_value);
if (str) {
printf("%s%s", comma, str);
first = false;
} else if (bit_value) {
printf("%s%u", comma, bit_mask);
first = false;
}
}
}
/**
* @internal
*/
static void printFlagBitsJSON(uint32_t indent, const char* nl, uint32_t flags, const char*(*toStringFn)(uint32_t, bool)) {
bool first = true;
for (uint32_t bit_index = 0; bit_index < 32; ++bit_index) {
uint32_t bit_mask = 1u << bit_index;
bool bit_value = (bit_mask & (uint32_t) flags) != 0;
const char* str = toStringFn(bit_index, bit_value);
if (str) {
printf("%s%s%*s\"%s\"", first ? "" : ",", first ? "" : nl, indent, "", str);
first = false;
} else if (bit_value) {
printf("%s%s%*s%u", first ? "" : ",", first ? "" : nl, indent, "", bit_mask);
first = false;
}
}
if (!first)
printf("%s", nl);
}
/**
* @~English
* @brief Print a human-readable interpretation of a data format descriptor.
*
* @param DFD Pointer to a data format descriptor.
* @param dataSize The maximum size that can be considered as part of the DFD.
**/
void printDFD(uint32_t *DFD, uint32_t dataSize)
{
#define PRINT_ENUM(VALUE, TO_STRING_FN) { \
int value = VALUE; \
const char* str = TO_STRING_FN(value); \
if (str) \
printf("%s", str); \
else \
printf("%u", value); \
}
const uint32_t sizeof_dfdTotalSize = sizeof(uint32_t);
const uint32_t sizeof_DFDBHeader = sizeof(uint32_t) * 2;
const uint32_t sizeof_BDFD = sizeof(uint32_t) * KHR_DF_WORD_SAMPLESTART;
const uint32_t sizeof_BDFDSample = sizeof(uint32_t) * KHR_DF_WORD_SAMPLEWORDS;
uint32_t dfdTotalSize = dataSize >= sizeof_dfdTotalSize ? DFD[0] : 0;
uint32_t remainingSize = dfdTotalSize < dataSize ? dfdTotalSize : dataSize;
if (remainingSize < sizeof_dfdTotalSize)
return; // Invalid DFD: dfdTotalSize must be present
uint32_t* block = DFD + 1;
remainingSize -= sizeof_dfdTotalSize;
printf("DFD total bytes: %u\n", dfdTotalSize);
for (int i = 0; i < MAX_NUM_DFD_BLOCKS; ++i) { // At most only iterate MAX_NUM_DFD_BLOCKS block
if (remainingSize < sizeof_DFDBHeader)
break; // Invalid DFD: Missing or partial block header
const khr_df_vendorid_e vendorID = KHR_DFDVAL(block, VENDORID);
const khr_df_khr_descriptortype_e descriptorType = KHR_DFDVAL(block, DESCRIPTORTYPE);
const khr_df_versionnumber_e versionNumber = KHR_DFDVAL(block, VERSIONNUMBER);
const uint32_t blockSize = KHR_DFDVAL(block, DESCRIPTORBLOCKSIZE);
printf("Vendor ID: ");
PRINT_ENUM(vendorID, dfdToStringVendorID);
printf("\nDescriptor type: ");
PRINT_ENUM(descriptorType, dfdToStringDescriptorType);
printf("\nVersion: ");
PRINT_ENUM(versionNumber, dfdToStringVersionNumber);
printf("\nDescriptor block size: %u", blockSize);
printf("\n");
if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT) {
if (remainingSize < sizeof_BDFD)
break; // Invalid DFD: Missing or partial basic DFD block
const int model = KHR_DFDVAL(block, MODEL);
khr_df_flags_e flags = KHR_DFDVAL(block, FLAGS);
printf("Flags: 0x%X (", flags);
printFlagBits(flags, dfdToStringFlagsBit);
printf(")\nTransfer: ");
PRINT_ENUM(KHR_DFDVAL(block, TRANSFER), dfdToStringTransferFunction);
printf("\nPrimaries: ");
PRINT_ENUM(KHR_DFDVAL(block, PRIMARIES), dfdToStringColorPrimaries);
printf("\nModel: ");
PRINT_ENUM(model, dfdToStringColorModel);
printf("\n");
printf("Dimensions: %u, %u, %u, %u\n",
KHR_DFDVAL(block, TEXELBLOCKDIMENSION0) + 1,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION1) + 1,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION2) + 1,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION3) + 1);
printf("Plane bytes: %u, %u, %u, %u, %u, %u, %u, %u\n",
KHR_DFDVAL(block, BYTESPLANE0),
KHR_DFDVAL(block, BYTESPLANE1),
KHR_DFDVAL(block, BYTESPLANE2),
KHR_DFDVAL(block, BYTESPLANE3),
KHR_DFDVAL(block, BYTESPLANE4),
KHR_DFDVAL(block, BYTESPLANE5),
KHR_DFDVAL(block, BYTESPLANE6),
KHR_DFDVAL(block, BYTESPLANE7));
int samples = (blockSize - sizeof_BDFD) / sizeof_BDFDSample;
if (samples > MAX_NUM_BDFD_SAMPLES)
samples = MAX_NUM_BDFD_SAMPLES; // Too many BDFD samples
for (int sample = 0; sample < samples; ++sample) {
if (remainingSize < sizeof_BDFD + (sample + 1) * sizeof_BDFDSample)
break; // Invalid DFD: Missing or partial basic DFD sample
khr_df_model_channels_e channelType = KHR_DFDSVAL(block, sample, CHANNELID);
printf("Sample %u:\n", sample);
khr_df_sample_datatype_qualifiers_e qualifiers = KHR_DFDSVAL(block, sample, QUALIFIERS);
printf(" Qualifiers: 0x%X (", qualifiers);
printFlagBits(qualifiers, dfdToStringSampleDatatypeQualifiers);
printf(")\n");
printf(" Channel Type: 0x%X", channelType);
{
const char* str = dfdToStringChannelId(model, channelType);
if (str)
printf(" (%s)\n", str);
else
printf(" (%u)\n", channelType);
}
printf(" Length: %u bits Offset: %u\n",
KHR_DFDSVAL(block, sample, BITLENGTH) + 1,
KHR_DFDSVAL(block, sample, BITOFFSET));
printf(" Position: %u, %u, %u, %u\n",
KHR_DFDSVAL(block, sample, SAMPLEPOSITION0),
KHR_DFDSVAL(block, sample, SAMPLEPOSITION1),
KHR_DFDSVAL(block, sample, SAMPLEPOSITION2),
KHR_DFDSVAL(block, sample, SAMPLEPOSITION3));
printf(" Lower: 0x%08x\n Upper: 0x%08x\n",
KHR_DFDSVAL(block, sample, SAMPLELOWER),
KHR_DFDSVAL(block, sample, SAMPLEUPPER));
}
} else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS) {
// TODO: Implement DFD print for ADDITIONAL_DIMENSIONS
} else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES) {
// TODO: Implement DFD print for ADDITIONAL_PLANES
} else {
printf("Unknown block\n");
}
const uint32_t advance = sizeof_DFDBHeader > blockSize ? sizeof_DFDBHeader : blockSize;
if (advance > remainingSize)
break;
remainingSize -= advance;
block += advance / 4;
}
#undef PRINT_ENUM
}
/**
* @~English
* @brief Print a JSON interpretation of a data format descriptor.
*
* @param DFD Pointer to a data format descriptor.
* @param dataSize The maximum size that can be considered as part of the DFD.
* @param base_indent The number of indentations to include at the front of every line
* @param indent_width The number of spaces to add with each nested scope
* @param minified Specifies whether the JSON output should be minified
**/
void printDFDJSON(uint32_t* DFD, uint32_t dataSize, uint32_t base_indent, uint32_t indent_width, bool minified)
{
if (minified) {
base_indent = 0;
indent_width = 0;
}
const char* space = minified ? "" : " ";
const char* nl = minified ? "" : "\n";
#define LENGTH_OF_INDENT(INDENT) ((base_indent + INDENT) * indent_width)
/** Prints an enum as string or number */
#define PRINT_ENUM(INDENT, NAME, VALUE, TO_STRING_FN, COMMA) { \
int value = VALUE; \
printf("%*s\"" NAME "\":%s", LENGTH_OF_INDENT(INDENT), "", space); \
const char* str = TO_STRING_FN(value); \
if (str) \
printf("\"%s\"", str); \
else \
printf("%u", value); \
printf(COMMA "%s", nl); \
}
/** Prints an enum as string or number if the to string function fails with a trailing comma*/
#define PRINT_ENUM_C(INDENT, NAME, VALUE, TO_STRING_FN) \
PRINT_ENUM(INDENT, NAME, VALUE, TO_STRING_FN, ",")
/** Prints an enum as string or number if the to string function fails without a trailing comma*/
#define PRINT_ENUM_E(INDENT, NAME, VALUE, TO_STRING_FN) \
PRINT_ENUM(INDENT, NAME, VALUE, TO_STRING_FN, "")
#define PRINT_INDENT(INDENT, FMT, ...) { \
printf("%*s" FMT, LENGTH_OF_INDENT(INDENT), "", __VA_ARGS__); \
}
#define PRINT_INDENT_NOARG(INDENT, FMT) { \
printf("%*s" FMT, LENGTH_OF_INDENT(INDENT), ""); \
}
const uint32_t sizeof_dfdTotalSize = sizeof(uint32_t);
const uint32_t sizeof_DFDBHeader = sizeof(uint32_t) * 2;
const uint32_t sizeof_BDFD = sizeof(uint32_t) * KHR_DF_WORD_SAMPLESTART;
const uint32_t sizeof_BDFDSample = sizeof(uint32_t) * KHR_DF_WORD_SAMPLEWORDS;
uint32_t dfdTotalSize = dataSize >= sizeof_dfdTotalSize ? DFD[0] : 0;
PRINT_INDENT(0, "\"totalSize\":%s%u,%s", space, dfdTotalSize, nl)
uint32_t remainingSize = dfdTotalSize < dataSize ? dfdTotalSize : dataSize;
if (remainingSize < sizeof_dfdTotalSize) {
PRINT_INDENT(0, "\"blocks\":%s[]%s", space, nl) // Print empty blocks to confirm to the json scheme
return; // Invalid DFD: dfdTotalSize must be present
}
uint32_t* block = DFD + 1;
remainingSize -= sizeof_dfdTotalSize;
PRINT_INDENT(0, "\"blocks\":%s[", space)
for (int i = 0; i < MAX_NUM_DFD_BLOCKS; ++i) { // At most only iterate MAX_NUM_DFD_BLOCKS block
if (remainingSize < sizeof_DFDBHeader)
break; // Invalid DFD: Missing or partial block header
const khr_df_vendorid_e vendorID = KHR_DFDVAL(block, VENDORID);
const khr_df_khr_descriptortype_e descriptorType = KHR_DFDVAL(block, DESCRIPTORTYPE);
const khr_df_versionnumber_e versionNumber = KHR_DFDVAL(block, VERSIONNUMBER);
const uint32_t blockSize = KHR_DFDVAL(block, DESCRIPTORBLOCKSIZE);
const int model = KHR_DFDVAL(block, MODEL);
if (i == 0) {
printf("%s", nl);
} else {
printf(",%s", nl);
}
PRINT_INDENT(1, "{%s", nl)
PRINT_ENUM_C(2, "vendorId", vendorID, dfdToStringVendorID);
PRINT_ENUM_C(2, "descriptorType", descriptorType, dfdToStringDescriptorType);
PRINT_ENUM_C(2, "versionNumber", versionNumber, dfdToStringVersionNumber);
PRINT_INDENT(2, "\"descriptorBlockSize\":%s%u", space, blockSize)
if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT) {
if (remainingSize < sizeof_BDFD) {
// Invalid DFD: Missing or partial basic DFD block
printf("%s", nl);
PRINT_INDENT(1, "}%s", nl) // End of block
break;
}
printf(",%s", nl);
PRINT_INDENT(2, "\"flags\":%s[%s", space, nl)
khr_df_flags_e flags = KHR_DFDVAL(block, FLAGS);
printFlagBitsJSON(LENGTH_OF_INDENT(3), nl, flags, dfdToStringFlagsBit);
PRINT_INDENT(2, "],%s", nl)
PRINT_ENUM_C(2, "transferFunction", KHR_DFDVAL(block, TRANSFER), dfdToStringTransferFunction);
PRINT_ENUM_C(2, "colorPrimaries", KHR_DFDVAL(block, PRIMARIES), dfdToStringColorPrimaries);
PRINT_ENUM_C(2, "colorModel", model, dfdToStringColorModel);
PRINT_INDENT(2, "\"texelBlockDimension\":%s[%u,%s%u,%s%u,%s%u],%s", space,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION0) + 1, space,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION1) + 1, space,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION2) + 1, space,
KHR_DFDVAL(block, TEXELBLOCKDIMENSION3) + 1, nl)
PRINT_INDENT(2, "\"bytesPlane\":%s[%u,%s%u,%s%u,%s%u,%s%u,%s%u,%s%u,%s%u],%s", space,
KHR_DFDVAL(block, BYTESPLANE0), space,
KHR_DFDVAL(block, BYTESPLANE1), space,
KHR_DFDVAL(block, BYTESPLANE2), space,
KHR_DFDVAL(block, BYTESPLANE3), space,
KHR_DFDVAL(block, BYTESPLANE4), space,
KHR_DFDVAL(block, BYTESPLANE5), space,
KHR_DFDVAL(block, BYTESPLANE6), space,
KHR_DFDVAL(block, BYTESPLANE7), nl)
PRINT_INDENT(2, "\"samples\":%s[%s", space, nl)
int samples = (blockSize - sizeof_BDFD) / sizeof_BDFDSample;
if (samples > MAX_NUM_BDFD_SAMPLES)
samples = MAX_NUM_BDFD_SAMPLES;
for (int sample = 0; sample < samples; ++sample) {
if (remainingSize < sizeof_BDFD + (sample + 1) * sizeof_BDFDSample)
break; // Invalid DFD: Missing or partial basic DFD sample
if (sample != 0)
printf(",%s", nl);
PRINT_INDENT(3, "{%s", nl)
khr_df_sample_datatype_qualifiers_e qualifiers = KHR_DFDSVAL(block, sample, QUALIFIERS);
if (qualifiers == 0) {
PRINT_INDENT(4, "\"qualifiers\":%s[],%s", space, nl)
} else {
PRINT_INDENT(4, "\"qualifiers\":%s[%s", space, nl)
printFlagBitsJSON(LENGTH_OF_INDENT(5), nl, qualifiers, dfdToStringSampleDatatypeQualifiers);
PRINT_INDENT(4, "],%s", nl)
}
khr_df_model_channels_e channelType = KHR_DFDSVAL(block, sample, CHANNELID);
const char* channelStr = dfdToStringChannelId(model, channelType);
if (channelStr)
PRINT_INDENT(4, "\"channelType\":%s\"%s\",%s", space, channelStr, nl)
else
PRINT_INDENT(4, "\"channelType\":%s%u,%s", space, channelType, nl)
PRINT_INDENT(4, "\"bitLength\":%s%u,%s", space, KHR_DFDSVAL(block, sample, BITLENGTH), nl)
PRINT_INDENT(4, "\"bitOffset\":%s%u,%s", space, KHR_DFDSVAL(block, sample, BITOFFSET), nl)
PRINT_INDENT(4, "\"samplePosition\":%s[%u,%s%u,%s%u,%s%u],%s", space,
KHR_DFDSVAL(block, sample, SAMPLEPOSITION0), space,
KHR_DFDSVAL(block, sample, SAMPLEPOSITION1), space,
KHR_DFDSVAL(block, sample, SAMPLEPOSITION2), space,
KHR_DFDSVAL(block, sample, SAMPLEPOSITION3), nl)
if (qualifiers & KHR_DF_SAMPLE_DATATYPE_SIGNED) {
PRINT_INDENT(4, "\"sampleLower\":%s%d,%s", space, KHR_DFDSVAL(block, sample, SAMPLELOWER), nl)
PRINT_INDENT(4, "\"sampleUpper\":%s%d%s", space, KHR_DFDSVAL(block, sample, SAMPLEUPPER), nl)
} else {
PRINT_INDENT(4, "\"sampleLower\":%s%u,%s", space, (unsigned int) KHR_DFDSVAL(block, sample, SAMPLELOWER), nl)
PRINT_INDENT(4, "\"sampleUpper\":%s%u%s", space, (unsigned int) KHR_DFDSVAL(block, sample, SAMPLEUPPER), nl)
}
PRINT_INDENT_NOARG(3, "}")
}
printf("%s", nl);
PRINT_INDENT(2, "]%s", nl) // End of samples
} else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS) {
printf("%s", nl);
// printf(",%s", nl); // If there is extra member printed
// TODO: Implement DFD print for ADDITIONAL_DIMENSIONS
} else if (vendorID == KHR_DF_VENDORID_KHRONOS && descriptorType == KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES) {
printf("%s", nl);
// printf(",%s", nl); // If there is extra member printed
// TODO: Implement DFD print for ADDITIONAL_PLANES
} else {
printf("%s", nl);
// printf(",%s", nl); // If there is extra member printed
// TODO: What to do with unknown blocks for json?
// Unknown block data in binary?
}
PRINT_INDENT_NOARG(1, "}") // End of block
const uint32_t advance = sizeof_DFDBHeader > blockSize ? sizeof_DFDBHeader : blockSize;
if (advance > remainingSize)
break;
remainingSize -= advance;
block += advance / 4;
}
printf("%s", nl);
PRINT_INDENT(0, "]%s", nl) // End of blocks
#undef PRINT_ENUM
#undef PRINT_ENUM_C
#undef PRINT_ENUM_E
#undef PRINT_INDENT
#undef PRINT_INDENT_NOARG
}