1/* -*- tab-width: 4; -*- */
2/* vi: set sw=2 ts=4 expandtab: */
3
4/* Copyright 2019-2020 The Khronos Group Inc.
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8/**
9 * @file
10 * @~English
11 * @brief Utilities for querying info from a data format descriptor.
12 * @author Mark Callow
13 */
14
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <KHR/khr_df.h>
20#include "dfd.h"
21
22/**
23 * @~English
24 * @brief Get the number and size of the image components from a DFD.
25 *
26 * This simplified function is for use only with the DFDs for unpacked
27 * formats which means all components have the same size.
28 *
29 * @param DFD Pointer to a Data Format Descriptor to interpret,
30 described as 32-bit words in native endianness.
31 Note that this is the whole descriptor, not just
32 the basic descriptor block.
33 * @param numComponents pointer to a 32-bit word in which the number of
34 components will be written.
35 * @param componentByteLength pointer to a 32-bit word in which the size of
36 a component in bytes will be written.
37 */
38void
39getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
40 uint32_t* componentByteLength)
41{
42 const uint32_t *BDFDB = DFD+1;
43 uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
44 uint32_t sampleCounter;
45 uint32_t currentChannel = ~0U; /* Don't start matched. */
46
47 /* This is specifically for unpacked formats which means the size of */
48 /* each component is the same. */
49 *numComponents = 0;
50 for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
51 uint32_t sampleByteLength = (KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1) >> 3U;
52 uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
53
54 if (sampleChannel == currentChannel) {
55 /* Continuation of the same channel. */
56 /* Accumulate the byte length. */
57 *componentByteLength += sampleByteLength;
58 } else {
59 /* Everything is new. Hopefully. */
60 currentChannel = sampleChannel;
61 (*numComponents)++;
62 *componentByteLength = sampleByteLength;
63 }
64 }
65}
66
67/**
68 * @~English
69 * @brief Return the number of "components" in the data.
70 *
71 * Calculates the number of uniques samples in the DFD by combining
72 * multiple samples for the same channel. For uncompressed colorModels
73 * this is the same as the number of components in the image data. For
74 * block-compressed color models this is the number of samples in
75 * the color model, typically 1 and in a few cases 2.
76 *
77 * @param DFD Pointer to a Data Format Descriptor for which,
78 * described as 32-bit words in native endianness.
79 * Note that this is the whole descriptor, not just
80 * the basic descriptor block.
81 */
82uint32_t getDFDNumComponents(const uint32_t* DFD)
83{
84 const uint32_t *BDFDB = DFD+1;
85 uint32_t currentChannel = ~0U; /* Don't start matched. */
86 uint32_t numComponents = 0;
87 uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
88 uint32_t sampleCounter;
89
90 for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
91 uint32_t sampleChannel = KHR_DFDSVAL(BDFDB, sampleCounter, CHANNELID);
92 if (sampleChannel != currentChannel) {
93 numComponents++;
94 currentChannel = sampleChannel;
95 }
96 }
97 return numComponents;
98}
99
100/**
101 * @~English
102 * @brief Recreate the value of bytesPlane0 from sample info.
103 *
104 * This can be use to recreate the value of bytesPlane0 for data that
105 * has been variable-rate compressed so has bytesPlane0 = 0. For DFDs
106 * that are valid for KTX files. Little-endian data only and no multi-plane
107 * formats.
108 *
109 * @param DFD Pointer to a Data Format Descriptor for which,
110 * described as 32-bit words in native endianness.
111 * Note that this is the whole descriptor, not just
112 * the basic descriptor block.
113 * @param bytesPlane0 pointer to a 32-bit word in which the recreated
114 * value of bytesPlane0 will be written.
115 */
116void
117recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0)
118{
119 const uint32_t *BDFDB = DFD+1;
120 uint32_t numSamples = KHR_DFDSAMPLECOUNT(BDFDB);
121 uint32_t sampleCounter;
122
123 uint32_t bitsPlane0 = 0;
124 uint32_t* bitOffsets = malloc(sizeof(uint32_t) * numSamples);
125 memset(bitOffsets, -1, sizeof(uint32_t) * numSamples);
126 for (sampleCounter = 0; sampleCounter < numSamples; ++sampleCounter) {
127 uint32_t sampleBitOffset = KHR_DFDSVAL(BDFDB, sampleCounter, BITOFFSET);
128 /* The sample bitLength field stores the bit length - 1. */
129 uint32_t sampleBitLength = KHR_DFDSVAL(BDFDB, sampleCounter, BITLENGTH) + 1;
130 uint32_t i;
131 for (i = 0; i < numSamples; i++) {
132 if (sampleBitOffset == bitOffsets[i]) {
133 // This sample is being repeated as in e.g. RGB9E5.
134 break;
135 }
136 }
137 if (i == numSamples) {
138 // Previously unseen bitOffset. Bump size.
139 bitsPlane0 += sampleBitLength;
140 bitOffsets[sampleCounter] = sampleBitOffset;
141 }
142 }
143 free(bitOffsets);
144 *bytesPlane0 = bitsPlane0 >> 3U;
145}
146
147