Home | History | Annotate | Download | only in pixelflinger2
      1 /**
      2  **
      3  ** Copyright 2010, The Android Open Source Project
      4  **
      5  ** Licensed under the Apache License, Version 2.0 (the "License");
      6  ** you may not use this file except in compliance with the License.
      7  ** You may obtain a copy of the License at
      8  **
      9  **     http://www.apache.org/licenses/LICENSE-2.0
     10  **
     11  ** Unless required by applicable law or agreed to in writing, software
     12  ** distributed under the License is distributed on an "AS IS" BASIS,
     13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  ** See the License for the specific language governing permissions and
     15  ** limitations under the License.
     16  */
     17 
     18 #include "texture.h"
     19 
     20 #include <assert.h>
     21 #include <string.h>
     22 #include <math.h>
     23 
     24 #include "pixelflinger2.h"
     25 
     26 #if USE_LLVM_EXECUTIONENGINE
     27 #include <llvm/Module.h>
     28 #include <llvm/ExecutionEngine/JIT.h>
     29 #include <llvm/DerivedTypes.h>
     30 #endif
     31 
     32 #if !USE_LLVM_TEXTURE_SAMPLER
     33 
     34 const struct GGLContext * textureGGLContext;
     35 
     36 union Pixel { unsigned char channels[4]; unsigned int val; };
     37 
     38 static inline void PixelRGBAToVector4 (const Pixel *pixel, Vector4 * color)  __attribute__((always_inline));
     39 static inline void PixelRGBAToVector4 (const Pixel *pixel, Vector4 * color)
     40 {
     41 #if defined(__ARM_HAVE_NEON) && USE_NEON
     42     int32x4_t c;
     43     c = vsetq_lane_s32(pixel->channels[0], c, 0);
     44     c = vsetq_lane_s32(pixel->channels[1], c, 1);
     45     c = vsetq_lane_s32(pixel->channels[2], c, 2);
     46     c = vsetq_lane_s32(pixel->channels[3], c, 3);
     47     color->f4 = vcvtq_f32_s32(c);
     48     color->f4 = vmulq_n_f32(color->f4, 1 / 255.0f);
     49 #else
     50 	color->r = (float)pixel->channels[0] / 255;
     51 	color->g = (float)pixel->channels[1] / 255;
     52 	color->b = (float)pixel->channels[2] / 255;
     53 	color->a = (float)pixel->channels[3] / 255;
     54 #endif
     55 }
     56 
     57 static inline void RGBAToVector4(const unsigned int rgba, Vector4 * color)
     58 {
     59 	PixelRGBAToVector4((const Pixel *)&rgba, color);
     60 }
     61 
     62 static inline void Lerp(Vec4<int> * a, Vec4<int> * b, int x, Vec4<int> * d)
     63 {
     64     for (unsigned i = 0; i < 4; i++)
     65     {
     66         int r = b->i[i] - a->i[i], s = a->i[i];
     67         d->i[i] = (r * x >> 16) + s;
     68     }
     69 }
     70 
     71 static inline void ToIntVec(Vec4<int> * a)
     72 {
     73     a->u[3] = a->u[0] >> 24;
     74     a->u[2] = (a->u[0] >> 16) & 0xff;
     75     a->u[1] = (a->u[0] >> 8) & 0xff;
     76     a->u[0] &= 0xff;
     77 }
     78 
     79 template<GGLPixelFormat format>
     80 static void PointSample(unsigned sample[4], const unsigned * data, const unsigned index)
     81 {
     82     if (GGL_PIXEL_FORMAT_RGBA_8888 == format)
     83         *sample = *(data + index);
     84     else if (GGL_PIXEL_FORMAT_RGBX_8888 == format)
     85     {
     86         *sample = *(data + index);
     87         *sample |= 0xff000000;
     88     }
     89     else if (GGL_PIXEL_FORMAT_RGB_565 == format)
     90     {
     91         sample[0] = *((const unsigned short *)data + index);
     92         sample[1] = (sample[0] & 0x7e0) << 5;
     93         sample[2] = (sample[0] & 0xf800) << 8;
     94         sample[0] = (sample[0] & 0x1f) << 3;
     95 
     96         sample[0] |= sample[0] >> 5;
     97         sample[1] = (sample[1] | (sample[1] >> 6)) & 0xff00;
     98         sample[2] = (sample[2] | (sample[2] >> 5)) & 0xff0000;
     99 
    100         sample[0] |= sample[1];
    101         sample[0] |= sample[2];
    102         sample[0] |= 0xff000000;
    103     }
    104     else if (GGL_PIXEL_FORMAT_UNKNOWN == format)
    105         sample[0] = 0xff00ffff;
    106     else
    107         assert(0);
    108 }
    109 
    110 static unsigned texcoordWrap(const unsigned wrap, float r, const unsigned size,
    111                                     unsigned * lerp)
    112 {
    113     const unsigned shift = 16;
    114     unsigned odd = 0;
    115     int tc;
    116 
    117     tc = r * (1 << shift);
    118 
    119     odd = tc & (1 << shift);
    120     if (0 == wrap || 2 == wrap) // REPEAT or MIRRORED
    121         tc &= (1 << shift) - 1; // only take mantissa
    122     tc *= size - 1;
    123     // TODO DXL linear filtering needs to be fixed for texcoord outside of [0,1]
    124     *lerp = tc & ((1 << shift) - 1);
    125     tc >>= shift;
    126 
    127     if (0 == wrap) // GL_REPEAT
    128     { }
    129     else if (1 == wrap) // GL_CLAMP_TO_EDGE
    130         tc = MIN2(size - 1, MAX2(0, tc));
    131     else if (2 == wrap)
    132         tc = odd ? size - 1 - tc : tc;
    133     else
    134         assert(0);
    135     return tc;
    136 }
    137 
    138 template<GGLPixelFormat format, ChannelType output, unsigned minMag, unsigned wrapS, unsigned wrapT>
    139 static void tex2d(unsigned sample[4], const float tex_coord[4], const unsigned sampler)
    140 {
    141    const unsigned * data = (const unsigned *)textureGGLContext->textureState.textureData[sampler];
    142    const unsigned width = textureGGLContext->textureState.textureDimensions[sampler * 2];
    143 	const unsigned height = textureGGLContext->textureState.textureDimensions[sampler * 2 + 1];
    144     unsigned xLerp = 0, yLerp = 0;
    145     const unsigned x0 = texcoordWrap(wrapS, tex_coord[0], width, &xLerp);
    146     const unsigned y0 = texcoordWrap(wrapT, tex_coord[1], height, &yLerp);
    147 
    148     if (0 == minMag)
    149     {
    150         PointSample<format>(sample, data, y0 * width + x0);
    151         sample[1] = (sample[0] & 0xff00) >> 8;
    152         sample[2] = (sample[0] & 0xff0000) >> 16;
    153         sample[3] = (sample[0] & 0xff000000) >> 24;
    154         sample[0] &= 0xff;
    155     }
    156     else if (1 == minMag)
    157     {
    158         const unsigned x1 = MIN2(width - 1, x0 + 1), y1 = MIN2(height - 1, y0 + 1);
    159         Vec4<int> samples[4] = {0};
    160         PointSample<format>((unsigned *)(samples + 0), data, y0 * width + x0);
    161         ToIntVec(samples + 0);
    162         PointSample<format>((unsigned *)(samples + 1), data, y0 * width + x1);
    163         ToIntVec(samples + 1);
    164         PointSample<format>((unsigned *)(samples + 2), data, y1 * width + x1);
    165         ToIntVec(samples + 2);
    166         PointSample<format>((unsigned *)(samples + 3), data, y1 * width + x0);
    167         ToIntVec(samples + 3);
    168 
    169         Lerp(samples + 0, samples + 1, xLerp, samples + 0);
    170         Lerp(samples + 3, samples + 2, xLerp, samples + 3);
    171         Lerp(samples + 0, samples + 3, yLerp, (Vec4<int> *)sample);
    172     }
    173     else
    174         assert(0);
    175 
    176     if (Fixed0 == output) // i32 non vector
    177         sample[0] = (sample[3] << 24) | (sample[2] << 16) | (sample[1] << 8) | sample[0];
    178     else if (Fixed8 == output) // 4 x i32
    179         ; // do nothing
    180     else if (Fixed16 == output) // 4 x i32
    181     {
    182         sample[0] <<= 8; sample[1] <<= 8; sample[2] <<= 8; sample[3] <<= 8;
    183     }
    184     else if (Float == output) // 4 x float
    185     {
    186         float * fsample = (float *)sample;
    187         fsample[0] = sample[0] / 255.0f; fsample[1] = sample[1] / 255.0f;
    188         fsample[2] = sample[2] / 255.0f; fsample[3] = sample[3] / 255.0f;
    189     }
    190 }
    191 
    192 template<GGLPixelFormat format, ChannelType output, unsigned minMag, unsigned wrapS, unsigned wrapT>
    193 void texcube(unsigned sample[4], const float tex_coord[4], const unsigned sampler)
    194 {
    195     float mx = fabs(tex_coord[0]), my = fabs(tex_coord[1]), mz = fabs(tex_coord[2]);
    196     float s = 0, t = 0, ma = 0;
    197     unsigned face = 0;
    198     if (mx > my && mx > mz)
    199     {
    200         if (tex_coord[0] >= 0)
    201         {
    202             s = -tex_coord[2];
    203             t = -tex_coord[1];
    204             face = 0;
    205         }
    206         else
    207         {
    208             s = tex_coord[2];
    209             t = -tex_coord[1];
    210             face = 1;
    211         }
    212         ma = mx;
    213     }
    214     else if (my > mx && my > mz)
    215     {
    216         if (tex_coord[1] >= 0)
    217         {
    218             s = tex_coord[0];
    219             t = tex_coord[2];
    220             face = 2;
    221         }
    222         else
    223         {
    224             s = tex_coord[0];
    225             t = -tex_coord[2];
    226             face = 3;
    227         }
    228         ma = my;
    229     }
    230     else
    231     {
    232         if (tex_coord[2] >= 0)
    233         {
    234             s = tex_coord[0];
    235             t = -tex_coord[1];
    236             face = 4;
    237         }
    238         else
    239         {
    240             s = -tex_coord[0];
    241             t = -tex_coord[2];
    242             face = 5;
    243         }
    244         ma = mz;
    245     }
    246 
    247     s = (s / ma + 1) * 0.5f;
    248     t = (t / ma + 1) * 0.5f;
    249 
    250     const unsigned * data = (const unsigned *)textureGGLContext->textureState.textureData[sampler];
    251     const unsigned width = textureGGLContext->textureState.textureDimensions[sampler * 2];
    252 	const unsigned height = textureGGLContext->textureState.textureDimensions[sampler * 2 + 1];
    253     unsigned xLerp = 0, yLerp = 0;
    254     const unsigned x0 = texcoordWrap(wrapS, s, width, &xLerp);
    255     const unsigned y0 = texcoordWrap(wrapT, t, height, &yLerp);
    256 
    257     if (0 == minMag)
    258     {
    259         PointSample<format>(sample, data, y0 * width + x0);
    260         sample[1] = (sample[0] & 0xff00) >> 8;
    261         sample[2] = (sample[0] & 0xff0000) >> 16;
    262         sample[3] = (sample[0] & 0xff000000) >> 24;
    263         sample[0] &= 0xff;
    264     }
    265     else if (1 == minMag)
    266     {
    267         const unsigned x1 = MIN2(width - 1, x0 + 1), y1 = MIN2(height - 1, y0 + 1);
    268         Vec4<int> samples[4] = {0};
    269         PointSample<format>((unsigned *)(samples + 0), data, face * width * height + y0 * width + x0);
    270         ToIntVec(samples + 0);
    271         PointSample<format>((unsigned *)(samples + 1), data, face * width * height + y0 * width + x1);
    272         ToIntVec(samples + 1);
    273         PointSample<format>((unsigned *)(samples + 2), data, face * width * height + y1 * width + x1);
    274         ToIntVec(samples + 2);
    275         PointSample<format>((unsigned *)(samples + 3), data, face * width * height + y1 * width + x0);
    276         ToIntVec(samples + 3);
    277 
    278         Lerp(samples + 0, samples + 1, xLerp, samples + 0);
    279         Lerp(samples + 3, samples + 2, xLerp, samples + 3);
    280         Lerp(samples + 0, samples + 3, yLerp, (Vec4<int> *)sample);
    281     }
    282     else
    283         assert(0);
    284 
    285     if (Fixed0 == output) // i32 non vector
    286         sample[0] = (sample[3] << 24) | (sample[2] << 16) | (sample[1] << 8) | sample[0];
    287     else if (Fixed8 == output) // 4 x i32
    288         ; // do nothing
    289     else if (Fixed16 == output) // 4 x i32
    290     {
    291         sample[0] <<= 8; sample[1] <<= 8; sample[2] <<= 8; sample[3] <<= 8;
    292     }
    293     else if (Float == output) // 4 x float
    294     {
    295         float * fsample = (float *)sample;
    296         fsample[0] = sample[0] / 255.0f; fsample[1] = sample[1] / 255.0f;
    297         fsample[2] = sample[2] / 255.0f; fsample[3] = sample[3] / 255.0f;
    298     }
    299 
    300 }
    301 
    302 #define TEXTURE_FUNCTION_ENTRY(target,format,output,filter,wrapS,wrapT) \
    303 { #target"_"#format"_"#output"_"#filter"_"#wrapS"_"#wrapT, \
    304 target<GGL_PIXEL_FORMAT_##format, output, filter, wrapS, wrapT> },
    305 
    306 #define TEXTURE_FUNCTION_ENTRY_WRAPT(target,format,output,minMag,wrapS) \
    307 TEXTURE_FUNCTION_ENTRY(target,format,output,minMag,wrapS,0) \
    308 TEXTURE_FUNCTION_ENTRY(target,format,output,minMag,wrapS,1) \
    309 TEXTURE_FUNCTION_ENTRY(target,format,output,minMag,wrapS,2)
    310 
    311 #define TEXTURE_FUNCTION_ENTRY_WRAPS(target,format,output,minMag) \
    312 TEXTURE_FUNCTION_ENTRY_WRAPT(target,format,output,minMag,0) \
    313 TEXTURE_FUNCTION_ENTRY_WRAPT(target,format,output,minMag,1) \
    314 TEXTURE_FUNCTION_ENTRY_WRAPT(target,format,output,minMag,2)
    315 
    316 #define TEXTURE_FUNCTION_ENTRY_FILTER(target,format,output) \
    317 TEXTURE_FUNCTION_ENTRY_WRAPS(target,format,output,0) \
    318 TEXTURE_FUNCTION_ENTRY_WRAPS(target,format,output,1)
    319 
    320 #define TEXTURE_FUNCTION_ENTRY_OUTPUT(target,format) \
    321 TEXTURE_FUNCTION_ENTRY_FILTER(target,format,Float) \
    322 TEXTURE_FUNCTION_ENTRY_FILTER(target,format,Fixed16) \
    323 TEXTURE_FUNCTION_ENTRY_FILTER(target,format,Fixed8) \
    324 TEXTURE_FUNCTION_ENTRY_FILTER(target,format,Fixed0)
    325 
    326 #define TEXTURE_FUNCTION_ENTRY_FORMAT(target) \
    327 TEXTURE_FUNCTION_ENTRY_OUTPUT(target,RGBA_8888) \
    328 TEXTURE_FUNCTION_ENTRY_OUTPUT(target,RGBX_8888) \
    329 TEXTURE_FUNCTION_ENTRY_OUTPUT(target,RGB_565) \
    330 TEXTURE_FUNCTION_ENTRY_OUTPUT(target,UNKNOWN)
    331 
    332 #define TEXTURE_FUNCTION_ENTRIES \
    333 TEXTURE_FUNCTION_ENTRY_FORMAT(tex2d) \
    334 TEXTURE_FUNCTION_ENTRY_FORMAT(texcube)
    335 
    336 static struct TextureFunctionMapping
    337 {
    338     const char * name;
    339     void (* function)(unsigned sample[4], const float tex_coord[4], const unsigned int tex_id);
    340 } textureFunctionMapping [] = { TEXTURE_FUNCTION_ENTRIES };
    341 
    342 
    343 #undef TEXTURE_FUNCTION_ENTRY
    344 
    345 #endif //#if !USE_LLVM_TEXTURE_SAMPLER
    346 
    347 #if USE_LLVM_EXECUTIONENGINE && !USE_LLVM_TEXTURE_SAMPLER
    348 
    349 void DeclareTextureFunctions(llvm::Module * mod)
    350 {
    351 	llvm::LLVMContext & llvm_ctx = mod->getContext();
    352 
    353     std::vector<const llvm::Type*> funcArgs;
    354     llvm::VectorType *vectorType = llvm::VectorType::get(llvm::Type::getFloatTy(llvm_ctx), 4);
    355     llvm::PointerType * vectorPtr = llvm::PointerType::get(vectorType, 0);
    356 
    357     funcArgs.push_back(vectorPtr);
    358 	funcArgs.push_back(vectorPtr);
    359 	funcArgs.push_back(llvm::Type::getInt32Ty(llvm_ctx));
    360 	// void function(float[4], const float[4], unsigned)
    361 
    362     llvm::FunctionType *functionType = llvm::FunctionType::get(llvm::Type::getVoidTy(llvm_ctx),
    363                                                    funcArgs,
    364                                                    false);
    365 
    366     for (unsigned i = 0; i < sizeof(textureFunctionMapping) / sizeof(*textureFunctionMapping); i++)
    367     {
    368         llvm::Function * func = llvm::cast<llvm::Function>(
    369         mod->getOrInsertFunction(textureFunctionMapping[i].name, functionType));
    370         func->setLinkage(llvm::GlobalValue::ExternalLinkage);
    371         func->setCallingConv(llvm::CallingConv::C);
    372     }
    373 }
    374 
    375 void AddTextureFunctionMappings(llvm::Module * mod, llvm::ExecutionEngine * ee)
    376 {
    377     if (mod->getFunction("tex2d_soa"))
    378         assert(0);//ee->addGlobalMapping(func, (void *)tex2d_soa);
    379 
    380     for (unsigned i = 0; i < sizeof(textureFunctionMapping) / sizeof(*textureFunctionMapping); i++)
    381     {
    382         llvm::Function * function = mod->getFunction(textureFunctionMapping[i].name);
    383         if (function)
    384             ee->updateGlobalMapping(function, (void *)textureFunctionMapping[i].function);
    385     }
    386 }
    387 #endif // #if USE_LLVM_EXECUTIONENGINE && !USE_LLVM_TEXTURE_SAMPLER
    388 
    389 static void SetSampler(GGLInterface * iface, const unsigned sampler, GGLTexture * texture)
    390 {
    391     assert(GGL_MAXCOMBINEDTEXTUREIMAGEUNITS > sampler);
    392     GGL_GET_CONTEXT(ctx, iface);
    393     if (!texture)
    394         SetShaderVerifyFunctions(iface);
    395     else if (ctx->state.textureState.textures[sampler].format != texture->format)
    396         SetShaderVerifyFunctions(iface);
    397     else if (ctx->state.textureState.textures[sampler].wrapS != texture->wrapS)
    398         SetShaderVerifyFunctions(iface);
    399     else if (ctx->state.textureState.textures[sampler].wrapT != texture->wrapT)
    400         SetShaderVerifyFunctions(iface);
    401     else if (ctx->state.textureState.textures[sampler].minFilter != texture->minFilter)
    402         SetShaderVerifyFunctions(iface);
    403     else if (ctx->state.textureState.textures[sampler].magFilter != texture->magFilter)
    404         SetShaderVerifyFunctions(iface);
    405 
    406     if (texture)
    407     {
    408         ctx->state.textureState.textures[sampler] = *texture; // shallow copy, data pointed to must remain valid
    409         //ctx->state.textureState.textureData[sampler] = texture->levels[0];
    410         ctx->state.textureState.textureData[sampler] = texture->levels;
    411         ctx->state.textureState.textureDimensions[sampler * 2] = texture->width;
    412         ctx->state.textureState.textureDimensions[sampler * 2 + 1] = texture->height;
    413     }
    414     else
    415     {
    416         memset(ctx->state.textureState.textures + sampler, 0, sizeof(ctx->state.textureState.textures[sampler]));
    417         ctx->state.textureState.textureData[sampler] = NULL;
    418         ctx->state.textureState.textureDimensions[sampler * 2] = 0;
    419         ctx->state.textureState.textureDimensions[sampler * 2 + 1] = 0;
    420     }
    421 }
    422 
    423 void InitializeTextureFunctions(GGLInterface * iface)
    424 {
    425     iface->SetSampler = SetSampler;
    426 }