Home | History | Annotate | Download | only in pixelflinger2
      1 /**
      2  **
      3  ** Copyright 2011, 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 <stack>
     19 
     20 #include "src/pixelflinger2/pixelflinger2.h"
     21 
     22 #include <llvm/IRBuilder.h>
     23 #include <llvm/Module.h>
     24 
     25 #include "src/pixelflinger2/llvm_helper.h"
     26 
     27 using namespace llvm;
     28 
     29 // texture data is int pointer to surface (will cast to short for 16bpp), index is linear texel index,
     30 // format is GGLPixelFormat for surface, return type is <4 x i32> rgba
     31 static Value * pointSample(IRBuilder<> & builder, Value * textureData, Value * index, const GGLPixelFormat format)
     32 {
     33    Value * texel = NULL;
     34    switch (format) {
     35    case GGL_PIXEL_FORMAT_RGBA_8888:
     36       textureData = builder.CreateGEP(textureData, index);
     37       texel = builder.CreateLoad(textureData, "texel");
     38       break;
     39    case GGL_PIXEL_FORMAT_RGBX_8888:
     40       textureData = builder.CreateGEP(textureData, index);
     41       texel = builder.CreateLoad(textureData, "texel");
     42       texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
     43       break;
     44    case GGL_PIXEL_FORMAT_RGB_565: {
     45       textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(), 0));
     46       textureData = builder.CreateGEP(textureData, index);
     47       texel = builder.CreateLoad(textureData, "texel565");
     48       texel = builder.CreateZExt(texel, Type::getInt32Ty(builder.getContext()));
     49 
     50       Value * b = builder.CreateAnd(texel, builder.getInt32(0x1f));
     51       b = builder.CreateShl(b, builder.getInt32(3));
     52       b = builder.CreateOr(b, builder.CreateLShr(b, builder.getInt32(5)));
     53 
     54       Value * g = builder.CreateAnd(texel, builder.getInt32(0x7e0));
     55       g = builder.CreateShl(g, builder.getInt32(5));
     56       g = builder.CreateOr(g, builder.CreateLShr(g, builder.getInt32(6)));
     57       g = builder.CreateAnd(g, builder.getInt32(0xff00));
     58 
     59       Value * r = builder.CreateAnd(texel, builder.getInt32(0xF800));
     60       r = builder.CreateShl(r, builder.getInt32(8));
     61       r = builder.CreateOr(r, builder.CreateLShr(r, builder.getInt32(5)));
     62       r = builder.CreateAnd(r, builder.getInt32(0xff0000));
     63 
     64       texel = builder.CreateOr(r, builder.CreateOr(g, b));
     65       texel = builder.CreateOr(texel, builder.getInt32(0xff000000), name("texel"));
     66       break;
     67    }
     68    case GGL_PIXEL_FORMAT_A_8: {
     69       textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
     70       textureData = builder.CreateGEP(textureData, index);
     71       texel = builder.CreateLoad(textureData, "texel_a8");
     72       texel = builder.CreateZExt(texel, builder.getInt32Ty());
     73       texel = builder.CreateShl(texel, builder.getInt32(24));
     74       break;
     75    }
     76    case GGL_PIXEL_FORMAT_L_8: {
     77       textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
     78       textureData = builder.CreateGEP(textureData, index);
     79       texel = builder.CreateLoad(textureData, "texel_l8");
     80       texel = builder.CreateZExt(texel, builder.getInt32Ty());
     81       texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
     82       texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
     83       texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
     84       break;
     85    }
     86    case GGL_PIXEL_FORMAT_LA_88: {
     87       textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(),0));
     88       textureData = builder.CreateGEP(textureData, index);
     89       texel = builder.CreateLoad(textureData, "texel_la8");
     90       texel = builder.CreateZExt(texel, builder.getInt32Ty());
     91       Value * alpha = builder.CreateAnd(texel, builder.getInt32(0xff00));
     92       texel = builder.CreateAnd(texel, builder.getInt32(0xff));
     93       texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
     94       texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
     95       texel = builder.CreateOr(texel, builder.CreateShl(alpha, 16));
     96       break;
     97    }
     98    case GGL_PIXEL_FORMAT_UNKNOWN: // usually means texture not set yet
     99       ALOGD("pf2: pointSample: unknown format, default to 0xffff00ff \n");
    100       texel = builder.getInt32(0xffff00ff);
    101       break;
    102    default:
    103       assert(0);
    104       break;
    105    }
    106    Value * channels = Constant::getNullValue(intVecType(builder));
    107 
    108 //   if (dstDesc && dstDesc->IsInt32Color()) {
    109 //      channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
    110 //      channels = builder.CreateBitCast(channels, floatVecType(builder));
    111 //      return channels;
    112 //   } else if (!dstDesc || dstDesc->IsVectorType()) {
    113    channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
    114    channels = builder.CreateInsertElement(channels, texel, builder.getInt32(1));
    115    channels = builder.CreateInsertElement(channels, texel, builder.getInt32(2));
    116    channels = builder.CreateInsertElement(channels, texel, builder.getInt32(3));
    117 //      if (dstDesc && dstDesc->IsVectorType(Fixed8)) {
    118 //         channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
    119 //         channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
    120 //         channels = builder.CreateBitCast(channels, floatVecType(builder));
    121 //      } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
    122 //         channels = builder.CreateShl(channels, constIntVec(builder, 8, 0, 0, 0));
    123 //         channels = builder.CreateLShr(channels, constIntVec(builder, 0, 0, 8, 16));
    124 //         channels = builder.CreateAnd(channels, constIntVec(builder, 0xff00, 0xff00, 0xff00, 0xff00));
    125 //         channels = builder.CreateBitCast(channels, floatVecType(builder));
    126 //      } else if (!dstDesc || dstDesc->IsVectorType(Float)) { // no analysis done in vertex shader, so use default float [0,1] output
    127    channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
    128    channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
    129 //   channels = builder.CreateUIToFP(channels, floatVecType(builder));
    130 //   channels = builder.CreateFMul(channels, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
    131 //                                 1 / 255.0f, 1 / 255.0f));
    132 //      } else
    133 //         assert(0);
    134 //   } else
    135 //      assert(0);
    136 
    137    return channels;
    138 }
    139 
    140 static const unsigned SHIFT = 16;
    141 
    142 // w  = width - 1, h = height - 1; similar to pointSample; returns <4 x i32> rgba
    143 static Value * linearSample(IRBuilder<> & builder, Value * textureData, Value * indexOffset,
    144                             Value * x0, Value * y0, Value * xLerp, Value * yLerp,
    145                             Value * w, Value * h,  Value * width, Value * height,
    146                             const GGLPixelFormat format/*, const RegDesc * dstDesc*/)
    147 {
    148    // TODO: linear filtering needs to be fixed for texcoord outside of [0,1]
    149    Value * x1 = builder.CreateAdd(x0, builder.getInt32(1));
    150    x1 = minIntScalar(builder, x1, w);
    151    Value * y1 = builder.CreateAdd(y0, builder.getInt32(1));
    152    y1 = minIntScalar(builder, y1, h);
    153 
    154 //   RegDesc regDesc;
    155 //   regDesc.SetVectorType(Fixed8);
    156 
    157    Value * index = builder.CreateMul(y0, width);
    158    index = builder.CreateAdd(index, x0);
    159    index = builder.CreateAdd(index, indexOffset);
    160    Value * s0 = pointSample(builder, textureData, index, format/*, &regDesc*/);
    161 //   s0 = builder.CreateBitCast(s0, intVecType(builder));
    162 
    163    index = builder.CreateMul(y0, width);
    164    index = builder.CreateAdd(index, x1);
    165    index = builder.CreateAdd(index, indexOffset);
    166    Value * s1 = pointSample(builder, textureData, index, format/*, &regDesc*/);
    167 //   s1 = builder.CreateBitCast(s1, intVecType(builder));
    168 
    169    index = builder.CreateMul(y1, width);
    170    index = builder.CreateAdd(index, x1);
    171    index = builder.CreateAdd(index, indexOffset);
    172    Value * s2 = pointSample(builder, textureData, index, format/*, &regDesc*/);
    173 //   s2 = builder.CreateBitCast(s2, intVecType(builder));
    174 
    175    index = builder.CreateMul(y1, width);
    176    index = builder.CreateAdd(index, x0);
    177    index = builder.CreateAdd(index, indexOffset);
    178    Value * s3 = pointSample(builder, textureData, index, format/*, &regDesc*/);
    179 //   s3 = builder.CreateBitCast(s3, intVecType(builder));
    180 
    181    Value * xLerpVec = intVec(builder, xLerp, xLerp, xLerp, xLerp);
    182 
    183    Value * h0 = builder.CreateMul(builder.CreateSub(s1, s0), xLerpVec);
    184    // arithmetic shift right, since it's the result of subtraction, which could be negative
    185    h0 = builder.CreateAShr(h0, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
    186    h0 = builder.CreateAdd(h0, s0);
    187 
    188    Value * h1 = builder.CreateMul(builder.CreateSub(s2, s3), xLerpVec);
    189    h1 = builder.CreateAShr(h1, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
    190    h1 = builder.CreateAdd(h1, s3);
    191 
    192    Value * sample = builder.CreateMul(builder.CreateSub(h1, h0),
    193                                       intVec(builder, yLerp, yLerp, yLerp, yLerp));
    194    sample = builder.CreateAShr(sample, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
    195    sample = builder.CreateAdd(sample, h0);
    196 
    197    return sample;
    198 //   if (!dstDesc || dstDesc->IsVectorType(Float)) {
    199 //      sample = builder.CreateUIToFP(sample, floatVecType(builder));
    200 //      return builder.CreateFMul(sample, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
    201 //                                1 / 255.0f, 1 / 255.0f));
    202 //   } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
    203 //      sample = builder.CreateShl(sample, constIntVec(builder, 8, 8, 8, 8));
    204 //      return builder.CreateBitCast(sample, floatVecType(builder));
    205 //   } else if (dstDesc && dstDesc->IsVectorType(Fixed8))
    206 //      return builder.CreateBitCast(sample, floatVecType(builder));
    207 //   else if (dstDesc && dstDesc->IsInt32Color()) {
    208 //      sample = builder.CreateShl(sample, constIntVec(builder, 0, 8, 16, 24));
    209 //      std::vector<llvm::Value*> samples = extractVector(sample);
    210 //      samples[0] = builder.CreateOr(samples[0], samples[1]);
    211 //      samples[0] = builder.CreateOr(samples[0], samples[2]);
    212 //      samples[0] = builder.CreateOr(samples[0], samples[3]);
    213 //      sample = builder.CreateInsertElement(sample, samples[0], builder.getInt32(0));
    214 //      return builder.CreateBitCast(sample, floatVecType(builder));
    215 //   } else
    216 //      assert(0);
    217 }
    218 
    219 // dim is size - 1, since [0.0f,1.0f]->[0, size - 1]
    220 static Value * texcoordWrap(IRBuilder<> & builder, const unsigned wrap,
    221                             /*const ChannelType type,*/ Value * r, Value * size, Value * dim,
    222                             Value ** texelLerp)
    223 {
    224    Type * intType = Type::getInt32Ty(builder.getContext());
    225    Value * tc = NULL;
    226    Value * odd = NULL;
    227 //   if (Float == type) {
    228    // convert float to fixed16 so that 16LSB are the remainder, and bit 16 is one
    229    // mantissa is the amount between two texels, used for linear interpolation
    230    tc = ConstantFP::get(builder.getContext(), APFloat(float(1 << SHIFT)));
    231    tc = builder.CreateFMul(tc, r);
    232    tc = builder.CreateFPToSI(tc, intType);
    233 //   } else if (Fixed16 == type) {
    234 //      assert(16 == SHIFT);
    235 //      tc = builder.CreateBitCast(r, Type::getInt32Ty(builder.getContext()));
    236 //   } else
    237 //      assert(0);
    238 
    239    odd = builder.CreateAnd(tc, builder.getInt32(1 << SHIFT), name("tc_odd"));
    240 
    241    if (0 == wrap || 2 == wrap) // just the mantissa for wrap and mirrored
    242       tc = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
    243 
    244    tc = builder.CreateMul(tc, dim);
    245 
    246    *texelLerp = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
    247 
    248    tc = builder.CreateLShr(tc, builder.getInt32(SHIFT));
    249 
    250    if (0 == wrap) // GL_REPEAT
    251    { } else if (1 == wrap) { // GL_CLAMP_TO_EDGE
    252       tc = maxIntScalar(builder, tc, builder.getInt32(0));
    253       tc = minIntScalar(builder, tc, dim);
    254    } else if (2 == wrap) { // GL_MIRRORER_REPEAT
    255       Value * tcPtr = builder.CreateAlloca(intType);
    256       builder.CreateStore(tc, tcPtr);
    257       odd = builder.CreateICmpNE(odd, builder.getInt32(0));
    258 
    259       CondBranch condBranch(builder);
    260       condBranch.ifCond(odd);
    261 
    262       tc = builder.CreateSub(dim, tc, name("tc_mirrored"));
    263       builder.CreateStore(tc, tcPtr);
    264 
    265       condBranch.endif();
    266 
    267       tc = builder.CreateLoad(tcPtr);
    268    } else
    269       assert(0);
    270 
    271    return tc;
    272 }
    273 
    274 Value * tex2D(IRBuilder<> & builder, Value * in1, const unsigned sampler,
    275               /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
    276               const GGLState * gglCtx)
    277 {
    278    Type * intType = builder.getInt32Ty();
    279    PointerType * intPointerType = PointerType::get(intType, 0);
    280 
    281    llvm::Module * module = builder.GetInsertBlock()->getParent()->getParent();
    282    std::vector<Value * > texcoords = extractVector(builder, in1);
    283 
    284    Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
    285    if (!textureDimensions)
    286       textureDimensions = new GlobalVariable(*module, intType, true,
    287                                              GlobalValue::ExternalLinkage,
    288                                              NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
    289    Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
    290                           sampler * 2);
    291    textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
    292    Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
    293                            sampler * 2 + 1);
    294    textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
    295    Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
    296    Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
    297 //   ChannelType sType = Float, tType = Float;
    298 //   if (in1Desc) {
    299 //      sType = in1Desc->channels[0];
    300 //      tType = in1Desc->channels[1];
    301 //   }
    302 
    303    Value * xLerp = NULL, * yLerp = NULL;
    304    Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
    305                             /*sType, */texcoords[0], textureWidth, textureW, &xLerp);
    306    Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
    307                             /*tType, */texcoords[1], textureHeight, textureH, &yLerp);
    308 
    309    Value * index = builder.CreateMul(y, textureWidth);
    310    index = builder.CreateAdd(index, x);
    311 
    312    Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
    313    if (!textureData)
    314       textureData = new GlobalVariable(*module, intPointerType,
    315                                        true, GlobalValue::ExternalLinkage,
    316                                        NULL, _PF2_TEXTURE_DATA_NAME_);
    317 
    318    textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
    319    textureData = builder.CreateLoad(textureData);
    320 
    321    if (0 == gglCtx->textureState.textures[sampler].minFilter &&
    322          0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
    323       Value * ret = pointSample(builder, textureData, index,
    324                                 gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
    325       return intColorVecToFloatColorVec(builder, ret);
    326    } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
    327               1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
    328       Value * ret = linearSample(builder, textureData, builder.getInt32(0), x, y, xLerp, yLerp,
    329                                  textureW, textureH,  textureWidth, textureHeight,
    330                                  gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
    331       return intColorVecToFloatColorVec(builder, ret);
    332    } else
    333       assert(!"unsupported texture filter");
    334    return NULL;
    335 }
    336 
    337 // only positive float; used in cube map since major axis is positive
    338 static Value * FCmpGT(IRBuilder<> & builder, Value * lhs, Value * rhs)
    339 {
    340    Type * const intType = Type::getInt32Ty(builder.getContext());
    341    lhs = builder.CreateBitCast(lhs, intType);
    342    rhs = builder.CreateBitCast(rhs, intType);
    343    return builder.CreateICmpUGT(lhs, rhs);
    344 }
    345 
    346 static Value * FPositive(IRBuilder<> & builder, Value * val)
    347 {
    348    // float cmp faster here
    349    return builder.CreateFCmpOGE(val, Constant::getNullValue(builder.getFloatTy()));
    350    //val = builder.CreateBitCast(val, Type::getInt32Ty(builder.getContext()));
    351    //return builder.CreateICmpSGE(val, storage->constantInt(0));
    352    //val = builder.CreateAnd(val, storage->constantInt(0x80000000));
    353    //return builder.CreateICmpNE(val, storage->constantInt(0));
    354 }
    355 
    356 static Value * Fabs(IRBuilder<> & builder, Value * val)
    357 {
    358    val = builder.CreateBitCast(val, builder.getInt32Ty());
    359    val = builder.CreateAnd(val, builder.getInt32(~0x80000000));
    360    return builder.CreateBitCast(val, builder.getFloatTy());
    361    //return builder.CreateICmpSGE(val, storage->constantInt(0));
    362 }
    363 
    364 Value * texCube(IRBuilder<> & builder, Value * in1, const unsigned sampler,
    365                 /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
    366                 const GGLState * gglCtx)
    367 {
    368 //   if (in1Desc) // the major axis determination code is only float for now
    369 //      assert(in1Desc->IsVectorType(Float));
    370 
    371    Type * const intType = builder.getInt32Ty();
    372    PointerType * const intPointerType = PointerType::get(intType, 0);
    373    Type * const floatType = builder.getFloatTy();
    374 
    375    Constant * const float1 = constFloat(builder, 1.0f);
    376    Constant * const float0_5 = constFloat(builder, 0.5f);
    377 
    378    Module * module = builder.GetInsertBlock()->getParent()->getParent();
    379    std::vector<Value * > texcoords = extractVector(builder, in1);
    380 
    381    Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
    382    if (!textureDimensions)
    383       textureDimensions = new GlobalVariable(*module, intType, true,
    384                                              GlobalValue::ExternalLinkage,
    385                                              NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
    386    Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
    387                           sampler * 2);
    388    textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
    389    Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
    390                            sampler * 2 + 1);
    391    textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
    392    Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
    393    Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
    394 
    395    Value * mx = Fabs(builder, texcoords[0]), * my = Fabs(builder, texcoords[1]);
    396    Value * mz = Fabs(builder, texcoords[2]);
    397    Value * sPtr = builder.CreateAlloca(floatType);
    398    Value * tPtr = builder.CreateAlloca(floatType);
    399    Value * maPtr = builder.CreateAlloca(floatType);
    400    Value * facePtr = builder.CreateAlloca(intType);
    401 
    402    Value * mxGmyCmp = FCmpGT(builder, mx, my);
    403    Value * mxGmzCmp = FCmpGT(builder, mx, mz);
    404 
    405    CondBranch condBranch(builder);
    406    condBranch.ifCond(builder.CreateAnd(mxGmyCmp, mxGmzCmp)); // if (mx > my && mx > mz)
    407 //   m_storage->setCurrentBlock(currentBlock(), false);
    408    {
    409       condBranch.ifCond(FPositive(builder, texcoords[0]));
    410 //      m_storage->setCurrentBlock(currentBlock(), false);
    411       {
    412          builder.CreateStore(builder.CreateFNeg(texcoords[2]), sPtr);
    413          builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
    414          builder.CreateStore(builder.getInt32(0), facePtr);
    415       }
    416       condBranch.elseop();
    417 //      m_storage->setCurrentBlock(currentBlock(), false);
    418       {
    419          builder.CreateStore((texcoords[2]), sPtr);
    420          builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
    421          builder.CreateStore(builder.getInt32(1), facePtr);
    422       }
    423       condBranch.endif(); // end if (x >= 0)
    424 //      m_storage->setCurrentBlock(currentBlock(), false);
    425 
    426       builder.CreateStore(mx, maPtr);
    427    }
    428    condBranch.elseop(); // !(mx > my && mx > mz)
    429 //   m_storage->setCurrentBlock(currentBlock(), false);
    430    {
    431       Value * myGmxCmp = FCmpGT(builder, my, mx);
    432       Value * myGmzCmp = FCmpGT(builder, my, mz);
    433       condBranch.ifCond(builder.CreateAnd(myGmxCmp, myGmzCmp)); // my > mx && my > mz
    434 //      m_storage->setCurrentBlock(currentBlock(), false);
    435       {
    436          condBranch.ifCond(FPositive(builder, texcoords[1]));
    437 //         m_storage->setCurrentBlock(currentBlock(), false);
    438          {
    439             builder.CreateStore((texcoords[0]), sPtr);
    440             builder.CreateStore((texcoords[2]), tPtr);
    441             builder.CreateStore(builder.getInt32(2), facePtr);
    442          }
    443          condBranch.elseop();
    444 //         m_storage->setCurrentBlock(currentBlock(), false);
    445          {
    446             builder.CreateStore(texcoords[0], sPtr);
    447             builder.CreateStore(builder.CreateFNeg(texcoords[2]), tPtr);
    448             builder.CreateStore(builder.getInt32(3), facePtr);
    449          }
    450          condBranch.endif();
    451 //         m_storage->setCurrentBlock(currentBlock(), false);
    452 
    453          builder.CreateStore(my, maPtr);
    454       }
    455       condBranch.elseop(); // !(my > mx && my > mz)
    456 //      m_storage->setCurrentBlock(currentBlock(), false);
    457       {
    458          //ifCond(builder.CreateFCmpOGE(texcoords[2], float0, name("zPositive")));
    459          condBranch.ifCond(FPositive(builder, texcoords[2]));
    460 //         m_storage->setCurrentBlock(currentBlock(), false);
    461          {
    462             builder.CreateStore((texcoords[0]), sPtr);
    463             builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
    464             builder.CreateStore(builder.getInt32(4), facePtr);
    465          }
    466          condBranch.elseop();
    467 //        m_storage->setCurrentBlock(currentBlock(), false);
    468          {
    469             builder.CreateStore(builder.CreateFNeg(texcoords[0]), sPtr);
    470             builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
    471             builder.CreateStore(builder.getInt32(5), facePtr);
    472          }
    473          condBranch.endif(); // end if (x >= 0)
    474 //         m_storage->setCurrentBlock(currentBlock(), false);
    475 
    476          builder.CreateStore(mz, maPtr);
    477       }
    478       condBranch.endif();
    479 //      m_storage->setCurrentBlock(currentBlock(), false);
    480    }
    481    condBranch.endif();
    482 //   m_storage->setCurrentBlock(currentBlock(), false);
    483 
    484 
    485    Value * s = builder.CreateLoad(sPtr);
    486    Value * t = builder.CreateLoad(tPtr);
    487    Value * ma = builder.CreateLoad(maPtr);
    488    Value * face = builder.CreateLoad(facePtr);
    489 
    490    s = builder.CreateFDiv(s, ma);
    491    s = builder.CreateFAdd(s, float1);
    492    s = builder.CreateFMul(s, float0_5);
    493 
    494    t = builder.CreateFDiv(t, ma);
    495    t = builder.CreateFAdd(t, float1);
    496    t = builder.CreateFMul(t, float0_5);
    497 
    498 //   ChannelType sType = Float, tType = Float;
    499    Value * xLerp = NULL, * yLerp = NULL;
    500    Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
    501                             /*sType, */s, textureWidth, textureW, &xLerp);
    502    Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
    503                             /*tType, */t, textureHeight, textureH, &yLerp);
    504    Value * indexOffset = builder.CreateMul(builder.CreateMul(textureHeight, textureWidth), face);
    505    Value * index = builder.CreateAdd(builder.CreateMul(y, textureWidth), x);
    506 
    507    Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
    508    if (!textureData)
    509       textureData = new GlobalVariable(*module, intPointerType,
    510                                        true, GlobalValue::ExternalLinkage,
    511                                        NULL, _PF2_TEXTURE_DATA_NAME_);
    512 
    513    textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
    514    textureData = builder.CreateLoad(textureData);
    515 
    516    if (0 == gglCtx->textureState.textures[sampler].minFilter &&
    517          0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
    518       textureData = pointSample(builder, textureData, builder.CreateAdd(indexOffset, index),
    519                                 gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
    520       return intColorVecToFloatColorVec(builder, textureData);
    521 
    522    } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
    523               1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
    524       textureData = linearSample(builder, textureData, indexOffset, x, y, xLerp, yLerp,
    525                                  textureW, textureH,  textureWidth, textureHeight,
    526                                  gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
    527       return intColorVecToFloatColorVec(builder, textureData);
    528    } else
    529       assert(!"unsupported texture filter");
    530    return NULL;
    531 }
    532