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