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