godot/thirdparty/libktx/lib/dfdutils/queries.c

180 lines
6.3 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 querying info from a data format descriptor.
* @author Mark Callow
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <KHR/khr_df.h>
#include "dfd.h"
/**
* @~English
* @brief Get the number and size of the image components from a DFD.
*
* This simplified function is for use only with the DFDs for unpacked
* formats which means all components have the same size.
*
* @param DFD Pointer to a Data Format Descriptor to interpret,
described as 32-bit words in native endianness.
Note that this is the whole descriptor, not just
the basic descriptor block.
* @param numComponents pointer to a 32-bit word in which the number of
components will be written.
* @param componentByteLength pointer to a 32-bit word in which the size of
a component in bytes will be written.
*/
void
getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
uint32_t* componentByteLength)
{
const uint32_t *BDFDB = DFD+1;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleNumber;
uint32_t currentChannel = ~0U; /* Don't start matched. */
/* This is specifically for unpacked formats which means the size of */
/* each component is the same. */
*numComponents = 0;
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleNumber, BITLENGTH) + 1) >> 3U;
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID);
if (sampleChannel == currentChannel) {
/* Continuation of the same channel. */
/* Accumulate the byte length. */
*componentByteLength += sampleByteLength;
} else {
/* Everything is new. Hopefully. */
currentChannel = sampleChannel;
(*numComponents)++;
*componentByteLength = sampleByteLength;
}
}
}
/**
* @~English
* @brief Return the number of "components" in the data.
*
* Calculates the number of uniques samples in the DFD by combining
* multiple samples for the same channel. For uncompressed colorModels
* this is the same as the number of components in the image data. For
* block-compressed color models this is the number of samples in
* the color model, typically 1 and in a few cases 2.
*
* @param DFD Pointer to a Data Format Descriptor for which,
* described as 32-bit words in native endianness.
* Note that this is the whole descriptor, not just
* the basic descriptor block.
*/
uint32_t getDFDNumComponents(const uint32_t* DFD)
{
const uint32_t *BDFDB = DFD+1;
uint32_t currentChannel = ~0U; /* Don't start matched. */
uint32_t numComponents = 0;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleNumber;
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleNumber, CHANNELID);
if (sampleChannel != currentChannel) {
numComponents++;
currentChannel = sampleChannel;
}
}
return numComponents;
}
/**
* @~English
* @brief Reconstruct the value of bytesPlane0 from sample info.
*
* Reconstruct the value for data that has been variable-rate compressed so
* has bytesPlane0 = 0. For DFDs that are valid for KTX files. Little-endian
* data only and no multi-plane formats.
*
* @param DFD Pointer to a Data Format Descriptor for which,
* described as 32-bit words in native endianness.
* Note that this is the whole descriptor, not just
* the basic descriptor block.
*/
uint32_t
reconstructDFDBytesPlane0FromSamples(const uint32_t* DFD)
{
const uint32_t *BDFDB = DFD+1;
uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
uint32_t sampleNumber;
uint32_t bitsPlane0 = 0;
int32_t largestOffset = 0;
uint32_t sampleNumberWithLargestOffset = 0;
// Special case these depth{,-stencil} formats. The unused bits are
// in the MSBs so have no visibility in the DFD therefore the max offset
// algorithm below returns a value that is too small.
if (KHR_DFDSVAL(BDFDB, 0, CHANNELID) == KHR_DF_CHANNEL_COMMON_DEPTH) {
if (numSamples == 1) {
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 24) {
// X8_D24_UNORM_PACK32,
return 4;
}
} else if (numSamples == 2) {
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 16) {
// D16_UNORM_S8_UINT
return 4;
}
if (KHR_DFDSVAL(BDFDB, 0, BITLENGTH) + 1 == 32
&& KHR_DFDSVAL(BDFDB, 1, CHANNELID) == KHR_DF_CHANNEL_COMMON_STENCIL) {
// D32_SFLOAT_S8_UINT
return 8;
}
}
}
for (sampleNumber = 0; sampleNumber < numSamples; ++sampleNumber) {
int32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleNumber, BITOFFSET);
if (sampleBitOffset > largestOffset) {
largestOffset = sampleBitOffset;
sampleNumberWithLargestOffset = sampleNumber;
}
}
/* The sample bitLength field stores the bit length - 1. */
uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleNumberWithLargestOffset, BITLENGTH) + 1;
bitsPlane0 = largestOffset + sampleBitLength;
return bitsPlane0 >> 3U;
}
/**
* @~English
* @brief Reconstruct the value of bytesPlane0 from sample info.
*
* @see reconstructDFDBytesPlane0FromSamples for details.
* @deprecated For backward comparibility only. Use
* reconstructDFDBytesPlane0FromSamples.
*
* @param DFD Pointer to a Data Format Descriptor for which,
* described as 32-bit words in native endianness.
* Note that this is the whole descriptor, not just
* the basic descriptor block.
* @param bytesPlane0 pointer to a 32-bit word in which the recreated
* value of bytesPlane0 will be written.
*/
void
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0)
{
*bytesPlane0 = reconstructDFDBytesPlane0FromSamples(DFD);
}