Hash :
2b132f42
Author :
Date :
2013-01-25T21:52:47
Implements generateMipmap for CPU-side textures TRAC #22350 Author: Shannon Woods Signed-off-by: Jamie Madill Signed-off-by: Daniel Koch git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1763 736b8ea6-26fd-11df-bfd4-992fa37f6226
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// generatemip.h: Defines the GenerateMip function, templated on the format
// type of the image for which mip levels are being generated.
#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_
#define LIBGLESV2_RENDERER_GENERATEMIP_H_
#include "libGLESv2/mathutil.h"
namespace rx
{
struct L8
{
unsigned char L;
static void average(L8 *dst, const L8 *src1, const L8 *src2)
{
dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L);
}
};
typedef L8 R8; // R8 type is functionally equivalent for mip purposes
typedef L8 A8; // A8 type is functionally equivalent for mip purposes
struct A8L8
{
unsigned char L;
unsigned char A;
static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
{
*(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
}
};
typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes
struct A8R8G8B8
{
unsigned char B;
unsigned char G;
unsigned char R;
unsigned char A;
static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
{
*(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
}
};
typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes
struct A16B16G16R16F
{
unsigned short R;
unsigned short G;
unsigned short B;
unsigned short A;
static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
{
dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f);
dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f);
}
};
struct R16F
{
unsigned short R;
static void average(R16F *dst, const R16F *src1, const R16F *src2)
{
dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
}
};
struct R16G16F
{
unsigned short R;
unsigned short G;
static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
{
dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
}
};
struct A32B32G32R32F
{
float R;
float G;
float B;
float A;
static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
{
dst->R = (src1->R + src2->R) * 0.5f;
dst->G = (src1->G + src2->G) * 0.5f;
dst->B = (src1->B + src2->B) * 0.5f;
dst->A = (src1->A + src2->A) * 0.5f;
}
};
struct R32F
{
float R;
static void average(R32F *dst, const R32F *src1, const R32F *src2)
{
dst->R = (src1->R + src2->R) * 0.5f;
}
};
struct R32G32F
{
float R;
float G;
static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
{
dst->R = (src1->R + src2->R) * 0.5f;
dst->G = (src1->G + src2->G) * 0.5f;
}
};
struct R32G32B32F
{
float R;
float G;
float B;
static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
{
dst->R = (src1->R + src2->R) * 0.5f;
dst->G = (src1->G + src2->G) * 0.5f;
dst->B = (src1->B + src2->B) * 0.5f;
}
};
template <typename T>
static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight,
const unsigned char *sourceData, int sourcePitch,
unsigned char *destData, int destPitch)
{
unsigned int mipWidth = std::max(1U, sourceWidth >> 1);
unsigned int mipHeight = std::max(1U, sourceHeight >> 1);
if (sourceHeight == 1)
{
ASSERT(sourceWidth != 1);
const T *src = (const T*)sourceData;
T *dst = (T*)destData;
for (unsigned int x = 0; x < mipWidth; x++)
{
T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]);
}
}
else if (sourceWidth == 1)
{
ASSERT(sourceHeight != 1);
for (unsigned int y = 0; y < mipHeight; y++)
{
const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
T *dst = (T*)(destData + y * destPitch);
T::average(dst, src0, src1);
}
}
else
{
for (unsigned int y = 0; y < mipHeight; y++)
{
const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch);
const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch);
T *dst = (T*)(destData + y * destPitch);
for (unsigned int x = 0; x < mipWidth; x++)
{
T tmp0;
T tmp1;
T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]);
T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]);
T::average(&dst[x], &tmp0, &tmp1);
}
}
}
}
}
#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_