180 lines
6.3 KiB
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);
|
|
}
|