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.
7
// generatemip.inc: Defines the GenerateMip function, templated on the format
8
// type of the image for which mip levels are being generated.
10
#include "common/mathutil.h"
12
#include "image_util/imageformats.h"
21
static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
23
return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
27
static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
29
return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
33
static 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)
38
ASSERT(sourceWidth == 1);
39
ASSERT(sourceHeight > 1);
40
ASSERT(sourceDepth == 1);
42
for (size_t y = 0; y < destHeight; y++)
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);
48
T::average(dst, src0, src1);
53
static 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)
58
ASSERT(sourceWidth > 1);
59
ASSERT(sourceHeight == 1);
60
ASSERT(sourceDepth == 1);
62
for (size_t x = 0; x < destWidth; x++)
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);
68
T::average(dst, src0, src1);
73
static 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)
78
ASSERT(sourceWidth == 1);
79
ASSERT(sourceHeight == 1);
80
ASSERT(sourceDepth > 1);
82
for (size_t z = 0; z < destDepth; z++)
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);
88
T::average(dst, src0, src1);
93
static 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)
98
ASSERT(sourceWidth > 1);
99
ASSERT(sourceHeight > 1);
100
ASSERT(sourceDepth == 1);
102
for (size_t y = 0; y < destHeight; y++)
104
for (size_t x = 0; x < destWidth; x++)
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);
114
T::average(&tmp0, src0, src1);
115
T::average(&tmp1, src2, src3);
116
T::average(dst, &tmp0, &tmp1);
121
template <typename T>
122
static 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)
127
ASSERT(sourceWidth == 1);
128
ASSERT(sourceHeight > 1);
129
ASSERT(sourceDepth > 1);
131
for (size_t z = 0; z < destDepth; z++)
133
for (size_t y = 0; y < destHeight; y++)
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);
143
T::average(&tmp0, src0, src1);
144
T::average(&tmp1, src2, src3);
145
T::average(dst, &tmp0, &tmp1);
150
template <typename T>
151
static 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)
156
ASSERT(sourceWidth > 1);
157
ASSERT(sourceHeight == 1);
158
ASSERT(sourceDepth > 1);
160
for (size_t z = 0; z < destDepth; z++)
162
for (size_t x = 0; x < destWidth; x++)
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);
172
T::average(&tmp0, src0, src1);
173
T::average(&tmp1, src2, src3);
174
T::average(dst, &tmp0, &tmp1);
179
template <typename T>
180
static 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)
185
ASSERT(sourceWidth > 1);
186
ASSERT(sourceHeight > 1);
187
ASSERT(sourceDepth > 1);
189
for (size_t z = 0; z < destDepth; z++)
191
for (size_t y = 0; y < destHeight; y++)
193
for (size_t x = 0; x < destWidth; x++)
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);
205
T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
207
T::average(&tmp0, src0, src1);
208
T::average(&tmp1, src2, src3);
209
T::average(&tmp2, src4, src5);
210
T::average(&tmp3, src6, src7);
212
T::average(&tmp4, &tmp0, &tmp1);
213
T::average(&tmp5, &tmp2, &tmp3);
215
T::average(dst, &tmp4, &tmp5);
222
typedef 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);
227
template <typename T>
228
static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
230
uint8_t index = ((sourceWidth > 1) ? 1 : 0) |
231
((sourceHeight > 1) ? 2 : 0) |
232
((sourceDepth > 1) ? 4 : 0);
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
252
template <typename T>
253
inline 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)
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);
261
priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
262
ASSERT(generationFunction != nullptr);
264
generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
265
mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);