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