1 // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "ASTC_Decoder.hpp"
16
17 #include "System/Math.hpp"
18
19 #ifdef SWIFTSHADER_ENABLE_ASTC
20 # include "astc_codec_internals.h"
21 #endif
22
23 #include <memory>
24 #include <unordered_map>
25
26 namespace {
27
28 #ifdef SWIFTSHADER_ENABLE_ASTC
write_imageblock(unsigned char * img,const imageblock * pb,int xsize,int ysize,int zsize,int bytes,int destPitchB,int destSliceB,bool isUnsignedByte,int xdim,int ydim,int zdim,int xpos,int ypos,int zpos)29 void write_imageblock(unsigned char *img,
30 // picture-block to initialize with image data. We assume that orig_data is valid
31 const imageblock *pb,
32 // output dimensions
33 int xsize, int ysize, int zsize,
34 // output format
35 int bytes, int destPitchB, int destSliceB, bool isUnsignedByte,
36 // block dimensions
37 int xdim, int ydim, int zdim,
38 // position to write the block to
39 int xpos, int ypos, int zpos)
40 {
41 const float *fptr = pb->orig_data;
42 const uint8_t *nptr = pb->nan_texel;
43
44 for(int z = 0; z < zdim; z++)
45 {
46 for(int y = 0; y < ydim; y++)
47 {
48 for(int x = 0; x < xdim; x++)
49 {
50 int xi = xpos + x;
51 int yi = ypos + y;
52 int zi = zpos + z;
53
54 if(xi >= 0 && yi >= 0 && zi >= 0 && xi < xsize && yi < ysize && zi < zsize)
55 {
56 unsigned char *pix = &img[zi * destSliceB + yi * destPitchB + xi * bytes];
57
58 if(isUnsignedByte)
59 {
60 if(*nptr)
61 {
62 // NaN-pixel, but we can't display it. Display purple instead.
63 pix[0] = 0xFF;
64 pix[1] = 0x00;
65 pix[2] = 0xFF;
66 pix[3] = 0xFF;
67 }
68 else
69 {
70 pix[0] = static_cast<unsigned char>(sw::clamp(fptr[0], 0.0f, 1.0f) * 255.0f + 0.5f);
71 pix[1] = static_cast<unsigned char>(sw::clamp(fptr[1], 0.0f, 1.0f) * 255.0f + 0.5f);
72 pix[2] = static_cast<unsigned char>(sw::clamp(fptr[2], 0.0f, 1.0f) * 255.0f + 0.5f);
73 pix[3] = static_cast<unsigned char>(sw::clamp(fptr[3], 0.0f, 1.0f) * 255.0f + 0.5f);
74 }
75 }
76 else
77 {
78 if(*nptr)
79 {
80 unsigned int *pixu = reinterpret_cast<unsigned int *>(pix);
81 pixu[0] = pixu[1] = pixu[2] = pixu[3] = 0x7FFFFFFF; // QNaN
82 }
83 else
84 {
85 float *pixf = reinterpret_cast<float *>(pix);
86 pixf[0] = fptr[0];
87 pixf[1] = fptr[1];
88 pixf[2] = fptr[2];
89 pixf[3] = fptr[3];
90 }
91 }
92 }
93 fptr += 4;
94 nptr++;
95 }
96 }
97 }
98 }
99 #endif
100
101 } // namespace
102
Decode(const unsigned char * source,unsigned char * dest,int destWidth,int destHeight,int destDepth,int bytes,int destPitchB,int destSliceB,int xBlockSize,int yBlockSize,int zBlockSize,int xblocks,int yblocks,int zblocks,bool isUnsignedByte)103 void ASTC_Decoder::Decode(const unsigned char *source, unsigned char *dest,
104 int destWidth, int destHeight, int destDepth,
105 int bytes, int destPitchB, int destSliceB,
106 int xBlockSize, int yBlockSize, int zBlockSize,
107 int xblocks, int yblocks, int zblocks, bool isUnsignedByte)
108 {
109 #ifdef SWIFTSHADER_ENABLE_ASTC
110 build_quantization_mode_table();
111
112 astc_decode_mode decode_mode = isUnsignedByte ? DECODE_LDR : DECODE_HDR;
113
114 std::unique_ptr<block_size_descriptor> bsd(new block_size_descriptor);
115 init_block_size_descriptor(xBlockSize, yBlockSize, zBlockSize, bsd.get());
116
117 std::unique_ptr<imageblock> ib(new imageblock);
118 std::unique_ptr<symbolic_compressed_block> scb(new symbolic_compressed_block);
119 for(int z = 0; z < zblocks; z++)
120 {
121 for(int y = 0; y < yblocks; y++)
122 {
123 for(int x = 0; x < xblocks; x++, source += 16)
124 {
125 physical_to_symbolic(bsd.get(), *(physical_compressed_block *)source, scb.get());
126 decompress_symbolic_block(decode_mode, bsd.get(), x * xBlockSize, y * yBlockSize, z * zBlockSize, scb.get(), ib.get());
127 write_imageblock(dest, ib.get(), destWidth, destHeight, destDepth, bytes, destPitchB, destSliceB, isUnsignedByte,
128 xBlockSize, yBlockSize, zBlockSize, x * xBlockSize, y * yBlockSize, z * zBlockSize);
129 }
130 }
131 }
132
133 term_block_size_descriptor(bsd.get());
134 #endif
135 }
136