• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2// Copyright 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "common/mathutil.h"
8
9#include <string.h>
10
11namespace angle
12{
13
14namespace priv
15{
16
17template <typename T>
18inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
19{
20    return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch));
21}
22
23template <typename T>
24inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
25{
26    return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch));
27}
28
29}  // namespace priv
30
31template <typename type, size_t componentCount>
32inline void LoadToNative(const ImageLoadContext &context, size_t width, size_t height, size_t depth,
33                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
34                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
35{
36    const size_t rowSize = width * sizeof(type) * componentCount;
37    const size_t layerSize = rowSize * height;
38    const size_t imageSize = layerSize * depth;
39
40    if (layerSize == inputDepthPitch && layerSize == outputDepthPitch)
41    {
42        ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch);
43        memcpy(output, input, imageSize);
44    }
45    else if (rowSize == inputRowPitch && rowSize == outputRowPitch)
46    {
47        for (size_t z = 0; z < depth; z++)
48        {
49            const type *source = priv::OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch);
50            type *dest = priv::OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch);
51
52            memcpy(dest, source, layerSize);
53        }
54    }
55    else
56    {
57        for (size_t z = 0; z < depth; z++)
58        {
59            for (size_t y = 0; y < height; y++)
60            {
61                const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
62                type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
63                memcpy(dest, source, width * sizeof(type) * componentCount);
64            }
65        }
66    }
67}
68
69template <typename type, uint32_t fourthComponentBits>
70inline void LoadToNative3To4(const ImageLoadContext &context, size_t width, size_t height,
71                             size_t depth, const uint8_t *input, size_t inputRowPitch,
72                             size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch,
73                             size_t outputDepthPitch)
74{
75    const type fourthValue = gl::bitCast<type>(fourthComponentBits);
76
77    for (size_t z = 0; z < depth; z++)
78    {
79        for (size_t y = 0; y < height; y++)
80        {
81            const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
82            type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
83            for (size_t x = 0; x < width; x++)
84            {
85                memcpy(&dest[x * 4], &source[x * 3], sizeof(type) * 3);
86                dest[x * 4 + 3] = fourthValue;
87            }
88        }
89    }
90}
91
92template <size_t componentCount>
93inline void Load32FTo16F(const ImageLoadContext &context, size_t width, size_t height, size_t depth,
94                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
95                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
96{
97    const size_t elementWidth = componentCount * width;
98
99    for (size_t z = 0; z < depth; z++)
100    {
101        for (size_t y = 0; y < height; y++)
102        {
103            const float *source = priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
104            uint16_t *dest = priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
105
106            for (size_t x = 0; x < elementWidth; x++)
107            {
108                dest[x] = gl::float32ToFloat16(source[x]);
109            }
110        }
111    }
112}
113
114template <typename type,
115          size_t inputComponentCount,
116          size_t outputComponentCount,
117          bool normalized>
118inline void LoadToFloat(const ImageLoadContext &context, size_t width, size_t height, size_t depth,
119                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
120                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) {
121    typedef std::numeric_limits<type> NL;
122
123    for (size_t z = 0; z < depth; z++)
124    {
125        for (size_t y = 0; y < height; y++)
126        {
127            const type *source_line = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
128            float *dest_line = priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
129
130            for (size_t x = 0; x < width; x++)
131            {
132                const type *source_pixel = source_line + x * inputComponentCount;
133                float *dest_pixel = dest_line + x * outputComponentCount;
134
135                for (size_t i = 0; i < inputComponentCount; i++)
136                {
137                    float result = 0;
138                    if (normalized)
139                    {
140                        if (NL::is_signed)
141                        {
142                            result = static_cast<float>(source_pixel[i]) / static_cast<float>(NL::max());
143                            result = result >= -1.0f ? result : -1.0f;
144                        }
145                        else
146                        {
147                            result = static_cast<float>(source_pixel[i]) / static_cast<float>(NL::max());
148                        }
149                    }
150                    else
151                    {
152                        result = static_cast<float>(source_pixel[i]);
153                    }
154                    dest_pixel[i] = result;
155                }
156
157                for (size_t j = inputComponentCount; j < outputComponentCount; j++)
158                {
159                    dest_pixel[j] = j == 3 ? 1.0f : 0.0f;
160                }
161            }
162        }
163    }
164}
165
166template <size_t blockWidth, size_t blockHeight, size_t blockDepth, size_t blockSize>
167inline void LoadCompressedToNative(const ImageLoadContext &context, size_t width, size_t height,
168                                   size_t depth, const uint8_t *input, size_t inputRowPitch,
169                                   size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch,
170                                   size_t outputDepthPitch)
171{
172    const size_t columns = (width + (blockWidth - 1)) / blockWidth;
173    const size_t rows = (height + (blockHeight - 1)) / blockHeight;
174    const size_t layers = (depth + (blockDepth - 1)) / blockDepth;
175
176    for (size_t z = 0; z < layers; ++z)
177    {
178        for (size_t y = 0; y < rows; ++y)
179        {
180            const uint8_t *source = priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
181            uint8_t *dest = priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
182            memcpy(dest, source, columns * blockSize);
183        }
184    }
185}
186
187template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
188inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
189                                     uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
190{
191    type writeValues[4] =
192    {
193        gl::bitCast<type>(firstBits),
194        gl::bitCast<type>(secondBits),
195        gl::bitCast<type>(thirdBits),
196        gl::bitCast<type>(fourthBits),
197    };
198
199    for (size_t z = 0; z < depth; z++)
200    {
201        for (size_t y = 0; y < height; y++)
202        {
203            type *destRow = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
204            for (size_t x = 0; x < width; x++)
205            {
206                type* destPixel = destRow + x * 4;
207
208                // This could potentially be optimized by generating an entire row of initialization
209                // data and copying row by row instead of pixel by pixel.
210                memcpy(destPixel, writeValues, sizeof(type) * 4);
211            }
212        }
213    }
214}
215
216template <size_t blockWidth, size_t blockHeight>
217inline void LoadASTCToRGBA8(const ImageLoadContext &context,
218                            size_t width,
219                            size_t height,
220                            size_t depth,
221                            const uint8_t *input,
222                            size_t inputRowPitch,
223                            size_t inputDepthPitch,
224                            uint8_t *output,
225                            size_t outputRowPitch,
226                            size_t outputDepthPitch)
227{
228    LoadASTCToRGBA8Inner(context, width, height, depth, blockWidth, blockHeight, input, inputRowPitch,
229                         inputDepthPitch, output, outputRowPitch, outputDepthPitch);
230}
231
232template <uint32_t indexBits, uint32_t redBlueBits, uint32_t greenBits, uint32_t alphaBits>
233inline void LoadPalettedToRGBA8(const ImageLoadContext &context,
234                                size_t width,
235                                size_t height,
236                                size_t depth,
237                                const uint8_t *input,
238                                size_t inputRowPitch,
239                                size_t inputDepthPitch,
240                                uint8_t *output,
241                                size_t outputRowPitch,
242                                size_t outputDepthPitch)
243{
244    static_assert(indexBits == 4 || indexBits == 8);
245    static_assert(redBlueBits == 4 || redBlueBits == 5 || redBlueBits == 8);
246    static_assert(greenBits == 4 || greenBits == 5 || greenBits == 6 || greenBits == 8);
247    static_assert(alphaBits == 0 || alphaBits == 1 || alphaBits == 4 || alphaBits == 8);
248    constexpr uint32_t colorBits = 2 * redBlueBits + greenBits + alphaBits;
249    static_assert(colorBits == 16 || colorBits == 24 || colorBits == 32);
250
251    LoadPalettedToRGBA8Impl(context, width, height, depth,
252                            indexBits, redBlueBits, greenBits, alphaBits,
253                            input, inputRowPitch, inputDepthPitch,
254                            output, outputRowPitch, outputDepthPitch);
255}
256
257// Temporary overload functions; need to have no-context overloads of the following functions used
258// by Chromium.  A Chromium change will switch to the with-context overloads, and then these can be
259// removed.
260inline void LoadEACR11ToR8(size_t width,
261                           size_t height,
262                           size_t depth,
263                           const uint8_t *input,
264                           size_t inputRowPitch,
265                           size_t inputDepthPitch,
266                           uint8_t *output,
267                           size_t outputRowPitch,
268                           size_t outputDepthPitch)
269{
270    LoadEACR11ToR8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
271                   outputRowPitch, outputDepthPitch);
272}
273
274inline void LoadEACR11SToR8(size_t width,
275                            size_t height,
276                            size_t depth,
277                            const uint8_t *input,
278                            size_t inputRowPitch,
279                            size_t inputDepthPitch,
280                            uint8_t *output,
281                            size_t outputRowPitch,
282                            size_t outputDepthPitch)
283{
284    LoadEACR11SToR8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
285                    outputRowPitch, outputDepthPitch);
286}
287
288inline void LoadEACRG11ToRG8(size_t width,
289                             size_t height,
290                             size_t depth,
291                             const uint8_t *input,
292                             size_t inputRowPitch,
293                             size_t inputDepthPitch,
294                             uint8_t *output,
295                             size_t outputRowPitch,
296                             size_t outputDepthPitch)
297{
298    LoadEACRG11ToRG8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
299                     outputRowPitch, outputDepthPitch);
300}
301
302inline void LoadEACRG11SToRG8(size_t width,
303                              size_t height,
304                              size_t depth,
305                              const uint8_t *input,
306                              size_t inputRowPitch,
307                              size_t inputDepthPitch,
308                              uint8_t *output,
309                              size_t outputRowPitch,
310                              size_t outputDepthPitch)
311{
312    LoadEACRG11SToRG8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
313                      outputRowPitch, outputDepthPitch);
314}
315
316inline void LoadETC2RGB8ToRGBA8(size_t width,
317                                size_t height,
318                                size_t depth,
319                                const uint8_t *input,
320                                size_t inputRowPitch,
321                                size_t inputDepthPitch,
322                                uint8_t *output,
323                                size_t outputRowPitch,
324                                size_t outputDepthPitch)
325{
326    LoadETC2RGB8ToRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
327                        outputRowPitch, outputDepthPitch);
328}
329
330inline void LoadETC2SRGB8ToRGBA8(size_t width,
331                                 size_t height,
332                                 size_t depth,
333                                 const uint8_t *input,
334                                 size_t inputRowPitch,
335                                 size_t inputDepthPitch,
336                                 uint8_t *output,
337                                 size_t outputRowPitch,
338                                 size_t outputDepthPitch)
339{
340    LoadETC2SRGB8ToRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
341                         outputRowPitch, outputDepthPitch);
342}
343
344inline void LoadETC2RGBA8ToRGBA8(size_t width,
345                                 size_t height,
346                                 size_t depth,
347                                 const uint8_t *input,
348                                 size_t inputRowPitch,
349                                 size_t inputDepthPitch,
350                                 uint8_t *output,
351                                 size_t outputRowPitch,
352                                 size_t outputDepthPitch)
353{
354    LoadETC2RGBA8ToRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
355                         outputRowPitch, outputDepthPitch);
356}
357
358inline void LoadETC2RGB8A1ToRGBA8(size_t width,
359                                  size_t height,
360                                  size_t depth,
361                                  const uint8_t *input,
362                                  size_t inputRowPitch,
363                                  size_t inputDepthPitch,
364                                  uint8_t *output,
365                                  size_t outputRowPitch,
366                                  size_t outputDepthPitch)
367{
368    LoadETC2RGB8A1ToRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
369                          outputRowPitch, outputDepthPitch);
370}
371
372inline void LoadETC2SRGBA8ToSRGBA8(size_t width,
373                                   size_t height,
374                                   size_t depth,
375                                   const uint8_t *input,
376                                   size_t inputRowPitch,
377                                   size_t inputDepthPitch,
378                                   uint8_t *output,
379                                   size_t outputRowPitch,
380                                   size_t outputDepthPitch)
381{
382    LoadETC2SRGBA8ToSRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
383                           outputRowPitch, outputDepthPitch);
384}
385
386inline void LoadETC2SRGB8A1ToRGBA8(size_t width,
387                                   size_t height,
388                                   size_t depth,
389                                   const uint8_t *input,
390                                   size_t inputRowPitch,
391                                   size_t inputDepthPitch,
392                                   uint8_t *output,
393                                   size_t outputRowPitch,
394                                   size_t outputDepthPitch)
395{
396    LoadETC2SRGB8A1ToRGBA8({}, width, height, depth, input, inputRowPitch, inputDepthPitch, output,
397                           outputRowPitch, outputDepthPitch);
398}
399
400} // namespace angle
401