| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Texture block decompression | ||
| 3 | * Copyright (C) 2009 Benjamin Dobell, Glass Echidna | ||
| 4 | * Copyright (C) 2012 Matthäus G. "Anteru" Chajdas (http://anteru.net) | ||
| 5 | * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com> | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 8 | * copy of this software and associated documentation files (the "Software"), | ||
| 9 | * to deal in the Software without restriction, including without limitation | ||
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 12 | * Software is furnished to do so, subject to the following conditions: | ||
| 13 | * The above copyright notice and this permission notice shall be included | ||
| 14 | * in all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 22 | * IN THE SOFTWARE. | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <stddef.h> | ||
| 26 | #include <stdint.h> | ||
| 27 | |||
| 28 | #include "libavutil/attributes.h" | ||
| 29 | #include "libavutil/common.h" | ||
| 30 | #include "libavutil/intreadwrite.h" | ||
| 31 | #include "libavutil/libm.h" | ||
| 32 | |||
| 33 | #include "texturedsp.h" | ||
| 34 | |||
| 35 | #define RGBA(r, g, b, a) (((uint8_t)(r) << 0) | \ | ||
| 36 | ((uint8_t)(g) << 8) | \ | ||
| 37 | ((uint8_t)(b) << 16) | \ | ||
| 38 | ((unsigned)(uint8_t)(a) << 24)) | ||
| 39 | |||
| 40 | 1128062 | static av_always_inline void extract_color(uint32_t colors[4], | |
| 41 | uint16_t color0, | ||
| 42 | uint16_t color1, | ||
| 43 | int dxtn, int alpha) | ||
| 44 | { | ||
| 45 | int tmp; | ||
| 46 | uint8_t r0, g0, b0, r1, g1, b1; | ||
| 47 |
2/2✓ Branch 0 taken 582270 times.
✓ Branch 1 taken 545792 times.
|
1128062 | uint8_t a = dxtn ? 0 : 255; |
| 48 | |||
| 49 | 1128062 | tmp = (color0 >> 11) * 255 + 16; | |
| 50 | 1128062 | r0 = (uint8_t) ((tmp / 32 + tmp) / 32); | |
| 51 | 1128062 | tmp = ((color0 & 0x07E0) >> 5) * 255 + 32; | |
| 52 | 1128062 | g0 = (uint8_t) ((tmp / 64 + tmp) / 64); | |
| 53 | 1128062 | tmp = (color0 & 0x001F) * 255 + 16; | |
| 54 | 1128062 | b0 = (uint8_t) ((tmp / 32 + tmp) / 32); | |
| 55 | |||
| 56 | 1128062 | tmp = (color1 >> 11) * 255 + 16; | |
| 57 | 1128062 | r1 = (uint8_t) ((tmp / 32 + tmp) / 32); | |
| 58 | 1128062 | tmp = ((color1 & 0x07E0) >> 5) * 255 + 32; | |
| 59 | 1128062 | g1 = (uint8_t) ((tmp / 64 + tmp) / 64); | |
| 60 | 1128062 | tmp = (color1 & 0x001F) * 255 + 16; | |
| 61 | 1128062 | b1 = (uint8_t) ((tmp / 32 + tmp) / 32); | |
| 62 | |||
| 63 |
4/4✓ Branch 0 taken 545792 times.
✓ Branch 1 taken 582270 times.
✓ Branch 2 taken 402770 times.
✓ Branch 3 taken 143022 times.
|
1128062 | if (dxtn || color0 > color1) { |
| 64 | 985040 | colors[0] = RGBA(r0, g0, b0, a); | |
| 65 | 985040 | colors[1] = RGBA(r1, g1, b1, a); | |
| 66 | 985040 | colors[2] = RGBA((2 * r0 + r1) / 3, | |
| 67 | (2 * g0 + g1) / 3, | ||
| 68 | (2 * b0 + b1) / 3, | ||
| 69 | a); | ||
| 70 | 985040 | colors[3] = RGBA((2 * r1 + r0) / 3, | |
| 71 | (2 * g1 + g0) / 3, | ||
| 72 | (2 * b1 + b0) / 3, | ||
| 73 | a); | ||
| 74 | } else { | ||
| 75 | 143022 | colors[0] = RGBA(r0, g0, b0, a); | |
| 76 | 143022 | colors[1] = RGBA(r1, g1, b1, a); | |
| 77 | 143022 | colors[2] = RGBA((r0 + r1) / 2, | |
| 78 | (g0 + g1) / 2, | ||
| 79 | (b0 + b1) / 2, | ||
| 80 | a); | ||
| 81 | 143022 | colors[3] = RGBA(0, 0, 0, alpha); | |
| 82 | } | ||
| 83 | 1128062 | } | |
| 84 | |||
| 85 | 545792 | static inline void dxt1_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 86 | const uint8_t *block, uint8_t alpha) | ||
| 87 | { | ||
| 88 | int x, y; | ||
| 89 | uint32_t colors[4]; | ||
| 90 | 545792 | uint16_t color0 = AV_RL16(block + 0); | |
| 91 | 545792 | uint16_t color1 = AV_RL16(block + 2); | |
| 92 | 545792 | uint32_t code = AV_RL32(block + 4); | |
| 93 | |||
| 94 | 545792 | extract_color(colors, color0, color1, 0, alpha); | |
| 95 | |||
| 96 |
2/2✓ Branch 0 taken 2183168 times.
✓ Branch 1 taken 545792 times.
|
2728960 | for (y = 0; y < 4; y++) { |
| 97 |
2/2✓ Branch 0 taken 8732672 times.
✓ Branch 1 taken 2183168 times.
|
10915840 | for (x = 0; x < 4; x++) { |
| 98 | 8732672 | uint32_t pixel = colors[code & 3]; | |
| 99 | 8732672 | code >>= 2; | |
| 100 | 8732672 | AV_WL32(dst + x * 4, pixel); | |
| 101 | } | ||
| 102 | 2183168 | dst += stride; | |
| 103 | } | ||
| 104 | 545792 | } | |
| 105 | |||
| 106 | /** | ||
| 107 | * Decompress one block of a DXT1 texture and store the resulting | ||
| 108 | * RGBA pixels in 'dst'. Alpha component is fully opaque. | ||
| 109 | * | ||
| 110 | * @param dst output buffer. | ||
| 111 | * @param stride scanline in bytes. | ||
| 112 | * @param block block to decompress. | ||
| 113 | * @return how much texture data has been consumed. | ||
| 114 | */ | ||
| 115 | 542720 | static int dxt1_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 116 | { | ||
| 117 | 542720 | dxt1_block_internal(dst, stride, block, 255); | |
| 118 | |||
| 119 | 542720 | return 8; | |
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Decompress one block of a DXT1 with 1-bit alpha texture and store | ||
| 124 | * the resulting RGBA pixels in 'dst'. Alpha is either fully opaque or | ||
| 125 | * fully transparent. | ||
| 126 | * | ||
| 127 | * @param dst output buffer. | ||
| 128 | * @param stride scanline in bytes. | ||
| 129 | * @param block block to decompress. | ||
| 130 | * @return how much texture data has been consumed. | ||
| 131 | */ | ||
| 132 | 3072 | static int dxt1a_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 133 | { | ||
| 134 | 3072 | dxt1_block_internal(dst, stride, block, 0); | |
| 135 | |||
| 136 | 3072 | return 8; | |
| 137 | } | ||
| 138 | |||
| 139 | 13758 | static inline void dxt3_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 140 | const uint8_t *block) | ||
| 141 | { | ||
| 142 | int x, y; | ||
| 143 | uint32_t colors[4]; | ||
| 144 | 13758 | uint16_t color0 = AV_RL16(block + 8); | |
| 145 | 13758 | uint16_t color1 = AV_RL16(block + 10); | |
| 146 | 13758 | uint32_t code = AV_RL32(block + 12); | |
| 147 | |||
| 148 | 13758 | extract_color(colors, color0, color1, 1, 0); | |
| 149 | |||
| 150 |
2/2✓ Branch 0 taken 55032 times.
✓ Branch 1 taken 13758 times.
|
68790 | for (y = 0; y < 4; y++) { |
| 151 | 55032 | const uint16_t alpha_code = AV_RL16(block + 2 * y); | |
| 152 | uint8_t alpha_values[4]; | ||
| 153 | |||
| 154 | 55032 | alpha_values[0] = ((alpha_code >> 0) & 0x0F) * 17; | |
| 155 | 55032 | alpha_values[1] = ((alpha_code >> 4) & 0x0F) * 17; | |
| 156 | 55032 | alpha_values[2] = ((alpha_code >> 8) & 0x0F) * 17; | |
| 157 | 55032 | alpha_values[3] = ((alpha_code >> 12) & 0x0F) * 17; | |
| 158 | |||
| 159 |
2/2✓ Branch 0 taken 220128 times.
✓ Branch 1 taken 55032 times.
|
275160 | for (x = 0; x < 4; x++) { |
| 160 | 220128 | uint8_t alpha = alpha_values[x]; | |
| 161 | 220128 | uint32_t pixel = colors[code & 3] | ((unsigned)alpha << 24); | |
| 162 | 220128 | code >>= 2; | |
| 163 | |||
| 164 | 220128 | AV_WL32(dst + x * 4, pixel); | |
| 165 | } | ||
| 166 | 55032 | dst += stride; | |
| 167 | } | ||
| 168 | 13758 | } | |
| 169 | |||
| 170 | /** Convert a premultiplied alpha pixel to a straight alpha pixel. */ | ||
| 171 | 8310784 | static av_always_inline void premult2straight(uint8_t *src) | |
| 172 | { | ||
| 173 | 8310784 | int r = src[0]; | |
| 174 | 8310784 | int g = src[1]; | |
| 175 | 8310784 | int b = src[2]; | |
| 176 | 8310784 | int a = src[3]; /* unchanged */ | |
| 177 | |||
| 178 |
2/2✓ Branch 0 taken 4156 times.
✓ Branch 1 taken 8306628 times.
|
8310784 | if (a == 0) |
| 179 | 4156 | return; | |
| 180 | |||
| 181 |
1/2✓ Branch 0 taken 8306628 times.
✗ Branch 1 not taken.
|
8306628 | src[0] = (uint8_t) FFMIN(r * 255 / a, 255); |
| 182 |
2/2✓ Branch 0 taken 8305640 times.
✓ Branch 1 taken 988 times.
|
8306628 | src[1] = (uint8_t) FFMIN(g * 255 / a, 255); |
| 183 |
2/2✓ Branch 0 taken 8306546 times.
✓ Branch 1 taken 82 times.
|
8306628 | src[2] = (uint8_t) FFMIN(b * 255 / a, 255); |
| 184 | } | ||
| 185 | |||
| 186 | /** | ||
| 187 | * Decompress one block of a DXT2 texture and store the resulting | ||
| 188 | * RGBA pixels in 'dst'. | ||
| 189 | * | ||
| 190 | * @param dst output buffer. | ||
| 191 | * @param stride scanline in bytes. | ||
| 192 | * @param block block to decompress. | ||
| 193 | * @return how much texture data has been consumed. | ||
| 194 | */ | ||
| 195 | 512 | static int dxt2_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 196 | { | ||
| 197 | int x, y; | ||
| 198 | |||
| 199 | 512 | dxt3_block_internal(dst, stride, block); | |
| 200 | |||
| 201 | /* This format is DXT3, but returns premultiplied alpha. It needs to be | ||
| 202 | * converted because it's what lavc outputs (and swscale expects). */ | ||
| 203 |
2/2✓ Branch 0 taken 2048 times.
✓ Branch 1 taken 512 times.
|
2560 | for (y = 0; y < 4; y++) |
| 204 |
2/2✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 2048 times.
|
10240 | for (x = 0; x < 4; x++) |
| 205 | 8192 | premult2straight(dst + x * 4 + y * stride); | |
| 206 | |||
| 207 | 512 | return 16; | |
| 208 | } | ||
| 209 | |||
| 210 | /** | ||
| 211 | * Decompress one block of a DXT3 texture and store the resulting | ||
| 212 | * RGBA pixels in 'dst'. | ||
| 213 | * | ||
| 214 | * @param dst output buffer. | ||
| 215 | * @param stride scanline in bytes. | ||
| 216 | * @param block block to decompress. | ||
| 217 | * @return how much texture data has been consumed. | ||
| 218 | */ | ||
| 219 | 13246 | static int dxt3_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 220 | { | ||
| 221 | 13246 | dxt3_block_internal(dst, stride, block); | |
| 222 | |||
| 223 | 13246 | return 16; | |
| 224 | } | ||
| 225 | |||
| 226 | /** | ||
| 227 | * Decompress a BC 16x3 index block stored as | ||
| 228 | * h g f e | ||
| 229 | * d c b a | ||
| 230 | * p o n m | ||
| 231 | * l k j i | ||
| 232 | * | ||
| 233 | * Bits packed as | ||
| 234 | * | h | g | f | e | d | c | b | a | // Entry | ||
| 235 | * |765 432 107 654 321 076 543 210| // Bit | ||
| 236 | * |0000000000111111111112222222222| // Byte | ||
| 237 | * | ||
| 238 | * into 16 8-bit indices. | ||
| 239 | */ | ||
| 240 | 609792 | static void decompress_indices(uint8_t *dst, const uint8_t *src) | |
| 241 | { | ||
| 242 | int block, i; | ||
| 243 | |||
| 244 |
2/2✓ Branch 0 taken 1219584 times.
✓ Branch 1 taken 609792 times.
|
1829376 | for (block = 0; block < 2; block++) { |
| 245 | 1219584 | int tmp = AV_RL24(src); | |
| 246 | |||
| 247 | /* Unpack 8x3 bit from last 3 byte block */ | ||
| 248 |
2/2✓ Branch 0 taken 9756672 times.
✓ Branch 1 taken 1219584 times.
|
10976256 | for (i = 0; i < 8; i++) |
| 249 | 9756672 | dst[i] = (tmp >> (i * 3)) & 0x7; | |
| 250 | |||
| 251 | 1219584 | src += 3; | |
| 252 | 1219584 | dst += 8; | |
| 253 | } | ||
| 254 | 609792 | } | |
| 255 | |||
| 256 | 568512 | static inline void dxt5_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 257 | const uint8_t *block) | ||
| 258 | { | ||
| 259 | int x, y; | ||
| 260 | uint32_t colors[4]; | ||
| 261 | uint8_t alpha_indices[16]; | ||
| 262 | 568512 | uint16_t color0 = AV_RL16(block + 8); | |
| 263 | 568512 | uint16_t color1 = AV_RL16(block + 10); | |
| 264 | 568512 | uint32_t code = AV_RL32(block + 12); | |
| 265 | 568512 | uint8_t alpha0 = *(block); | |
| 266 | 568512 | uint8_t alpha1 = *(block + 1); | |
| 267 | |||
| 268 | 568512 | decompress_indices(alpha_indices, block + 2); | |
| 269 | |||
| 270 | 568512 | extract_color(colors, color0, color1, 1, 0); | |
| 271 | |||
| 272 |
2/2✓ Branch 0 taken 2274048 times.
✓ Branch 1 taken 568512 times.
|
2842560 | for (y = 0; y < 4; y++) { |
| 273 |
2/2✓ Branch 0 taken 9096192 times.
✓ Branch 1 taken 2274048 times.
|
11370240 | for (x = 0; x < 4; x++) { |
| 274 | 9096192 | int alpha_code = alpha_indices[x + y * 4]; | |
| 275 | uint32_t pixel; | ||
| 276 | uint8_t alpha; | ||
| 277 | |||
| 278 |
2/2✓ Branch 0 taken 4550243 times.
✓ Branch 1 taken 4545949 times.
|
9096192 | if (alpha_code == 0) { |
| 279 | 4550243 | alpha = alpha0; | |
| 280 |
2/2✓ Branch 0 taken 4214403 times.
✓ Branch 1 taken 331546 times.
|
4545949 | } else if (alpha_code == 1) { |
| 281 | 4214403 | alpha = alpha1; | |
| 282 | } else { | ||
| 283 |
2/2✓ Branch 0 taken 300328 times.
✓ Branch 1 taken 31218 times.
|
331546 | if (alpha0 > alpha1) { |
| 284 | 300328 | alpha = (uint8_t) (((8 - alpha_code) * alpha0 + | |
| 285 | 300328 | (alpha_code - 1) * alpha1) / 7); | |
| 286 | } else { | ||
| 287 |
2/2✓ Branch 0 taken 6494 times.
✓ Branch 1 taken 24724 times.
|
31218 | if (alpha_code == 6) { |
| 288 | 6494 | alpha = 0; | |
| 289 |
2/2✓ Branch 0 taken 18150 times.
✓ Branch 1 taken 6574 times.
|
24724 | } else if (alpha_code == 7) { |
| 290 | 18150 | alpha = 255; | |
| 291 | } else { | ||
| 292 | 6574 | alpha = (uint8_t) (((6 - alpha_code) * alpha0 + | |
| 293 | 6574 | (alpha_code - 1) * alpha1) / 5); | |
| 294 | } | ||
| 295 | } | ||
| 296 | } | ||
| 297 | 9096192 | pixel = colors[code & 3] | ((unsigned)alpha << 24); | |
| 298 | 9096192 | code >>= 2; | |
| 299 | 9096192 | AV_WL32(dst + x * 4, pixel); | |
| 300 | } | ||
| 301 | 2274048 | dst += stride; | |
| 302 | } | ||
| 303 | 568512 | } | |
| 304 | |||
| 305 | /** | ||
| 306 | * Decompress one block of a DXT4 texture and store the resulting | ||
| 307 | * RGBA pixels in 'dst'. | ||
| 308 | * | ||
| 309 | * @param dst output buffer. | ||
| 310 | * @param stride scanline in bytes. | ||
| 311 | * @param block block to decompress. | ||
| 312 | * @return how much texture data has been consumed. | ||
| 313 | */ | ||
| 314 | 518912 | static int dxt4_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 315 | { | ||
| 316 | int x, y; | ||
| 317 | |||
| 318 | 518912 | dxt5_block_internal(dst, stride, block); | |
| 319 | |||
| 320 | /* This format is DXT5, but returns premultiplied alpha. It needs to be | ||
| 321 | * converted because it's what lavc outputs (and swscale expects). */ | ||
| 322 |
2/2✓ Branch 0 taken 2075648 times.
✓ Branch 1 taken 518912 times.
|
2594560 | for (y = 0; y < 4; y++) |
| 323 |
2/2✓ Branch 0 taken 8302592 times.
✓ Branch 1 taken 2075648 times.
|
10378240 | for (x = 0; x < 4; x++) |
| 324 | 8302592 | premult2straight(dst + x * 4 + y * stride); | |
| 325 | |||
| 326 | 518912 | return 16; | |
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Decompress one block of a DXT5 texture and store the resulting | ||
| 331 | * RGBA pixels in 'dst'. | ||
| 332 | * | ||
| 333 | * @param dst output buffer. | ||
| 334 | * @param stride scanline in bytes. | ||
| 335 | * @param block block to decompress. | ||
| 336 | * @return how much texture data has been consumed. | ||
| 337 | */ | ||
| 338 | 27392 | static int dxt5_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 339 | { | ||
| 340 | 27392 | dxt5_block_internal(dst, stride, block); | |
| 341 | |||
| 342 | 27392 | return 16; | |
| 343 | } | ||
| 344 | |||
| 345 | /** | ||
| 346 | * Convert a YCoCg buffer to RGBA. | ||
| 347 | * | ||
| 348 | * @param src input buffer. | ||
| 349 | * @param scaled variant with scaled chroma components and opaque alpha. | ||
| 350 | */ | ||
| 351 | 355328 | static av_always_inline void ycocg2rgba(uint8_t *src, int scaled) | |
| 352 | { | ||
| 353 | 355328 | int r = src[0]; | |
| 354 | 355328 | int g = src[1]; | |
| 355 | 355328 | int b = src[2]; | |
| 356 | 355328 | int a = src[3]; | |
| 357 | |||
| 358 |
2/2✓ Branch 0 taken 347136 times.
✓ Branch 1 taken 8192 times.
|
355328 | int s = scaled ? (b >> 3) + 1 : 1; |
| 359 | 355328 | int y = a; | |
| 360 | 355328 | int co = (r - 128) / s; | |
| 361 | 355328 | int cg = (g - 128) / s; | |
| 362 | |||
| 363 | 355328 | src[0] = av_clip_uint8(y + co - cg); | |
| 364 | 355328 | src[1] = av_clip_uint8(y + cg); | |
| 365 | 355328 | src[2] = av_clip_uint8(y - co - cg); | |
| 366 |
2/2✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 347136 times.
|
355328 | src[3] = scaled ? 255 : b; |
| 367 | 355328 | } | |
| 368 | |||
| 369 | /** | ||
| 370 | * Decompress one block of a DXT5 texture with classic YCoCg and store | ||
| 371 | * the resulting RGBA pixels in 'dst'. Alpha component is fully opaque. | ||
| 372 | * | ||
| 373 | * @param dst output buffer. | ||
| 374 | * @param stride scanline in bytes. | ||
| 375 | * @param block block to decompress. | ||
| 376 | * @return how much texture data has been consumed. | ||
| 377 | */ | ||
| 378 | 512 | static int dxt5y_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 379 | { | ||
| 380 | int x, y; | ||
| 381 | |||
| 382 | /* This format is basically DXT5, with luma stored in alpha. | ||
| 383 | * Run a normal decompress and then reorder the components. */ | ||
| 384 | 512 | dxt5_block_internal(dst, stride, block); | |
| 385 | |||
| 386 |
2/2✓ Branch 0 taken 2048 times.
✓ Branch 1 taken 512 times.
|
2560 | for (y = 0; y < 4; y++) |
| 387 |
2/2✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 2048 times.
|
10240 | for (x = 0; x < 4; x++) |
| 388 | 8192 | ycocg2rgba(dst + x * 4 + y * stride, 0); | |
| 389 | |||
| 390 | 512 | return 16; | |
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * Decompress one block of a DXT5 texture with scaled YCoCg and store | ||
| 395 | * the resulting RGBA pixels in 'dst'. Alpha component is fully opaque. | ||
| 396 | * | ||
| 397 | * @param dst output buffer. | ||
| 398 | * @param stride scanline in bytes. | ||
| 399 | * @param block block to decompress. | ||
| 400 | * @return how much texture data has been consumed. | ||
| 401 | */ | ||
| 402 | 21696 | static int dxt5ys_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 403 | { | ||
| 404 | int x, y; | ||
| 405 | |||
| 406 | /* This format is basically DXT5, with luma stored in alpha. | ||
| 407 | * Run a normal decompress and then reorder the components. */ | ||
| 408 | 21696 | dxt5_block_internal(dst, stride, block); | |
| 409 | |||
| 410 |
2/2✓ Branch 0 taken 86784 times.
✓ Branch 1 taken 21696 times.
|
108480 | for (y = 0; y < 4; y++) |
| 411 |
2/2✓ Branch 0 taken 347136 times.
✓ Branch 1 taken 86784 times.
|
433920 | for (x = 0; x < 4; x++) |
| 412 | 347136 | ycocg2rgba(dst + x * 4 + y * stride, 1); | |
| 413 | |||
| 414 | 21696 | return 16; | |
| 415 | } | ||
| 416 | |||
| 417 | 41280 | static inline void rgtc_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 418 | const uint8_t *block, | ||
| 419 | const int *color_tab, int mono, int offset, int pix_size) | ||
| 420 | { | ||
| 421 | uint8_t indices[16]; | ||
| 422 | int x, y; | ||
| 423 | |||
| 424 | 41280 | decompress_indices(indices, block + 2); | |
| 425 | |||
| 426 | /* Only one or two channels are stored at most, since it only used to | ||
| 427 | * compress specular (black and white) or normal (red and green) maps. | ||
| 428 | * Although the standard says to zero out unused components, many | ||
| 429 | * implementations fill all of them with the same value. */ | ||
| 430 |
2/2✓ Branch 0 taken 165120 times.
✓ Branch 1 taken 41280 times.
|
206400 | for (y = 0; y < 4; y++) { |
| 431 |
2/2✓ Branch 0 taken 660480 times.
✓ Branch 1 taken 165120 times.
|
825600 | for (x = 0; x < 4; x++) { |
| 432 | 660480 | int i = indices[x + y * 4]; | |
| 433 | /* Interval expansion from [-1 1] or [0 1] to [0 255]. */ | ||
| 434 | 660480 | int c = color_tab[i]; | |
| 435 | |||
| 436 |
2/2✓ Branch 0 taken 570368 times.
✓ Branch 1 taken 90112 times.
|
660480 | if (mono){ |
| 437 | 570368 | dst [x * pix_size + y * stride + offset] = (uint8_t)c; | |
| 438 | } | ||
| 439 | else{ | ||
| 440 | 90112 | uint32_t pixel = RGBA(c, c, c, 255U); | |
| 441 | 90112 | AV_WL32(dst + x * pix_size + y * stride, pixel); | |
| 442 | } | ||
| 443 | } | ||
| 444 | } | ||
| 445 | 41280 | } | |
| 446 | |||
| 447 | 41280 | static inline void rgtc1_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 448 | const uint8_t *block, int sign, int mono, int offset, int pix_size) | ||
| 449 | { | ||
| 450 | int color_table[8]; | ||
| 451 | int r0, r1; | ||
| 452 | |||
| 453 |
2/2✓ Branch 0 taken 1536 times.
✓ Branch 1 taken 39744 times.
|
41280 | if (sign) { |
| 454 | /* signed data is in [-128 127] so just offset it to unsigned | ||
| 455 | * and it can be treated exactly the same */ | ||
| 456 | 1536 | r0 = ((int8_t) block[0]) + 128; | |
| 457 | 1536 | r1 = ((int8_t) block[1]) + 128; | |
| 458 | } else { | ||
| 459 | 39744 | r0 = block[0]; | |
| 460 | 39744 | r1 = block[1]; | |
| 461 | } | ||
| 462 | |||
| 463 | 41280 | color_table[0] = r0; | |
| 464 | 41280 | color_table[1] = r1; | |
| 465 | |||
| 466 |
2/2✓ Branch 0 taken 22084 times.
✓ Branch 1 taken 19196 times.
|
41280 | if (r0 > r1) { |
| 467 | /* 6 interpolated color values */ | ||
| 468 | 22084 | color_table[2] = (6 * r0 + 1 * r1) / 7; // bit code 010 | |
| 469 | 22084 | color_table[3] = (5 * r0 + 2 * r1) / 7; // bit code 011 | |
| 470 | 22084 | color_table[4] = (4 * r0 + 3 * r1) / 7; // bit code 100 | |
| 471 | 22084 | color_table[5] = (3 * r0 + 4 * r1) / 7; // bit code 101 | |
| 472 | 22084 | color_table[6] = (2 * r0 + 5 * r1) / 7; // bit code 110 | |
| 473 | 22084 | color_table[7] = (1 * r0 + 6 * r1) / 7; // bit code 111 | |
| 474 | } else { | ||
| 475 | /* 4 interpolated color values */ | ||
| 476 | 19196 | color_table[2] = (4 * r0 + 1 * r1) / 5; // bit code 010 | |
| 477 | 19196 | color_table[3] = (3 * r0 + 2 * r1) / 5; // bit code 011 | |
| 478 | 19196 | color_table[4] = (2 * r0 + 3 * r1) / 5; // bit code 100 | |
| 479 | 19196 | color_table[5] = (1 * r0 + 4 * r1) / 5; // bit code 101 | |
| 480 | 19196 | color_table[6] = 0; /* min range */ // bit code 110 | |
| 481 | 19196 | color_table[7] = 255; /* max range */ // bit code 111 | |
| 482 | } | ||
| 483 | |||
| 484 | 41280 | rgtc_block_internal(dst, stride, block, color_table, mono, offset, pix_size); | |
| 485 | 41280 | } | |
| 486 | |||
| 487 | /** | ||
| 488 | * Decompress one block of a RGRC1 texture with signed components | ||
| 489 | * and store the resulting RGBA pixels in 'dst'. | ||
| 490 | * | ||
| 491 | * @param dst output buffer. | ||
| 492 | * @param stride scanline in bytes. | ||
| 493 | * @param block block to decompress. | ||
| 494 | * @return how much texture data has been consumed. | ||
| 495 | */ | ||
| 496 | 512 | static int rgtc1s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 497 | { | ||
| 498 | 512 | rgtc1_block_internal(dst, stride, block, 1, 0, 0, 4); | |
| 499 | |||
| 500 | 512 | return 8; | |
| 501 | } | ||
| 502 | |||
| 503 | /** | ||
| 504 | * Decompress one block of a RGRC1 texture with unsigned components | ||
| 505 | * and store the resulting RGBA pixels in 'dst'. | ||
| 506 | * | ||
| 507 | * @param dst output buffer. | ||
| 508 | * @param stride scanline in bytes. | ||
| 509 | * @param block block to decompress. | ||
| 510 | * @return how much texture data has been consumed. | ||
| 511 | */ | ||
| 512 | 1024 | static int rgtc1u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 513 | { | ||
| 514 | 1024 | rgtc1_block_internal(dst, stride, block, 0, 0, 0, 4); | |
| 515 | |||
| 516 | 1024 | return 8; | |
| 517 | } | ||
| 518 | |||
| 519 | /** | ||
| 520 | * Decompress one block of a RGTC1 texture with unsigned components | ||
| 521 | * and overwrite the alpha component in 'dst' (RGBA data). | ||
| 522 | * | ||
| 523 | * @param dst output buffer. | ||
| 524 | * @param stride scanline in bytes. | ||
| 525 | * @param block block to decompress. | ||
| 526 | * @return how much texture data has been consumed. | ||
| 527 | */ | ||
| 528 | 1728 | static int rgtc1u_alpha_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 529 | { | ||
| 530 | 1728 | rgtc1_block_internal(dst, stride, block, 0, 1, 3, 4); | |
| 531 | |||
| 532 | 1728 | return 8; | |
| 533 | } | ||
| 534 | |||
| 535 | /** | ||
| 536 | * Decompress one block of a RGTC1 texture with unsigned components | ||
| 537 | * to Gray 8. | ||
| 538 | * | ||
| 539 | * @param dst output buffer. | ||
| 540 | * @param stride scanline in bytes. | ||
| 541 | * @param block block to decompress. | ||
| 542 | * @return how much texture data has been consumed. | ||
| 543 | */ | ||
| 544 | 33920 | static int rgtc1u_gray_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 545 | { | ||
| 546 | 33920 | rgtc1_block_internal(dst, stride, block, 0, 1, 0, 1); | |
| 547 | |||
| 548 | 33920 | return 8; | |
| 549 | } | ||
| 550 | |||
| 551 | 2048 | static inline void rgtc2_block_internal(uint8_t *dst, ptrdiff_t stride, | |
| 552 | const uint8_t *block, int sign) | ||
| 553 | { | ||
| 554 | /* 4x4 block containing 4 component pixels. */ | ||
| 555 | uint8_t c0[4 * 4 * 4]; | ||
| 556 | uint8_t c1[4 * 4 * 4]; | ||
| 557 | int x, y; | ||
| 558 | |||
| 559 | /* Decompress the two channels separately and interleave them afterwards. */ | ||
| 560 | 2048 | rgtc1_block_internal(c0, 16, block, sign, 0, 0, 4); | |
| 561 | 2048 | rgtc1_block_internal(c1, 16, block + 8, sign, 0, 0, 4); | |
| 562 | |||
| 563 | /* B is rebuilt exactly like a normal map. */ | ||
| 564 |
2/2✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 2048 times.
|
10240 | for (y = 0; y < 4; y++) { |
| 565 |
2/2✓ Branch 0 taken 32768 times.
✓ Branch 1 taken 8192 times.
|
40960 | for (x = 0; x < 4; x++) { |
| 566 | 32768 | uint8_t *p = dst + x * 4 + y * stride; | |
| 567 | 32768 | int r = c0[x * 4 + y * 16]; | |
| 568 | 32768 | int g = c1[x * 4 + y * 16]; | |
| 569 | 32768 | int b = 127; | |
| 570 | |||
| 571 | 32768 | int d = (255 * 255 - r * r - g * g) / 2; | |
| 572 |
2/2✓ Branch 0 taken 26534 times.
✓ Branch 1 taken 6234 times.
|
32768 | if (d > 0) |
| 573 | 26534 | b = lrint(sqrtf(d)); | |
| 574 | |||
| 575 | 32768 | p[0] = r; | |
| 576 | 32768 | p[1] = g; | |
| 577 | 32768 | p[2] = b; | |
| 578 | 32768 | p[3] = 255; | |
| 579 | } | ||
| 580 | } | ||
| 581 | 2048 | } | |
| 582 | |||
| 583 | /** | ||
| 584 | * Decompress one block of a RGRC2 texture with signed components | ||
| 585 | * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. | ||
| 586 | * | ||
| 587 | * @param dst output buffer. | ||
| 588 | * @param stride scanline in bytes. | ||
| 589 | * @param block block to decompress. | ||
| 590 | * @return how much texture data has been consumed. | ||
| 591 | */ | ||
| 592 | 512 | static int rgtc2s_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 593 | { | ||
| 594 | 512 | rgtc2_block_internal(dst, stride, block, 1); | |
| 595 | |||
| 596 | 512 | return 16; | |
| 597 | } | ||
| 598 | |||
| 599 | /** | ||
| 600 | * Decompress one block of a RGRC2 texture with unsigned components | ||
| 601 | * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. | ||
| 602 | * | ||
| 603 | * @param dst output buffer. | ||
| 604 | * @param stride scanline in bytes. | ||
| 605 | * @param block block to decompress. | ||
| 606 | * @return how much texture data has been consumed. | ||
| 607 | */ | ||
| 608 | 512 | static int rgtc2u_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 609 | { | ||
| 610 | 512 | rgtc2_block_internal(dst, stride, block, 0); | |
| 611 | |||
| 612 | 512 | return 16; | |
| 613 | } | ||
| 614 | |||
| 615 | /** | ||
| 616 | * Decompress one block of a 3Dc texture with unsigned components | ||
| 617 | * and store the resulting RGBA pixels in 'dst'. Alpha is fully opaque. | ||
| 618 | * | ||
| 619 | * @param dst output buffer. | ||
| 620 | * @param stride scanline in bytes. | ||
| 621 | * @param block block to decompress. | ||
| 622 | * @return how much texture data has been consumed. | ||
| 623 | */ | ||
| 624 | 1024 | static int dxn3dc_block(uint8_t *dst, ptrdiff_t stride, const uint8_t *block) | |
| 625 | { | ||
| 626 | int x, y; | ||
| 627 | 1024 | rgtc2_block_internal(dst, stride, block, 0); | |
| 628 | |||
| 629 | /* This is the 3Dc variant of RGTC2, with swapped R and G. */ | ||
| 630 |
2/2✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 1024 times.
|
5120 | for (y = 0; y < 4; y++) { |
| 631 |
2/2✓ Branch 0 taken 16384 times.
✓ Branch 1 taken 4096 times.
|
20480 | for (x = 0; x < 4; x++) { |
| 632 | 16384 | uint8_t *p = dst + x * 4 + y * stride; | |
| 633 | 16384 | FFSWAP(uint8_t, p[0], p[1]); | |
| 634 | } | ||
| 635 | } | ||
| 636 | |||
| 637 | 1024 | return 16; | |
| 638 | } | ||
| 639 | |||
| 640 | 160 | av_cold void ff_texturedsp_init(TextureDSPContext *c) | |
| 641 | { | ||
| 642 | 160 | c->dxt1_block = dxt1_block; | |
| 643 | 160 | c->dxt1a_block = dxt1a_block; | |
| 644 | 160 | c->dxt2_block = dxt2_block; | |
| 645 | 160 | c->dxt3_block = dxt3_block; | |
| 646 | 160 | c->dxt4_block = dxt4_block; | |
| 647 | 160 | c->dxt5_block = dxt5_block; | |
| 648 | 160 | c->dxt5y_block = dxt5y_block; | |
| 649 | 160 | c->dxt5ys_block = dxt5ys_block; | |
| 650 | 160 | c->rgtc1s_block = rgtc1s_block; | |
| 651 | 160 | c->rgtc1u_block = rgtc1u_block; | |
| 652 | 160 | c->rgtc1u_gray_block = rgtc1u_gray_block; | |
| 653 | 160 | c->rgtc1u_alpha_block = rgtc1u_alpha_block; | |
| 654 | 160 | c->rgtc2s_block = rgtc2s_block; | |
| 655 | 160 | c->rgtc2u_block = rgtc2u_block; | |
| 656 | 160 | c->dxn3dc_block = dxn3dc_block; | |
| 657 | 160 | } | |
| 658 | |||
| 659 | #define TEXTUREDSP_FUNC_NAME ff_texturedsp_exec_decompress_threads | ||
| 660 | #define TEXTUREDSP_TEX_FUNC(a, b, c) tex_funct(a, b, c) | ||
| 661 | #include "texturedsp_template.c" | ||
| 662 |