• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2// Copyright 2015 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// generatemip.inc: Defines the GenerateMip function, templated on the format
8// type of the image for which mip levels are being generated.
9
10#include "common/mathutil.h"
11
12#include "image_util/imageformats.h"
13
14namespace angle
15{
16
17namespace priv
18{
19
20template <typename T>
21static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
22{
23    return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
24}
25
26template <typename T>
27static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
28{
29    return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
30}
31
32template <typename T>
33static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
34                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
35                          size_t destWidth, size_t destHeight, size_t destDepth,
36                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
37{
38    ASSERT(sourceWidth == 1);
39    ASSERT(sourceHeight > 1);
40    ASSERT(sourceDepth == 1);
41
42    for (size_t y = 0; y < destHeight; y++)
43    {
44        const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch);
45        const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
46        T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch);
47
48        T::average(dst, src0, src1);
49    }
50}
51
52template <typename T>
53static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
54                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
55                          size_t destWidth, size_t destHeight, size_t destDepth,
56                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
57{
58    ASSERT(sourceWidth > 1);
59    ASSERT(sourceHeight == 1);
60    ASSERT(sourceDepth == 1);
61
62    for (size_t x = 0; x < destWidth; x++)
63    {
64        const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch);
65        const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch);
66        T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch);
67
68        T::average(dst, src0, src1);
69    }
70}
71
72template <typename T>
73static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
74                          const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
75                          size_t destWidth, size_t destHeight, size_t destDepth,
76                          uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
77{
78    ASSERT(sourceWidth == 1);
79    ASSERT(sourceHeight == 1);
80    ASSERT(sourceDepth > 1);
81
82    for (size_t z = 0; z < destDepth; z++)
83    {
84        const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch);
85        const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
86        T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch);
87
88        T::average(dst, src0, src1);
89    }
90}
91
92template <typename T>
93static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
94                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
95                           size_t destWidth, size_t destHeight, size_t destDepth,
96                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
97{
98    ASSERT(sourceWidth > 1);
99    ASSERT(sourceHeight > 1);
100    ASSERT(sourceDepth == 1);
101
102    for (size_t y = 0; y < destHeight; y++)
103    {
104        for (size_t x = 0; x < destWidth; x++)
105        {
106            const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch);
107            const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
108            const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch);
109            const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
110            T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch);
111
112            T tmp0, tmp1;
113
114            T::average(&tmp0, src0, src1);
115            T::average(&tmp1, src2, src3);
116            T::average(dst, &tmp0, &tmp1);
117        }
118    }
119}
120
121template <typename T>
122static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
123                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
124                           size_t destWidth, size_t destHeight, size_t destDepth,
125                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
126{
127    ASSERT(sourceWidth == 1);
128    ASSERT(sourceHeight > 1);
129    ASSERT(sourceDepth > 1);
130
131    for (size_t z = 0; z < destDepth; z++)
132    {
133        for (size_t y = 0; y < destHeight; y++)
134        {
135            const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
136            const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
137            const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
138            const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
139            T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch);
140
141            T tmp0, tmp1;
142
143            T::average(&tmp0, src0, src1);
144            T::average(&tmp1, src2, src3);
145            T::average(dst, &tmp0, &tmp1);
146        }
147    }
148}
149
150template <typename T>
151static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
152                           const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
153                           size_t destWidth, size_t destHeight, size_t destDepth,
154                           uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
155{
156    ASSERT(sourceWidth > 1);
157    ASSERT(sourceHeight == 1);
158    ASSERT(sourceDepth > 1);
159
160    for (size_t z = 0; z < destDepth; z++)
161    {
162        for (size_t x = 0; x < destWidth; x++)
163        {
164            const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch);
165            const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
166            const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch);
167            const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
168            T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch);
169
170            T tmp0, tmp1;
171
172            T::average(&tmp0, src0, src1);
173            T::average(&tmp1, src2, src3);
174            T::average(dst, &tmp0, &tmp1);
175        }
176    }
177}
178
179template <typename T>
180static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
181                            const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
182                            size_t destWidth, size_t destHeight, size_t destDepth,
183                            uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
184{
185    ASSERT(sourceWidth > 1);
186    ASSERT(sourceHeight > 1);
187    ASSERT(sourceDepth > 1);
188
189    for (size_t z = 0; z < destDepth; z++)
190    {
191        for (size_t y = 0; y < destHeight; y++)
192        {
193            for (size_t x = 0; x < destWidth; x++)
194            {
195                const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
196                const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
197                const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
198                const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
199                const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
200                const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
201                const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
202                const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
203                T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch);
204
205                T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
206
207                T::average(&tmp0, src0, src1);
208                T::average(&tmp1, src2, src3);
209                T::average(&tmp2, src4, src5);
210                T::average(&tmp3, src6, src7);
211
212                T::average(&tmp4, &tmp0, &tmp1);
213                T::average(&tmp5, &tmp2, &tmp3);
214
215                T::average(dst, &tmp4, &tmp5);
216            }
217        }
218    }
219}
220
221
222typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
223                                      const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
224                                      size_t destWidth, size_t destHeight, size_t destDepth,
225                                      uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
226
227template <typename T>
228static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
229{
230    uint8_t index = ((sourceWidth > 1)  ? 1 : 0) |
231                    ((sourceHeight > 1) ? 2 : 0) |
232                    ((sourceDepth > 1)  ? 4 : 0);
233
234    switch (index)
235    {
236      case 0: return nullptr;
237      case 1: return GenerateMip_X<T>;   // W x 1 x 1
238      case 2: return GenerateMip_Y<T>;   // 1 x H x 1
239      case 3: return GenerateMip_XY<T>;  // W x H x 1
240      case 4: return GenerateMip_Z<T>;   // 1 x 1 x D
241      case 5: return GenerateMip_XZ<T>;  // W x 1 x D
242      case 6: return GenerateMip_YZ<T>;  // 1 x H x D
243      case 7: return GenerateMip_XYZ<T>; // W x H x D
244    }
245
246    UNREACHABLE();
247    return nullptr;
248}
249
250}  // namespace priv
251
252template <typename T>
253inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
254                        const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
255                        uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
256{
257    size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1);
258    size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1);
259    size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1);
260
261    priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
262    ASSERT(generationFunction != nullptr);
263
264    generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
265                       mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);
266}
267
268}  // namespace angle
269