2 * Copyright (C) 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * \file texcompress_bptc.c
26 * GL_ARB_texture_compression_bptc support.
30 #include "texcompress.h"
31 #include "texcompress_bptc.h"
32 #include "util/format_srgb.h"
38 #define N_PARTITIONS 64
39 #define BLOCK_BYTES 16
41 struct bptc_unorm_mode
{
44 bool has_rotation_bits
;
45 bool has_index_selection_bit
;
48 bool has_endpoint_pbits
;
49 bool has_shared_pbits
;
51 int n_secondary_index_bits
;
54 struct bptc_float_bitfield
{
62 struct bptc_float_mode
{
64 bool transformed_endpoints
;
69 struct bptc_float_bitfield bitfields
[24];
78 static const struct bptc_unorm_mode
79 bptc_unorm_modes
[] = {
80 /* 0 */ { 3, 4, false, false, 4, 0, true, false, 3, 0 },
81 /* 1 */ { 2, 6, false, false, 6, 0, false, true, 3, 0 },
82 /* 2 */ { 3, 6, false, false, 5, 0, false, false, 2, 0 },
83 /* 3 */ { 2, 6, false, false, 7, 0, true, false, 2, 0 },
84 /* 4 */ { 1, 0, true, true, 5, 6, false, false, 2, 3 },
85 /* 5 */ { 1, 0, true, false, 7, 8, false, false, 2, 2 },
86 /* 6 */ { 1, 0, false, false, 7, 7, true, false, 4, 0 },
87 /* 7 */ { 2, 6, false, false, 5, 5, true, false, 2, 0 }
90 static const struct bptc_float_mode
91 bptc_float_modes
[] = {
93 { false, true, 5, 10, 3, { 5, 5, 5 },
94 { { 2, 1, 4, 1, false }, { 2, 2, 4, 1, false }, { 3, 2, 4, 1, false },
95 { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
96 { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
97 { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
98 { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
99 { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
100 { 3, 2, 3, 1, false },
104 { false, true, 5, 7, 3, { 6, 6, 6 },
105 { { 2, 1, 5, 1, false }, { 3, 1, 4, 1, false }, { 3, 1, 5, 1, false },
106 { 0, 0, 0, 7, false }, { 3, 2, 0, 1, false }, { 3, 2, 1, 1, false },
107 { 2, 2, 4, 1, false }, { 0, 1, 0, 7, false }, { 2, 2, 5, 1, false },
108 { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, { 0, 2, 0, 7, false },
109 { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
110 { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
111 { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
112 { 2, 0, 0, 6, false },
113 { 3, 0, 0, 6, false },
117 { false, true, 5, 11, 3, { 5, 4, 4 },
118 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
119 { 1, 0, 0, 5, false }, { 0, 0, 10, 1, false }, { 2, 1, 0, 4, false },
120 { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, { 3, 2, 0, 1, false },
121 { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
122 { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
123 { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
127 { false, false, 0, 10, 4, { 10, 10, 10 },
128 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
129 { 1, 0, 0, 10, false }, { 1, 1, 0, 10, false }, { 1, 2, 0, 10, false },
133 { false, true, 5, 11, 3, { 4, 5, 4 },
134 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
135 { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 3, 1, 4, 1, false },
136 { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, { 0, 1, 10, 1, false },
137 { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
138 { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
139 { 3, 2, 0, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
140 { 2, 1, 4, 1, false }, { 3, 2, 3, 1, false },
144 { false, true, 0, 11, 4, { 9, 9, 9 },
145 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
146 { 1, 0, 0, 9, false }, { 0, 0, 10, 1, false }, { 1, 1, 0, 9, false },
147 { 0, 1, 10, 1, false }, { 1, 2, 0, 9, false }, { 0, 2, 10, 1, false },
151 { false, true, 5, 11, 3, { 4, 4, 5 },
152 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
153 { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 2, 2, 4, 1, false },
154 { 2, 1, 0, 4, false }, { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false },
155 { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
156 { 0, 2, 10, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
157 { 3, 2, 1, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
158 { 3, 2, 4, 1, false }, { 3, 2, 3, 1, false },
162 { false, true, 0, 12, 4, { 8, 8, 8 },
163 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
164 { 1, 0, 0, 8, false }, { 0, 0, 10, 2, true }, { 1, 1, 0, 8, false },
165 { 0, 1, 10, 2, true }, { 1, 2, 0, 8, false }, { 0, 2, 10, 2, true },
169 { false, true, 5, 9, 3, { 5, 5, 5 },
170 { { 0, 0, 0, 9, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 9, false },
171 { 2, 1, 4, 1, false }, { 0, 2, 0, 9, false }, { 3, 2, 4, 1, false },
172 { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
173 { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
174 { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
175 { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
176 { 3, 2, 3, 1, false },
180 { false, true, 0, 16, 4, { 4, 4, 4 },
181 { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
182 { 1, 0, 0, 4, false }, { 0, 0, 10, 6, true }, { 1, 1, 0, 4, false },
183 { 0, 1, 10, 6, true }, { 1, 2, 0, 4, false }, { 0, 2, 10, 6, true },
187 { false, true, 5, 8, 3, { 6, 5, 5 },
188 { { 0, 0, 0, 8, false }, { 3, 1, 4, 1, false }, { 2, 2, 4, 1, false },
189 { 0, 1, 0, 8, false }, { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false },
190 { 0, 2, 0, 8, false }, { 3, 2, 3, 1, false }, { 3, 2, 4, 1, false },
191 { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false },
192 { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
193 { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 6, false },
194 { 3, 0, 0, 6, false },
198 { true /* reserved */ },
200 { false, true, 5, 8, 3, { 5, 6, 5 },
201 { { 0, 0, 0, 8, false }, { 3, 2, 0, 1, false }, { 2, 2, 4, 1, false },
202 { 0, 1, 0, 8, false }, { 2, 1, 5, 1, false }, { 2, 1, 4, 1, false },
203 { 0, 2, 0, 8, false }, { 3, 1, 5, 1, false }, { 3, 2, 4, 1, false },
204 { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
205 { 1, 1, 0, 6, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
206 { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
207 { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
211 { true /* reserved */ },
213 { false, true, 5, 8, 3, { 5, 5, 6 },
214 { { 0, 0, 0, 8, false }, { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false },
215 { 0, 1, 0, 8, false }, { 2, 2, 5, 1, false }, { 2, 1, 4, 1, false },
216 { 0, 2, 0, 8, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
217 { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
218 { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
219 { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
220 { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
224 { true /* reserved */ },
226 { false, false, 5, 6, 3, { 6, 6, 6 },
227 { { 0, 0, 0, 6, false }, { 3, 1, 4, 1, false }, { 3, 2, 0, 1, false },
228 { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 6, false },
229 { 2, 1, 5, 1, false }, { 2, 2, 5, 1, false }, { 3, 2, 2, 1, false },
230 { 2, 1, 4, 1, false }, { 0, 2, 0, 6, false }, { 3, 1, 5, 1, false },
231 { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
232 { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
233 { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
234 { 2, 0, 0, 6, false }, { 3, 0, 0, 6, false },
238 { true /* reserved */ },
241 /* This partition table is used when the mode has two subsets. Each
242 * partition is represented by a 32-bit value which gives 2 bits per texel
243 * within the block. The value of the two bits represents which subset to use
246 static const uint32_t
247 partition_table1
[N_PARTITIONS
] = {
248 0x50505050U
, 0x40404040U
, 0x54545454U
, 0x54505040U
,
249 0x50404000U
, 0x55545450U
, 0x55545040U
, 0x54504000U
,
250 0x50400000U
, 0x55555450U
, 0x55544000U
, 0x54400000U
,
251 0x55555440U
, 0x55550000U
, 0x55555500U
, 0x55000000U
,
252 0x55150100U
, 0x00004054U
, 0x15010000U
, 0x00405054U
,
253 0x00004050U
, 0x15050100U
, 0x05010000U
, 0x40505054U
,
254 0x00404050U
, 0x05010100U
, 0x14141414U
, 0x05141450U
,
255 0x01155440U
, 0x00555500U
, 0x15014054U
, 0x05414150U
,
256 0x44444444U
, 0x55005500U
, 0x11441144U
, 0x05055050U
,
257 0x05500550U
, 0x11114444U
, 0x41144114U
, 0x44111144U
,
258 0x15055054U
, 0x01055040U
, 0x05041050U
, 0x05455150U
,
259 0x14414114U
, 0x50050550U
, 0x41411414U
, 0x00141400U
,
260 0x00041504U
, 0x00105410U
, 0x10541000U
, 0x04150400U
,
261 0x50410514U
, 0x41051450U
, 0x05415014U
, 0x14054150U
,
262 0x41050514U
, 0x41505014U
, 0x40011554U
, 0x54150140U
,
263 0x50505500U
, 0x00555050U
, 0x15151010U
, 0x54540404U
,
266 /* This partition table is used when the mode has three subsets. In this case
267 * the values can be 0, 1 or 2.
269 static const uint32_t
270 partition_table2
[N_PARTITIONS
] = {
271 0xaa685050U
, 0x6a5a5040U
, 0x5a5a4200U
, 0x5450a0a8U
,
272 0xa5a50000U
, 0xa0a05050U
, 0x5555a0a0U
, 0x5a5a5050U
,
273 0xaa550000U
, 0xaa555500U
, 0xaaaa5500U
, 0x90909090U
,
274 0x94949494U
, 0xa4a4a4a4U
, 0xa9a59450U
, 0x2a0a4250U
,
275 0xa5945040U
, 0x0a425054U
, 0xa5a5a500U
, 0x55a0a0a0U
,
276 0xa8a85454U
, 0x6a6a4040U
, 0xa4a45000U
, 0x1a1a0500U
,
277 0x0050a4a4U
, 0xaaa59090U
, 0x14696914U
, 0x69691400U
,
278 0xa08585a0U
, 0xaa821414U
, 0x50a4a450U
, 0x6a5a0200U
,
279 0xa9a58000U
, 0x5090a0a8U
, 0xa8a09050U
, 0x24242424U
,
280 0x00aa5500U
, 0x24924924U
, 0x24499224U
, 0x50a50a50U
,
281 0x500aa550U
, 0xaaaa4444U
, 0x66660000U
, 0xa5a0a5a0U
,
282 0x50a050a0U
, 0x69286928U
, 0x44aaaa44U
, 0x66666600U
,
283 0xaa444444U
, 0x54a854a8U
, 0x95809580U
, 0x96969600U
,
284 0xa85454a8U
, 0x80959580U
, 0xaa141414U
, 0x96960000U
,
285 0xaaaa1414U
, 0xa05050a0U
, 0xa0a5a5a0U
, 0x96000000U
,
286 0x40804080U
, 0xa9a8a9a8U
, 0xaaaaaa44U
, 0x2a4a5254U
290 anchor_indices
[][N_PARTITIONS
] = {
291 /* Anchor index values for the second subset of two-subset partitioning */
293 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
294 0xf,0x2,0x8,0x2,0x2,0x8,0x8,0xf,0x2,0x8,0x2,0x2,0x8,0x8,0x2,0x2,
295 0xf,0xf,0x6,0x8,0x2,0x8,0xf,0xf,0x2,0x8,0x2,0x2,0x2,0xf,0xf,0x6,
296 0x6,0x2,0x6,0x8,0xf,0xf,0x2,0x2,0xf,0xf,0xf,0xf,0xf,0x2,0x2,0xf
299 /* Anchor index values for the second subset of three-subset partitioning */
301 0x3,0x3,0xf,0xf,0x8,0x3,0xf,0xf,0x8,0x8,0x6,0x6,0x6,0x5,0x3,0x3,
302 0x3,0x3,0x8,0xf,0x3,0x3,0x6,0xa,0x5,0x8,0x8,0x6,0x8,0x5,0xf,0xf,
303 0x8,0xf,0x3,0x5,0x6,0xa,0x8,0xf,0xf,0x3,0xf,0x5,0xf,0xf,0xf,0xf,
304 0x3,0xf,0x5,0x5,0x5,0x8,0x5,0xa,0x5,0xa,0x8,0xd,0xf,0xc,0x3,0x3
307 /* Anchor index values for the third subset of three-subset
311 0xf,0x8,0x8,0x3,0xf,0xf,0x3,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,
312 0xf,0x8,0xf,0x3,0xf,0x8,0xf,0x8,0x3,0xf,0x6,0xa,0xf,0xf,0xa,0x8,
313 0xf,0x3,0xf,0xa,0xa,0x8,0x9,0xa,0x6,0xf,0x8,0xf,0x3,0x6,0x6,0x8,
314 0xf,0x3,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3,0xf,0xf,0x8
319 extract_bits(const uint8_t *block
,
323 int byte_index
= offset
/ 8;
324 int bit_index
= offset
% 8;
325 int n_bits_in_byte
= MIN2(n_bits
, 8 - bit_index
);
330 result
|= ((block
[byte_index
] >> bit_index
) &
331 ((1 << n_bits_in_byte
) - 1)) << bit
;
333 n_bits
-= n_bits_in_byte
;
338 bit
+= n_bits_in_byte
;
341 n_bits_in_byte
= MIN2(n_bits
, 8);
346 expand_component(uint8_t byte
,
349 /* Expands a n-bit quantity into a byte by copying the most-significant
350 * bits into the unused least-significant bits.
352 return byte
<< (8 - n_bits
) | (byte
>> (2 * n_bits
- 8));
356 extract_unorm_endpoints(const struct bptc_unorm_mode
*mode
,
357 const uint8_t *block
,
359 uint8_t endpoints
[][4])
367 /* Extract each color component */
368 for (component
= 0; component
< 3; component
++) {
369 for (subset
= 0; subset
< mode
->n_subsets
; subset
++) {
370 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
371 endpoints
[subset
* 2 + endpoint
][component
] =
372 extract_bits(block
, bit_offset
, mode
->n_color_bits
);
373 bit_offset
+= mode
->n_color_bits
;
378 /* Extract the alpha values */
379 if (mode
->n_alpha_bits
> 0) {
380 for (subset
= 0; subset
< mode
->n_subsets
; subset
++) {
381 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
382 endpoints
[subset
* 2 + endpoint
][3] =
383 extract_bits(block
, bit_offset
, mode
->n_alpha_bits
);
384 bit_offset
+= mode
->n_alpha_bits
;
390 for (subset
= 0; subset
< mode
->n_subsets
; subset
++)
391 for (endpoint
= 0; endpoint
< 2; endpoint
++)
392 endpoints
[subset
* 2 + endpoint
][3] = 255;
397 /* Add in the p-bits */
398 if (mode
->has_endpoint_pbits
) {
399 for (subset
= 0; subset
< mode
->n_subsets
; subset
++) {
400 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
401 pbit
= extract_bits(block
, bit_offset
, 1);
404 for (component
= 0; component
< n_components
; component
++) {
405 endpoints
[subset
* 2 + endpoint
][component
] <<= 1;
406 endpoints
[subset
* 2 + endpoint
][component
] |= pbit
;
410 } else if (mode
->has_shared_pbits
) {
411 for (subset
= 0; subset
< mode
->n_subsets
; subset
++) {
412 pbit
= extract_bits(block
, bit_offset
, 1);
415 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
416 for (component
= 0; component
< n_components
; component
++) {
417 endpoints
[subset
* 2 + endpoint
][component
] <<= 1;
418 endpoints
[subset
* 2 + endpoint
][component
] |= pbit
;
424 /* Expand the n-bit values to a byte */
425 for (subset
= 0; subset
< mode
->n_subsets
; subset
++) {
426 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
427 for (component
= 0; component
< 3; component
++) {
428 endpoints
[subset
* 2 + endpoint
][component
] =
429 expand_component(endpoints
[subset
* 2 + endpoint
][component
],
431 mode
->has_endpoint_pbits
+
432 mode
->has_shared_pbits
);
435 if (mode
->n_alpha_bits
> 0) {
436 endpoints
[subset
* 2 + endpoint
][3] =
437 expand_component(endpoints
[subset
* 2 + endpoint
][3],
439 mode
->has_endpoint_pbits
+
440 mode
->has_shared_pbits
);
449 is_anchor(int n_subsets
,
460 return anchor_indices
[0][partition_num
] == texel
;
462 return (anchor_indices
[1][partition_num
] == texel
||
463 anchor_indices
[2][partition_num
] == texel
);
471 count_anchors_before_texel(int n_subsets
,
484 if (texel
> anchor_indices
[0][partition_num
])
488 if (texel
> anchor_indices
[1][partition_num
])
490 if (texel
> anchor_indices
[2][partition_num
])
502 interpolate(int32_t a
, int32_t b
,
506 static const uint8_t weights2
[] = { 0, 21, 43, 64 };
507 static const uint8_t weights3
[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
508 static const uint8_t weights4
[] =
509 { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
510 static const uint8_t *weights
[] = {
511 NULL
, NULL
, weights2
, weights3
, weights4
515 weight
= weights
[index_bits
][index
];
517 return ((64 - weight
) * a
+ weight
* b
+ 32) >> 6;
521 apply_rotation(int rotation
,
531 t
= result
[rotation
];
532 result
[rotation
] = result
[3];
537 fetch_rgba_unorm_from_block(const uint8_t *block
,
541 int mode_num
= ffs(block
[0]);
542 const struct bptc_unorm_mode
*mode
;
543 int bit_offset
, secondary_bit_offset
;
551 int anchors_before_texel
;
553 uint8_t endpoints
[3 * 2][4];
558 /* According to the spec this mode is reserved and shouldn't be used. */
559 memset(result
, 0, 3);
564 mode
= bptc_unorm_modes
+ mode_num
- 1;
565 bit_offset
= mode_num
;
567 partition_num
= extract_bits(block
, bit_offset
, mode
->n_partition_bits
);
568 bit_offset
+= mode
->n_partition_bits
;
570 switch (mode
->n_subsets
) {
575 subsets
= partition_table1
[partition_num
];
578 subsets
= partition_table2
[partition_num
];
585 if (mode
->has_rotation_bits
) {
586 rotation
= extract_bits(block
, bit_offset
, 2);
592 if (mode
->has_index_selection_bit
) {
593 index_selection
= extract_bits(block
, bit_offset
, 1);
599 bit_offset
= extract_unorm_endpoints(mode
, block
, bit_offset
, endpoints
);
601 anchors_before_texel
= count_anchors_before_texel(mode
->n_subsets
,
602 partition_num
, texel
);
604 /* Calculate the offset to the secondary index */
605 secondary_bit_offset
= (bit_offset
+
606 BLOCK_SIZE
* BLOCK_SIZE
* mode
->n_index_bits
-
608 mode
->n_secondary_index_bits
* texel
-
609 anchors_before_texel
);
611 /* Calculate the offset to the primary index for this texel */
612 bit_offset
+= mode
->n_index_bits
* texel
- anchors_before_texel
;
614 subset_num
= (subsets
>> (texel
* 2)) & 3;
616 anchor
= is_anchor(mode
->n_subsets
, partition_num
, texel
);
618 index_bits
= mode
->n_index_bits
;
621 indices
[0] = extract_bits(block
, bit_offset
, index_bits
);
623 if (mode
->n_secondary_index_bits
) {
624 index_bits
= mode
->n_secondary_index_bits
;
627 indices
[1] = extract_bits(block
, secondary_bit_offset
, index_bits
);
630 index
= indices
[index_selection
];
631 index_bits
= (index_selection
?
632 mode
->n_secondary_index_bits
:
635 for (component
= 0; component
< 3; component
++)
636 result
[component
] = interpolate(endpoints
[subset_num
* 2][component
],
637 endpoints
[subset_num
* 2 + 1][component
],
641 /* Alpha uses the opposite index from the color components */
642 if (mode
->n_secondary_index_bits
&& !index_selection
) {
644 index_bits
= mode
->n_secondary_index_bits
;
647 index_bits
= mode
->n_index_bits
;
650 result
[3] = interpolate(endpoints
[subset_num
* 2][3],
651 endpoints
[subset_num
* 2 + 1][3],
655 apply_rotation(rotation
, result
);
659 fetch_bptc_rgba_unorm_bytes(const GLubyte
*map
,
660 GLint rowStride
, GLint i
, GLint j
,
663 const GLubyte
*block
;
665 block
= map
+ (((rowStride
+ 3) / 4) * (j
/ 4) + (i
/ 4)) * 16;
667 fetch_rgba_unorm_from_block(block
, texel
, (i
% 4) + (j
% 4) * 4);
671 fetch_bptc_rgba_unorm(const GLubyte
*map
,
672 GLint rowStride
, GLint i
, GLint j
,
675 GLubyte texel_bytes
[4];
677 fetch_bptc_rgba_unorm_bytes(map
, rowStride
, i
, j
, texel_bytes
);
679 texel
[RCOMP
] = UBYTE_TO_FLOAT(texel_bytes
[0]);
680 texel
[GCOMP
] = UBYTE_TO_FLOAT(texel_bytes
[1]);
681 texel
[BCOMP
] = UBYTE_TO_FLOAT(texel_bytes
[2]);
682 texel
[ACOMP
] = UBYTE_TO_FLOAT(texel_bytes
[3]);
686 fetch_bptc_srgb_alpha_unorm(const GLubyte
*map
,
687 GLint rowStride
, GLint i
, GLint j
,
690 GLubyte texel_bytes
[4];
692 fetch_bptc_rgba_unorm_bytes(map
, rowStride
, i
, j
, texel_bytes
);
694 texel
[RCOMP
] = util_format_srgb_8unorm_to_linear_float(texel_bytes
[0]);
695 texel
[GCOMP
] = util_format_srgb_8unorm_to_linear_float(texel_bytes
[1]);
696 texel
[BCOMP
] = util_format_srgb_8unorm_to_linear_float(texel_bytes
[2]);
697 texel
[ACOMP
] = UBYTE_TO_FLOAT(texel_bytes
[3]);
701 sign_extend(int32_t value
,
704 if ((value
& (1 << (n_bits
- 1)))) {
705 value
|= (~(int32_t) 0) << n_bits
;
712 signed_unquantize(int value
, int n_endpoint_bits
)
716 if (n_endpoint_bits
>= 16)
729 if (value
>= (1 << (n_endpoint_bits
- 1)) - 1)
732 value
= ((value
<< 15) + 0x4000) >> (n_endpoint_bits
- 1);
741 unsigned_unquantize(int value
, int n_endpoint_bits
)
743 if (n_endpoint_bits
>= 15)
749 if (value
== (1 << n_endpoint_bits
) - 1)
752 return ((value
<< 15) + 0x4000) >> (n_endpoint_bits
- 1);
756 extract_float_endpoints(const struct bptc_float_mode
*mode
,
757 const uint8_t *block
,
759 int32_t endpoints
[][3],
762 const struct bptc_float_bitfield
*bitfield
;
763 int endpoint
, component
;
768 if (mode
->n_partition_bits
)
773 memset(endpoints
, 0, sizeof endpoints
[0][0] * n_endpoints
* 3);
775 for (bitfield
= mode
->bitfields
; bitfield
->endpoint
!= -1; bitfield
++) {
776 value
= extract_bits(block
, bit_offset
, bitfield
->n_bits
);
777 bit_offset
+= bitfield
->n_bits
;
779 if (bitfield
->reverse
) {
780 for (i
= 0; i
< bitfield
->n_bits
; i
++) {
781 if (value
& (1 << i
))
782 endpoints
[bitfield
->endpoint
][bitfield
->component
] |=
783 1 << ((bitfield
->n_bits
- 1 - i
) + bitfield
->offset
);
786 endpoints
[bitfield
->endpoint
][bitfield
->component
] |=
787 value
<< bitfield
->offset
;
791 if (mode
->transformed_endpoints
) {
792 /* The endpoints are specified as signed offsets from e0 */
793 for (endpoint
= 1; endpoint
< n_endpoints
; endpoint
++) {
794 for (component
= 0; component
< 3; component
++) {
795 value
= sign_extend(endpoints
[endpoint
][component
],
796 mode
->n_delta_bits
[component
]);
797 endpoints
[endpoint
][component
] =
798 ((endpoints
[0][component
] + value
) &
799 ((1 << mode
->n_endpoint_bits
) - 1));
805 for (endpoint
= 0; endpoint
< n_endpoints
; endpoint
++) {
806 for (component
= 0; component
< 3; component
++) {
807 value
= sign_extend(endpoints
[endpoint
][component
],
808 mode
->n_endpoint_bits
);
809 endpoints
[endpoint
][component
] =
810 signed_unquantize(value
, mode
->n_endpoint_bits
);
814 for (endpoint
= 0; endpoint
< n_endpoints
; endpoint
++) {
815 for (component
= 0; component
< 3; component
++) {
816 endpoints
[endpoint
][component
] =
817 unsigned_unquantize(endpoints
[endpoint
][component
],
818 mode
->n_endpoint_bits
);
827 finish_unsigned_unquantize(int32_t value
)
829 return value
* 31 / 64;
833 finish_signed_unquantize(int32_t value
)
836 return (-value
* 31 / 32) | 0x8000;
838 return value
* 31 / 32;
842 fetch_rgb_float_from_block(const uint8_t *block
,
848 const struct bptc_float_mode
*mode
;
854 int anchors_before_texel
;
855 int32_t endpoints
[2 * 2][3];
861 if (block
[0] & 0x2) {
862 mode_num
= (((block
[0] >> 1) & 0xe) | (block
[0] & 1)) + 2;
865 mode_num
= block
[0] & 3;
869 mode
= bptc_float_modes
+ mode_num
;
871 if (mode
->reserved
) {
872 memset(result
, 0, sizeof result
[0] * 3);
877 bit_offset
= extract_float_endpoints(mode
, block
, bit_offset
,
878 endpoints
, is_signed
);
880 if (mode
->n_partition_bits
) {
881 partition_num
= extract_bits(block
, bit_offset
, mode
->n_partition_bits
);
882 bit_offset
+= mode
->n_partition_bits
;
884 subsets
= partition_table1
[partition_num
];
892 anchors_before_texel
=
893 count_anchors_before_texel(n_subsets
, partition_num
, texel
);
895 /* Calculate the offset to the primary index for this texel */
896 bit_offset
+= mode
->n_index_bits
* texel
- anchors_before_texel
;
898 subset_num
= (subsets
>> (texel
* 2)) & 3;
900 index_bits
= mode
->n_index_bits
;
901 if (is_anchor(n_subsets
, partition_num
, texel
))
903 index
= extract_bits(block
, bit_offset
, index_bits
);
905 for (component
= 0; component
< 3; component
++) {
906 value
= interpolate(endpoints
[subset_num
* 2][component
],
907 endpoints
[subset_num
* 2 + 1][component
],
912 value
= finish_signed_unquantize(value
);
914 value
= finish_unsigned_unquantize(value
);
916 result
[component
] = _mesa_half_to_float(value
);
923 fetch_bptc_rgb_float(const GLubyte
*map
,
924 GLint rowStride
, GLint i
, GLint j
,
928 const GLubyte
*block
;
930 block
= map
+ (((rowStride
+ 3) / 4) * (j
/ 4) + (i
/ 4)) * 16;
932 fetch_rgb_float_from_block(block
, texel
, (i
% 4) + (j
% 4) * 4, is_signed
);
936 fetch_bptc_rgb_signed_float(const GLubyte
*map
,
937 GLint rowStride
, GLint i
, GLint j
,
940 fetch_bptc_rgb_float(map
, rowStride
, i
, j
, texel
, true);
944 fetch_bptc_rgb_unsigned_float(const GLubyte
*map
,
945 GLint rowStride
, GLint i
, GLint j
,
948 fetch_bptc_rgb_float(map
, rowStride
, i
, j
, texel
, false);
951 compressed_fetch_func
952 _mesa_get_bptc_fetch_func(mesa_format format
)
955 case MESA_FORMAT_BPTC_RGBA_UNORM
:
956 return fetch_bptc_rgba_unorm
;
957 case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM
:
958 return fetch_bptc_srgb_alpha_unorm
;
959 case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT
:
960 return fetch_bptc_rgb_signed_float
;
961 case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT
:
962 return fetch_bptc_rgb_unsigned_float
;
969 write_bits(struct bit_writer
*writer
, int n_bits
, int value
)
972 if (n_bits
+ writer
->pos
>= 8) {
973 *(writer
->dst
++) = writer
->buf
| (value
<< writer
->pos
);
975 value
>>= (8 - writer
->pos
);
976 n_bits
-= (8 - writer
->pos
);
979 writer
->buf
|= value
<< writer
->pos
;
980 writer
->pos
+= n_bits
;
983 } while (n_bits
> 0);
987 get_average_luminance_alpha_unorm(int width
, int height
,
988 const uint8_t *src
, int src_rowstride
,
989 int *average_luminance
, int *average_alpha
)
991 int luminance_sum
= 0, alpha_sum
= 0;
994 for (y
= 0; y
< height
; y
++) {
995 for (x
= 0; x
< width
; x
++) {
996 luminance_sum
+= src
[0] + src
[1] + src
[2];
1000 src
+= src_rowstride
- width
* 4;
1003 *average_luminance
= luminance_sum
/ (width
* height
);
1004 *average_alpha
= alpha_sum
/ (width
* height
);
1008 get_rgba_endpoints_unorm(int width
, int height
,
1009 const uint8_t *src
, int src_rowstride
,
1010 int average_luminance
, int average_alpha
,
1011 uint8_t endpoints
[][4])
1013 int endpoint_luminances
[2];
1019 const uint8_t *p
= src
;
1020 int rgb_left_endpoint_count
= 0;
1021 int alpha_left_endpoint_count
= 0;
1024 memset(sums
, 0, sizeof sums
);
1026 for (y
= 0; y
< height
; y
++) {
1027 for (x
= 0; x
< width
; x
++) {
1028 luminance
= p
[0] + p
[1] + p
[2];
1029 if (luminance
< average_luminance
) {
1031 rgb_left_endpoint_count
++;
1035 for (i
= 0; i
< 3; i
++)
1036 sums
[endpoint
][i
] += p
[i
];
1038 if (p
[2] < average_alpha
) {
1040 alpha_left_endpoint_count
++;
1044 sums
[endpoint
][3] += p
[3];
1049 p
+= src_rowstride
- width
* 4;
1052 if (rgb_left_endpoint_count
== 0 ||
1053 rgb_left_endpoint_count
== width
* height
) {
1054 for (i
= 0; i
< 3; i
++)
1055 endpoints
[0][i
] = endpoints
[1][i
] =
1056 (sums
[0][i
] + sums
[1][i
]) / (width
* height
);
1058 for (i
= 0; i
< 3; i
++) {
1059 endpoints
[0][i
] = sums
[0][i
] / rgb_left_endpoint_count
;
1060 endpoints
[1][i
] = (sums
[1][i
] /
1061 (width
* height
- rgb_left_endpoint_count
));
1065 if (alpha_left_endpoint_count
== 0 ||
1066 alpha_left_endpoint_count
== width
* height
) {
1067 endpoints
[0][3] = endpoints
[1][3] =
1068 (sums
[0][3] + sums
[1][3]) / (width
* height
);
1070 endpoints
[0][3] = sums
[0][3] / alpha_left_endpoint_count
;
1071 endpoints
[1][3] = (sums
[1][3] /
1072 (width
* height
- alpha_left_endpoint_count
));
1075 /* We may need to swap the endpoints to ensure the most-significant bit of
1076 * the first index is zero */
1078 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1079 endpoint_luminances
[endpoint
] =
1080 endpoints
[endpoint
][0] +
1081 endpoints
[endpoint
][1] +
1082 endpoints
[endpoint
][2];
1084 midpoint
= (endpoint_luminances
[0] + endpoint_luminances
[1]) / 2;
1086 if ((src
[0] + src
[1] + src
[2] <= midpoint
) !=
1087 (endpoint_luminances
[0] <= midpoint
)) {
1088 memcpy(temp
, endpoints
[0], 3);
1089 memcpy(endpoints
[0], endpoints
[1], 3);
1090 memcpy(endpoints
[1], temp
, 3);
1093 /* Same for the alpha endpoints */
1095 midpoint
= (endpoints
[0][3] + endpoints
[1][3]) / 2;
1097 if ((src
[3] <= midpoint
) != (endpoints
[0][3] <= midpoint
)) {
1098 temp
[0] = endpoints
[0][3];
1099 endpoints
[0][3] = endpoints
[1][3];
1100 endpoints
[1][3] = temp
[0];
1105 write_rgb_indices_unorm(struct bit_writer
*writer
,
1106 int src_width
, int src_height
,
1107 const uint8_t *src
, int src_rowstride
,
1108 uint8_t endpoints
[][4])
1111 int endpoint_luminances
[2];
1116 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1117 endpoint_luminances
[endpoint
] =
1118 endpoints
[endpoint
][0] +
1119 endpoints
[endpoint
][1] +
1120 endpoints
[endpoint
][2];
1123 /* If the endpoints have the same luminance then we'll just use index 0 for
1124 * all of the texels */
1125 if (endpoint_luminances
[0] == endpoint_luminances
[1]) {
1126 write_bits(writer
, BLOCK_SIZE
* BLOCK_SIZE
* 2 - 1, 0);
1130 for (y
= 0; y
< src_height
; y
++) {
1131 for (x
= 0; x
< src_width
; x
++) {
1132 luminance
= src
[0] + src
[1] + src
[2];
1134 index
= ((luminance
- endpoint_luminances
[0]) * 3 /
1135 (endpoint_luminances
[1] - endpoint_luminances
[0]));
1141 assert(x
!= 0 || y
!= 0 || index
< 2);
1143 write_bits(writer
, (x
== 0 && y
== 0) ? 1 : 2, index
);
1148 /* Pad the indices out to the block size */
1149 if (src_width
< BLOCK_SIZE
)
1150 write_bits(writer
, 2 * (BLOCK_SIZE
- src_width
), 0);
1152 src
+= src_rowstride
- src_width
* 4;
1155 /* Pad the indices out to the block size */
1156 if (src_height
< BLOCK_SIZE
)
1157 write_bits(writer
, 2 * BLOCK_SIZE
* (BLOCK_SIZE
- src_height
), 0);
1161 write_alpha_indices_unorm(struct bit_writer
*writer
,
1162 int src_width
, int src_height
,
1163 const uint8_t *src
, int src_rowstride
,
1164 uint8_t endpoints
[][4])
1169 /* If the endpoints have the same alpha then we'll just use index 0 for
1170 * all of the texels */
1171 if (endpoints
[0][3] == endpoints
[1][3]) {
1172 write_bits(writer
, BLOCK_SIZE
* BLOCK_SIZE
* 3 - 1, 0);
1176 for (y
= 0; y
< src_height
; y
++) {
1177 for (x
= 0; x
< src_width
; x
++) {
1178 index
= (((int) src
[3] - (int) endpoints
[0][3]) * 7 /
1179 ((int) endpoints
[1][3] - endpoints
[0][3]));
1185 assert(x
!= 0 || y
!= 0 || index
< 4);
1187 /* The first index has one less bit */
1188 write_bits(writer
, (x
== 0 && y
== 0) ? 2 : 3, index
);
1193 /* Pad the indices out to the block size */
1194 if (src_width
< BLOCK_SIZE
)
1195 write_bits(writer
, 3 * (BLOCK_SIZE
- src_width
), 0);
1197 src
+= src_rowstride
- src_width
* 4;
1200 /* Pad the indices out to the block size */
1201 if (src_height
< BLOCK_SIZE
)
1202 write_bits(writer
, 3 * BLOCK_SIZE
* (BLOCK_SIZE
- src_height
), 0);
1206 compress_rgba_unorm_block(int src_width
, int src_height
,
1207 const uint8_t *src
, int src_rowstride
,
1210 int average_luminance
, average_alpha
;
1211 uint8_t endpoints
[2][4];
1212 struct bit_writer writer
;
1213 int component
, endpoint
;
1215 get_average_luminance_alpha_unorm(src_width
, src_height
, src
, src_rowstride
,
1216 &average_luminance
, &average_alpha
);
1217 get_rgba_endpoints_unorm(src_width
, src_height
, src
, src_rowstride
,
1218 average_luminance
, average_alpha
,
1225 write_bits(&writer
, 5, 0x10); /* mode 4 */
1226 write_bits(&writer
, 2, 0); /* rotation 0 */
1227 write_bits(&writer
, 1, 0); /* index selection bit */
1229 /* Write the color endpoints */
1230 for (component
= 0; component
< 3; component
++)
1231 for (endpoint
= 0; endpoint
< 2; endpoint
++)
1232 write_bits(&writer
, 5, endpoints
[endpoint
][component
] >> 3);
1234 /* Write the alpha endpoints */
1235 for (endpoint
= 0; endpoint
< 2; endpoint
++)
1236 write_bits(&writer
, 6, endpoints
[endpoint
][3] >> 2);
1238 write_rgb_indices_unorm(&writer
,
1239 src_width
, src_height
,
1242 write_alpha_indices_unorm(&writer
,
1243 src_width
, src_height
,
1249 compress_rgba_unorm(int width
, int height
,
1250 const uint8_t *src
, int src_rowstride
,
1251 uint8_t *dst
, int dst_rowstride
)
1256 if (dst_rowstride
>= width
* 4)
1257 dst_row_diff
= dst_rowstride
- ((width
+ 3) & ~3) * 4;
1261 for (y
= 0; y
< height
; y
+= BLOCK_SIZE
) {
1262 for (x
= 0; x
< width
; x
+= BLOCK_SIZE
) {
1263 compress_rgba_unorm_block(MIN2(width
- x
, BLOCK_SIZE
),
1264 MIN2(height
- y
, BLOCK_SIZE
),
1265 src
+ x
* 4 + y
* src_rowstride
,
1270 dst
+= dst_row_diff
;
1275 _mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS
)
1277 const GLubyte
*pixels
;
1278 const GLubyte
*tempImage
= NULL
;
1282 if (srcFormat
!= GL_RGBA
||
1283 srcType
!= GL_UNSIGNED_BYTE
||
1284 ctx
->_ImageTransferState
||
1285 srcPacking
->SwapBytes
) {
1286 /* convert image to RGBA/ubyte */
1287 baseFormat
= _mesa_get_format_base_format(dstFormat
);
1288 tempImage
= _mesa_make_temp_ubyte_image(ctx
, dims
,
1291 srcWidth
, srcHeight
, srcDepth
,
1292 srcFormat
, srcType
, srcAddr
,
1295 return GL_FALSE
; /* out of memory */
1298 rowstride
= srcWidth
* 4;
1300 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1301 srcFormat
, srcType
, 0, 0);
1302 rowstride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1303 srcFormat
, srcType
);
1306 compress_rgba_unorm(srcWidth
, srcHeight
,
1308 dstSlices
[0], dstRowStride
);
1310 free((void *) tempImage
);
1316 get_average_luminance_float(int width
, int height
,
1317 const float *src
, int src_rowstride
)
1319 float luminance_sum
= 0;
1322 for (y
= 0; y
< height
; y
++) {
1323 for (x
= 0; x
< width
; x
++) {
1324 luminance_sum
+= src
[0] + src
[1] + src
[2];
1327 src
+= (src_rowstride
- width
* 3 * sizeof (float)) / sizeof (float);
1330 return luminance_sum
/ (width
* height
);
1334 clamp_value(float value
, bool is_signed
)
1336 if (value
> 65504.0f
)
1340 if (value
< -65504.0f
)
1353 get_endpoints_float(int width
, int height
,
1354 const float *src
, int src_rowstride
,
1355 float average_luminance
, float endpoints
[][3],
1358 float endpoint_luminances
[2];
1361 int endpoint
, component
;
1364 const float *p
= src
;
1365 int left_endpoint_count
= 0;
1368 memset(sums
, 0, sizeof sums
);
1370 for (y
= 0; y
< height
; y
++) {
1371 for (x
= 0; x
< width
; x
++) {
1372 luminance
= p
[0] + p
[1] + p
[2];
1373 if (luminance
< average_luminance
) {
1375 left_endpoint_count
++;
1379 for (i
= 0; i
< 3; i
++)
1380 sums
[endpoint
][i
] += p
[i
];
1385 p
+= (src_rowstride
- width
* 3 * sizeof (float)) / sizeof (float);
1388 if (left_endpoint_count
== 0 ||
1389 left_endpoint_count
== width
* height
) {
1390 for (i
= 0; i
< 3; i
++)
1391 endpoints
[0][i
] = endpoints
[1][i
] =
1392 (sums
[0][i
] + sums
[1][i
]) / (width
* height
);
1394 for (i
= 0; i
< 3; i
++) {
1395 endpoints
[0][i
] = sums
[0][i
] / left_endpoint_count
;
1396 endpoints
[1][i
] = sums
[1][i
] / (width
* height
- left_endpoint_count
);
1400 /* Clamp the endpoints to the range of a half float and strip out
1402 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1403 for (component
= 0; component
< 3; component
++) {
1404 endpoints
[endpoint
][component
] =
1405 clamp_value(endpoints
[endpoint
][component
], is_signed
);
1409 /* We may need to swap the endpoints to ensure the most-significant bit of
1410 * the first index is zero */
1412 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1413 endpoint_luminances
[endpoint
] =
1414 endpoints
[endpoint
][0] +
1415 endpoints
[endpoint
][1] +
1416 endpoints
[endpoint
][2];
1418 midpoint
= (endpoint_luminances
[0] + endpoint_luminances
[1]) / 2.0f
;
1420 if ((src
[0] + src
[1] + src
[2] <= midpoint
) !=
1421 (endpoint_luminances
[0] <= midpoint
)) {
1422 memcpy(temp
, endpoints
[0], sizeof temp
);
1423 memcpy(endpoints
[0], endpoints
[1], sizeof temp
);
1424 memcpy(endpoints
[1], temp
, sizeof temp
);
1429 write_rgb_indices_float(struct bit_writer
*writer
,
1430 int src_width
, int src_height
,
1431 const float *src
, int src_rowstride
,
1432 float endpoints
[][3])
1435 float endpoint_luminances
[2];
1440 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1441 endpoint_luminances
[endpoint
] =
1442 endpoints
[endpoint
][0] +
1443 endpoints
[endpoint
][1] +
1444 endpoints
[endpoint
][2];
1447 /* If the endpoints have the same luminance then we'll just use index 0 for
1448 * all of the texels */
1449 if (endpoint_luminances
[0] == endpoint_luminances
[1]) {
1450 write_bits(writer
, BLOCK_SIZE
* BLOCK_SIZE
* 4 - 1, 0);
1454 for (y
= 0; y
< src_height
; y
++) {
1455 for (x
= 0; x
< src_width
; x
++) {
1456 luminance
= src
[0] + src
[1] + src
[2];
1458 index
= ((luminance
- endpoint_luminances
[0]) * 15 /
1459 (endpoint_luminances
[1] - endpoint_luminances
[0]));
1462 else if (index
> 15)
1465 assert(x
!= 0 || y
!= 0 || index
< 8);
1467 write_bits(writer
, (x
== 0 && y
== 0) ? 3 : 4, index
);
1472 /* Pad the indices out to the block size */
1473 if (src_width
< BLOCK_SIZE
)
1474 write_bits(writer
, 4 * (BLOCK_SIZE
- src_width
), 0);
1476 src
+= (src_rowstride
- src_width
* 3 * sizeof (float)) / sizeof (float);
1479 /* Pad the indices out to the block size */
1480 if (src_height
< BLOCK_SIZE
)
1481 write_bits(writer
, 4 * BLOCK_SIZE
* (BLOCK_SIZE
- src_height
), 0);
1485 get_endpoint_value(float value
, bool is_signed
)
1491 half
= _mesa_float_to_half(value
);
1493 if (half
& 0x8000) {
1498 half
= (32 * half
/ 31) >> 6;
1501 half
= -half
& ((1 << 10) - 1);
1508 half
= _mesa_float_to_half(value
);
1510 return (64 * half
/ 31) >> 6;
1515 compress_rgb_float_block(int src_width
, int src_height
,
1516 const float *src
, int src_rowstride
,
1520 float average_luminance
;
1521 float endpoints
[2][3];
1522 struct bit_writer writer
;
1523 int component
, endpoint
;
1527 get_average_luminance_float(src_width
, src_height
, src
, src_rowstride
);
1528 get_endpoints_float(src_width
, src_height
, src
, src_rowstride
,
1529 average_luminance
, endpoints
, is_signed
);
1535 write_bits(&writer
, 5, 3); /* mode 3 */
1537 /* Write the endpoints */
1538 for (endpoint
= 0; endpoint
< 2; endpoint
++) {
1539 for (component
= 0; component
< 3; component
++) {
1541 get_endpoint_value(endpoints
[endpoint
][component
], is_signed
);
1542 write_bits(&writer
, 10, endpoint_value
);
1546 write_rgb_indices_float(&writer
,
1547 src_width
, src_height
,
1553 compress_rgb_float(int width
, int height
,
1554 const float *src
, int src_rowstride
,
1555 uint8_t *dst
, int dst_rowstride
,
1561 if (dst_rowstride
>= width
* 4)
1562 dst_row_diff
= dst_rowstride
- ((width
+ 3) & ~3) * 4;
1566 for (y
= 0; y
< height
; y
+= BLOCK_SIZE
) {
1567 for (x
= 0; x
< width
; x
+= BLOCK_SIZE
) {
1568 compress_rgb_float_block(MIN2(width
- x
, BLOCK_SIZE
),
1569 MIN2(height
- y
, BLOCK_SIZE
),
1571 y
* src_rowstride
/ sizeof (float),
1577 dst
+= dst_row_diff
;
1582 texstore_bptc_rgb_float(TEXSTORE_PARAMS
,
1585 const float *pixels
;
1586 const float *tempImage
= NULL
;
1590 if (srcFormat
!= GL_RGB
||
1591 srcType
!= GL_FLOAT
||
1592 ctx
->_ImageTransferState
||
1593 srcPacking
->SwapBytes
) {
1594 /* convert image to RGB/float */
1595 baseFormat
= _mesa_get_format_base_format(dstFormat
);
1596 tempImage
= _mesa_make_temp_float_image(ctx
, dims
,
1599 srcWidth
, srcHeight
, srcDepth
,
1600 srcFormat
, srcType
, srcAddr
,
1602 ctx
->_ImageTransferState
);
1604 return GL_FALSE
; /* out of memory */
1607 rowstride
= srcWidth
* sizeof(float) * 3;
1609 pixels
= _mesa_image_address2d(srcPacking
, srcAddr
, srcWidth
, srcHeight
,
1610 srcFormat
, srcType
, 0, 0);
1611 rowstride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
1612 srcFormat
, srcType
);
1615 compress_rgb_float(srcWidth
, srcHeight
,
1617 dstSlices
[0], dstRowStride
,
1620 free((void *) tempImage
);
1626 _mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS
)
1628 ASSERT(dstFormat
== MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT
);
1630 return texstore_bptc_rgb_float(ctx
, dims
, baseInternalFormat
,
1631 dstFormat
, dstRowStride
, dstSlices
,
1632 srcWidth
, srcHeight
, srcDepth
,
1634 srcAddr
, srcPacking
,
1639 _mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS
)
1641 ASSERT(dstFormat
== MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT
);
1643 return texstore_bptc_rgb_float(ctx
, dims
, baseInternalFormat
,
1644 dstFormat
, dstRowStride
, dstSlices
,
1645 srcWidth
, srcHeight
, srcDepth
,
1647 srcAddr
, srcPacking
,
1648 false /* unsigned */);