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