101e6ff90560d588418e706ce4d2a16d5a15520e5David Li/**
23225321119408735f16b72b539c9fb7d80683552David Li **
33225321119408735f16b72b539c9fb7d80683552David Li ** Copyright 2011, The Android Open Source Project
43225321119408735f16b72b539c9fb7d80683552David Li **
501e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** Licensed under the Apache License, Version 2.0 (the "License");
601e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** you may not use this file except in compliance with the License.
701e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** You may obtain a copy of the License at
83225321119408735f16b72b539c9fb7d80683552David Li **
901e6ff90560d588418e706ce4d2a16d5a15520e5David Li **     http://www.apache.org/licenses/LICENSE-2.0
103225321119408735f16b72b539c9fb7d80683552David Li **
1101e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** Unless required by applicable law or agreed to in writing, software
1201e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** distributed under the License is distributed on an "AS IS" BASIS,
1301e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1401e6ff90560d588418e706ce4d2a16d5a15520e5David Li ** See the License for the specific language governing permissions and
153225321119408735f16b72b539c9fb7d80683552David Li ** limitations under the License.
163225321119408735f16b72b539c9fb7d80683552David Li */
1701e6ff90560d588418e706ce4d2a16d5a15520e5David Li
1813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li#include <stack>
1913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
2013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li#include "src/pixelflinger2/pixelflinger2.h"
2113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
22359cceccdd5673460cf06d1b80b70c80f887b0ddShih-wei Liao#include <llvm/IRBuilder.h>
2313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li#include <llvm/Module.h>
2413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
253225321119408735f16b72b539c9fb7d80683552David Li#include "src/pixelflinger2/llvm_helper.h"
2613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
273225321119408735f16b72b539c9fb7d80683552David Liusing namespace llvm;
2813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
2913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li// texture data is int pointer to surface (will cast to short for 16bpp), index is linear texel index,
3013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li// format is GGLPixelFormat for surface, return type is <4 x i32> rgba
313225321119408735f16b72b539c9fb7d80683552David Listatic Value * pointSample(IRBuilder<> & builder, Value * textureData, Value * index, const GGLPixelFormat format)
3213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
3313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * texel = NULL;
3413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   switch (format) {
3513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   case GGL_PIXEL_FORMAT_RGBA_8888:
3613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = builder.CreateGEP(textureData, index);
3713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateLoad(textureData, "texel");
3813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      break;
3913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   case GGL_PIXEL_FORMAT_RGBX_8888:
4013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = builder.CreateGEP(textureData, index);
4113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateLoad(textureData, "texel");
4213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
4313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      break;
4413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   case GGL_PIXEL_FORMAT_RGB_565: {
4501e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(), 0));
4613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = builder.CreateGEP(textureData, index);
4713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateLoad(textureData, "texel565");
4813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateZExt(texel, Type::getInt32Ty(builder.getContext()));
4913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
5001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      Value * b = builder.CreateAnd(texel, builder.getInt32(0x1f));
5101e6ff90560d588418e706ce4d2a16d5a15520e5David Li      b = builder.CreateShl(b, builder.getInt32(3));
5201e6ff90560d588418e706ce4d2a16d5a15520e5David Li      b = builder.CreateOr(b, builder.CreateLShr(b, builder.getInt32(5)));
5313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
5413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * g = builder.CreateAnd(texel, builder.getInt32(0x7e0));
5513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      g = builder.CreateShl(g, builder.getInt32(5));
5613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      g = builder.CreateOr(g, builder.CreateLShr(g, builder.getInt32(6)));
5713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      g = builder.CreateAnd(g, builder.getInt32(0xff00));
5813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
5901e6ff90560d588418e706ce4d2a16d5a15520e5David Li      Value * r = builder.CreateAnd(texel, builder.getInt32(0xF800));
6001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      r = builder.CreateShl(r, builder.getInt32(8));
6101e6ff90560d588418e706ce4d2a16d5a15520e5David Li      r = builder.CreateOr(r, builder.CreateLShr(r, builder.getInt32(5)));
6201e6ff90560d588418e706ce4d2a16d5a15520e5David Li      r = builder.CreateAnd(r, builder.getInt32(0xff0000));
6313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
6413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateOr(r, builder.CreateOr(g, b));
6513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      texel = builder.CreateOr(texel, builder.getInt32(0xff000000), name("texel"));
6613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      break;
6713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   }
6801e6ff90560d588418e706ce4d2a16d5a15520e5David Li   case GGL_PIXEL_FORMAT_A_8: {
6901e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
7001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateGEP(textureData, index);
7101e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateLoad(textureData, "texel_a8");
7201e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateZExt(texel, builder.getInt32Ty());
7301e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateShl(texel, builder.getInt32(24));
7401e6ff90560d588418e706ce4d2a16d5a15520e5David Li      break;
7501e6ff90560d588418e706ce4d2a16d5a15520e5David Li   }
7601e6ff90560d588418e706ce4d2a16d5a15520e5David Li   case GGL_PIXEL_FORMAT_L_8: {
7701e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
7801e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateGEP(textureData, index);
7901e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateLoad(textureData, "texel_l8");
8001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateZExt(texel, builder.getInt32Ty());
8101e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
8201e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
8301e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
8401e6ff90560d588418e706ce4d2a16d5a15520e5David Li      break;
8501e6ff90560d588418e706ce4d2a16d5a15520e5David Li   }
8601e6ff90560d588418e706ce4d2a16d5a15520e5David Li   case GGL_PIXEL_FORMAT_LA_88: {
8701e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(),0));
8801e6ff90560d588418e706ce4d2a16d5a15520e5David Li      textureData = builder.CreateGEP(textureData, index);
8901e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateLoad(textureData, "texel_la8");
9001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateZExt(texel, builder.getInt32Ty());
9101e6ff90560d588418e706ce4d2a16d5a15520e5David Li      Value * alpha = builder.CreateAnd(texel, builder.getInt32(0xff00));
9201e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateAnd(texel, builder.getInt32(0xff));
9301e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
9401e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
9501e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.CreateOr(texel, builder.CreateShl(alpha, 16));
9601e6ff90560d588418e706ce4d2a16d5a15520e5David Li      break;
9701e6ff90560d588418e706ce4d2a16d5a15520e5David Li   }
9813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   case GGL_PIXEL_FORMAT_UNKNOWN: // usually means texture not set yet
99a5ca04aebd1a0df7c52e170252cf3c2f3ee3e8a2Steve Block      ALOGD("pf2: pointSample: unknown format, default to 0xffff00ff \n");
10001e6ff90560d588418e706ce4d2a16d5a15520e5David Li      texel = builder.getInt32(0xffff00ff);
10113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      break;
10213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   default:
10313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      assert(0);
10413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      break;
10513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   }
10613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * channels = Constant::getNullValue(intVecType(builder));
10713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
10813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   if (dstDesc && dstDesc->IsInt32Color()) {
10913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
11013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      channels = builder.CreateBitCast(channels, floatVecType(builder));
11113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      return channels;
11213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else if (!dstDesc || dstDesc->IsVectorType()) {
11301e6ff90560d588418e706ce4d2a16d5a15520e5David Li   channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
11401e6ff90560d588418e706ce4d2a16d5a15520e5David Li   channels = builder.CreateInsertElement(channels, texel, builder.getInt32(1));
11501e6ff90560d588418e706ce4d2a16d5a15520e5David Li   channels = builder.CreateInsertElement(channels, texel, builder.getInt32(2));
11601e6ff90560d588418e706ce4d2a16d5a15520e5David Li   channels = builder.CreateInsertElement(channels, texel, builder.getInt32(3));
11713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      if (dstDesc && dstDesc->IsVectorType(Fixed8)) {
11813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
11913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
12013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateBitCast(channels, floatVecType(builder));
12113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
12213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateShl(channels, constIntVec(builder, 8, 0, 0, 0));
12313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateLShr(channels, constIntVec(builder, 0, 0, 8, 16));
12413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateAnd(channels, constIntVec(builder, 0xff00, 0xff00, 0xff00, 0xff00));
12513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         channels = builder.CreateBitCast(channels, floatVecType(builder));
12613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      } else if (!dstDesc || dstDesc->IsVectorType(Float)) { // no analysis done in vertex shader, so use default float [0,1] output
12713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
12813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
12913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   channels = builder.CreateUIToFP(channels, floatVecType(builder));
13013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   channels = builder.CreateFMul(channels, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
13113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//                                 1 / 255.0f, 1 / 255.0f));
13213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      } else
13313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         assert(0);
13413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else
13513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      assert(0);
13613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
13713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return channels;
13813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
13913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
14013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Listatic const unsigned SHIFT = 16;
14113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
14213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li// w  = width - 1, h = height - 1; similar to pointSample; returns <4 x i32> rgba
1433225321119408735f16b72b539c9fb7d80683552David Listatic Value * linearSample(IRBuilder<> & builder, Value * textureData, Value * indexOffset,
14401e6ff90560d588418e706ce4d2a16d5a15520e5David Li                            Value * x0, Value * y0, Value * xLerp, Value * yLerp,
14501e6ff90560d588418e706ce4d2a16d5a15520e5David Li                            Value * w, Value * h,  Value * width, Value * height,
14601e6ff90560d588418e706ce4d2a16d5a15520e5David Li                            const GGLPixelFormat format/*, const RegDesc * dstDesc*/)
14713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
14813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   // TODO: linear filtering needs to be fixed for texcoord outside of [0,1]
14913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * x1 = builder.CreateAdd(x0, builder.getInt32(1));
15013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   x1 = minIntScalar(builder, x1, w);
15113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * y1 = builder.CreateAdd(y0, builder.getInt32(1));
15213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   y1 = minIntScalar(builder, y1, h);
15313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
15413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   RegDesc regDesc;
15513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   regDesc.SetVectorType(Fixed8);
15613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
15713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * index = builder.CreateMul(y0, width);
15813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, x0);
15913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, indexOffset);
16013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * s0 = pointSample(builder, textureData, index, format/*, &regDesc*/);
16113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   s0 = builder.CreateBitCast(s0, intVecType(builder));
16213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
16313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateMul(y0, width);
16413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, x1);
16513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, indexOffset);
16613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * s1 = pointSample(builder, textureData, index, format/*, &regDesc*/);
16713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   s1 = builder.CreateBitCast(s1, intVecType(builder));
16813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
16913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateMul(y1, width);
17013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, x1);
17113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, indexOffset);
17213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * s2 = pointSample(builder, textureData, index, format/*, &regDesc*/);
17313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   s2 = builder.CreateBitCast(s2, intVecType(builder));
17413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
17513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateMul(y1, width);
17613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, x0);
17713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, indexOffset);
17813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * s3 = pointSample(builder, textureData, index, format/*, &regDesc*/);
17913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   s3 = builder.CreateBitCast(s3, intVecType(builder));
18013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
18113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * xLerpVec = intVec(builder, xLerp, xLerp, xLerp, xLerp);
18213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
18313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * h0 = builder.CreateMul(builder.CreateSub(s1, s0), xLerpVec);
18413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   // arithmetic shift right, since it's the result of subtraction, which could be negative
18513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   h0 = builder.CreateAShr(h0, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
18613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   h0 = builder.CreateAdd(h0, s0);
18713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
18813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * h1 = builder.CreateMul(builder.CreateSub(s2, s3), xLerpVec);
18913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   h1 = builder.CreateAShr(h1, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
19013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   h1 = builder.CreateAdd(h1, s3);
19113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
19213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * sample = builder.CreateMul(builder.CreateSub(h1, h0),
19313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                      intVec(builder, yLerp, yLerp, yLerp, yLerp));
19413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   sample = builder.CreateAShr(sample, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
19513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   sample = builder.CreateAdd(sample, h0);
19613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
19713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return sample;
19813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   if (!dstDesc || dstDesc->IsVectorType(Float)) {
19913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      sample = builder.CreateUIToFP(sample, floatVecType(builder));
20013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      return builder.CreateFMul(sample, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
20113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//                                1 / 255.0f, 1 / 255.0f));
20213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
20313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      sample = builder.CreateShl(sample, constIntVec(builder, 8, 8, 8, 8));
20413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      return builder.CreateBitCast(sample, floatVecType(builder));
20513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else if (dstDesc && dstDesc->IsVectorType(Fixed8))
20613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      return builder.CreateBitCast(sample, floatVecType(builder));
20713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   else if (dstDesc && dstDesc->IsInt32Color()) {
20813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      sample = builder.CreateShl(sample, constIntVec(builder, 0, 8, 16, 24));
20913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      std::vector<llvm::Value*> samples = extractVector(sample);
21013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      samples[0] = builder.CreateOr(samples[0], samples[1]);
21113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      samples[0] = builder.CreateOr(samples[0], samples[2]);
21213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      samples[0] = builder.CreateOr(samples[0], samples[3]);
21313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      sample = builder.CreateInsertElement(sample, samples[0], builder.getInt32(0));
21413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      return builder.CreateBitCast(sample, floatVecType(builder));
21513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else
21613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      assert(0);
21713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
21813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
21913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li// dim is size - 1, since [0.0f,1.0f]->[0, size - 1]
22013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Listatic Value * texcoordWrap(IRBuilder<> & builder, const unsigned wrap,
22113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            /*const ChannelType type,*/ Value * r, Value * size, Value * dim,
22213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            Value ** texelLerp)
22313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
224ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   Type * intType = Type::getInt32Ty(builder.getContext());
22513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * tc = NULL;
22613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * odd = NULL;
22713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   if (Float == type) {
22813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   // convert float to fixed16 so that 16LSB are the remainder, and bit 16 is one
22913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   // mantissa is the amount between two texels, used for linear interpolation
23013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   tc = ConstantFP::get(builder.getContext(), APFloat(float(1 << SHIFT)));
23113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   tc = builder.CreateFMul(tc, r);
23213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   tc = builder.CreateFPToSI(tc, intType);
23313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else if (Fixed16 == type) {
23413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      assert(16 == SHIFT);
23513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      tc = builder.CreateBitCast(r, Type::getInt32Ty(builder.getContext()));
23613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   } else
23713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      assert(0);
23813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
23913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   odd = builder.CreateAnd(tc, builder.getInt32(1 << SHIFT), name("tc_odd"));
24013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
24113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (0 == wrap || 2 == wrap) // just the mantissa for wrap and mirrored
24213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      tc = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
24313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
24413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   tc = builder.CreateMul(tc, dim);
24513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
24613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   *texelLerp = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
24713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
24813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   tc = builder.CreateLShr(tc, builder.getInt32(SHIFT));
24913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
25013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (0 == wrap) // GL_REPEAT
25113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   { } else if (1 == wrap) { // GL_CLAMP_TO_EDGE
25213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      tc = maxIntScalar(builder, tc, builder.getInt32(0));
25313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      tc = minIntScalar(builder, tc, dim);
25413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else if (2 == wrap) { // GL_MIRRORER_REPEAT
25513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * tcPtr = builder.CreateAlloca(intType);
25613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      builder.CreateStore(tc, tcPtr);
25713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      odd = builder.CreateICmpNE(odd, builder.getInt32(0));
25813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
25913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      CondBranch condBranch(builder);
26013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.ifCond(odd);
26113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
26213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      tc = builder.CreateSub(dim, tc, name("tc_mirrored"));
26313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      builder.CreateStore(tc, tcPtr);
26413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
26513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.endif();
26613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
26713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      tc = builder.CreateLoad(tcPtr);
26813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else
26913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      assert(0);
27013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
27113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return tc;
27213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
27313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
27413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid LiValue * tex2D(IRBuilder<> & builder, Value * in1, const unsigned sampler,
27513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li              /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
2762ac1cf8a62bcf080b70eaa7c0e4f57d4e8001685David Li              const GGLState * gglCtx)
27713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
278ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   Type * intType = builder.getInt32Ty();
279ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   PointerType * intPointerType = PointerType::get(intType, 0);
28013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
28113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   llvm::Module * module = builder.GetInsertBlock()->getParent()->getParent();
28213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   std::vector<Value * > texcoords = extractVector(builder, in1);
28313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
28413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
28513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (!textureDimensions)
28613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureDimensions = new GlobalVariable(*module, intType, true,
28713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                             GlobalValue::ExternalLinkage,
28813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                             NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
28913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
29013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                          sampler * 2);
29113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
29213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
29313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                           sampler * 2 + 1);
29413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
29513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
29613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
29713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   ChannelType sType = Float, tType = Float;
29813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   if (in1Desc) {
29913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      sType = in1Desc->channels[0];
30013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      tType = in1Desc->channels[1];
30113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   }
30213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
30313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * xLerp = NULL, * yLerp = NULL;
30413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
30513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            /*sType, */texcoords[0], textureWidth, textureW, &xLerp);
30613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
30713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            /*tType, */texcoords[1], textureHeight, textureH, &yLerp);
30813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
30913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * index = builder.CreateMul(y, textureWidth);
31013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   index = builder.CreateAdd(index, x);
31113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
31213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
31313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (!textureData)
31413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = new GlobalVariable(*module, intPointerType,
31513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                       true, GlobalValue::ExternalLinkage,
31613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                       NULL, _PF2_TEXTURE_DATA_NAME_);
31713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
31813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
31913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureData = builder.CreateLoad(textureData);
32013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
32113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (0 == gglCtx->textureState.textures[sampler].minFilter &&
32213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
32313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * ret = pointSample(builder, textureData, index,
32413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
32513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      return intColorVecToFloatColorVec(builder, ret);
32613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
32713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li              1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
32813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * ret = linearSample(builder, textureData, builder.getInt32(0), x, y, xLerp, yLerp,
32913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                 textureW, textureH,  textureWidth, textureHeight,
33013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                 gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
33113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      return intColorVecToFloatColorVec(builder, ret);
33213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else
33313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      assert(!"unsupported texture filter");
33413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return NULL;
33513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
33613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
33713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li// only positive float; used in cube map since major axis is positive
33813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Listatic Value * FCmpGT(IRBuilder<> & builder, Value * lhs, Value * rhs)
33913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
340ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   Type * const intType = Type::getInt32Ty(builder.getContext());
34113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   lhs = builder.CreateBitCast(lhs, intType);
34213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   rhs = builder.CreateBitCast(rhs, intType);
34313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return builder.CreateICmpUGT(lhs, rhs);
34413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
34513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
34613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Listatic Value * FPositive(IRBuilder<> & builder, Value * val)
34713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
34813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   // float cmp faster here
34913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return builder.CreateFCmpOGE(val, Constant::getNullValue(builder.getFloatTy()));
35013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   //val = builder.CreateBitCast(val, Type::getInt32Ty(builder.getContext()));
35113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   //return builder.CreateICmpSGE(val, storage->constantInt(0));
35213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   //val = builder.CreateAnd(val, storage->constantInt(0x80000000));
35313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   //return builder.CreateICmpNE(val, storage->constantInt(0));
35413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
35513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
35613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Listatic Value * Fabs(IRBuilder<> & builder, Value * val)
35713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
35813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   val = builder.CreateBitCast(val, builder.getInt32Ty());
35913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   val = builder.CreateAnd(val, builder.getInt32(~0x80000000));
36013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return builder.CreateBitCast(val, builder.getFloatTy());
36113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   //return builder.CreateICmpSGE(val, storage->constantInt(0));
36213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
36313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
36413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid LiValue * texCube(IRBuilder<> & builder, Value * in1, const unsigned sampler,
36513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
3662ac1cf8a62bcf080b70eaa7c0e4f57d4e8001685David Li                const GGLState * gglCtx)
36713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li{
36813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   if (in1Desc) // the major axis determination code is only float for now
36913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      assert(in1Desc->IsVectorType(Float));
37013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
371ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   Type * const intType = builder.getInt32Ty();
372ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   PointerType * const intPointerType = PointerType::get(intType, 0);
373ae0c16b29d641afaff99ac106eff87fea72a23e6Logan Chien   Type * const floatType = builder.getFloatTy();
37413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
37513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Constant * const float1 = constFloat(builder, 1.0f);
37613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Constant * const float0_5 = constFloat(builder, 0.5f);
37713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
37813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Module * module = builder.GetInsertBlock()->getParent()->getParent();
37913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   std::vector<Value * > texcoords = extractVector(builder, in1);
38013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
38136ffccf19c02a54a6dc9952dc9c181d4fda2a020David Li   Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
38213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (!textureDimensions)
38313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureDimensions = new GlobalVariable(*module, intType, true,
38413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                             GlobalValue::ExternalLinkage,
38536ffccf19c02a54a6dc9952dc9c181d4fda2a020David Li                                             NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
38613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
38713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                          sampler * 2);
38813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
38913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
39013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                           sampler * 2 + 1);
39113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
39213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
39313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
39413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
39513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * mx = Fabs(builder, texcoords[0]), * my = Fabs(builder, texcoords[1]);
39613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * mz = Fabs(builder, texcoords[2]);
39713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * sPtr = builder.CreateAlloca(floatType);
39813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * tPtr = builder.CreateAlloca(floatType);
39913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * maPtr = builder.CreateAlloca(floatType);
40013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * facePtr = builder.CreateAlloca(intType);
40113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
40213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * mxGmyCmp = FCmpGT(builder, mx, my);
40313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * mxGmzCmp = FCmpGT(builder, mx, mz);
40413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
40513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   CondBranch condBranch(builder);
40613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   condBranch.ifCond(builder.CreateAnd(mxGmyCmp, mxGmzCmp)); // if (mx > my && mx > mz)
40713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   m_storage->setCurrentBlock(currentBlock(), false);
40813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   {
40913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.ifCond(FPositive(builder, texcoords[0]));
41013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
41113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      {
41213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(builder.CreateFNeg(texcoords[2]), sPtr);
41313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
41413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(builder.getInt32(0), facePtr);
41513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      }
41613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.elseop();
41713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
41813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      {
41913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore((texcoords[2]), sPtr);
42013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
42113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(builder.getInt32(1), facePtr);
42213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      }
42313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.endif(); // end if (x >= 0)
42413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
42513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
42613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      builder.CreateStore(mx, maPtr);
42713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   }
42813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   condBranch.elseop(); // !(mx > my && mx > mz)
42913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   m_storage->setCurrentBlock(currentBlock(), false);
43013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   {
43113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * myGmxCmp = FCmpGT(builder, my, mx);
43213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      Value * myGmzCmp = FCmpGT(builder, my, mz);
43313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.ifCond(builder.CreateAnd(myGmxCmp, myGmzCmp)); // my > mx && my > mz
43413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
43513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      {
43613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.ifCond(FPositive(builder, texcoords[1]));
43713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         m_storage->setCurrentBlock(currentBlock(), false);
43813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         {
43913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore((texcoords[0]), sPtr);
44013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore((texcoords[2]), tPtr);
44113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.getInt32(2), facePtr);
44213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         }
44313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.elseop();
44413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         m_storage->setCurrentBlock(currentBlock(), false);
44513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         {
44613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(texcoords[0], sPtr);
44713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.CreateFNeg(texcoords[2]), tPtr);
44813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.getInt32(3), facePtr);
44913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         }
45013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.endif();
45113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         m_storage->setCurrentBlock(currentBlock(), false);
45213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
45313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(my, maPtr);
45413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      }
45513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.elseop(); // !(my > mx && my > mz)
45613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
45713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      {
45813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         //ifCond(builder.CreateFCmpOGE(texcoords[2], float0, name("zPositive")));
45913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.ifCond(FPositive(builder, texcoords[2]));
46013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         m_storage->setCurrentBlock(currentBlock(), false);
46113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         {
46213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore((texcoords[0]), sPtr);
46313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
46413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.getInt32(4), facePtr);
46513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         }
46613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.elseop();
46713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//        m_storage->setCurrentBlock(currentBlock(), false);
46813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         {
46913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.CreateFNeg(texcoords[0]), sPtr);
47013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
47113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li            builder.CreateStore(builder.getInt32(5), facePtr);
47213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         }
47313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         condBranch.endif(); // end if (x >= 0)
47413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//         m_storage->setCurrentBlock(currentBlock(), false);
47513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
47613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         builder.CreateStore(mz, maPtr);
47713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      }
47813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      condBranch.endif();
47913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//      m_storage->setCurrentBlock(currentBlock(), false);
48013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   }
48113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   condBranch.endif();
48213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   m_storage->setCurrentBlock(currentBlock(), false);
48313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
48413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
48513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * s = builder.CreateLoad(sPtr);
48613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * t = builder.CreateLoad(tPtr);
48713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * ma = builder.CreateLoad(maPtr);
48813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * face = builder.CreateLoad(facePtr);
48913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
49013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   s = builder.CreateFDiv(s, ma);
49113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   s = builder.CreateFAdd(s, float1);
49213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   s = builder.CreateFMul(s, float0_5);
49313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
49413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   t = builder.CreateFDiv(t, ma);
49513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   t = builder.CreateFAdd(t, float1);
49613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   t = builder.CreateFMul(t, float0_5);
49713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
49813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li//   ChannelType sType = Float, tType = Float;
49913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * xLerp = NULL, * yLerp = NULL;
50013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
50113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            /*sType, */s, textureWidth, textureW, &xLerp);
50213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
50313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                            /*tType, */t, textureHeight, textureH, &yLerp);
50413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * indexOffset = builder.CreateMul(builder.CreateMul(textureHeight, textureWidth), face);
50513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   Value * index = builder.CreateAdd(builder.CreateMul(y, textureWidth), x);
50613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
50736ffccf19c02a54a6dc9952dc9c181d4fda2a020David Li   Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
50813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (!textureData)
50913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = new GlobalVariable(*module, intPointerType,
51013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li                                       true, GlobalValue::ExternalLinkage,
51136ffccf19c02a54a6dc9952dc9c181d4fda2a020David Li                                       NULL, _PF2_TEXTURE_DATA_NAME_);
51213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
51313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
51413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   textureData = builder.CreateLoad(textureData);
51513fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li
51613fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   if (0 == gglCtx->textureState.textures[sampler].minFilter &&
51713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li         0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
51813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = pointSample(builder, textureData, builder.CreateAdd(indexOffset, index),
51901e6ff90560d588418e706ce4d2a16d5a15520e5David Li                                gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
52013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      return intColorVecToFloatColorVec(builder, textureData);
52101e6ff90560d588418e706ce4d2a16d5a15520e5David Li
52213fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
52313fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li              1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
52413fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      textureData = linearSample(builder, textureData, indexOffset, x, y, xLerp, yLerp,
52501e6ff90560d588418e706ce4d2a16d5a15520e5David Li                                 textureW, textureH,  textureWidth, textureHeight,
52601e6ff90560d588418e706ce4d2a16d5a15520e5David Li                                 gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
52713fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      return intColorVecToFloatColorVec(builder, textureData);
52813fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   } else
52913fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li      assert(!"unsupported texture filter");
53013fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li   return NULL;
53113fea0fc797fa0d4c236db5aa2e6a23fc0e450dbDavid Li}
532