summaryrefslogtreecommitdiff
path: root/src/pixelflinger2/llvm_texture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pixelflinger2/llvm_texture.cpp')
-rw-r--r--src/pixelflinger2/llvm_texture.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/src/pixelflinger2/llvm_texture.cpp b/src/pixelflinger2/llvm_texture.cpp
new file mode 100644
index 0000000..f3d2bea
--- /dev/null
+++ b/src/pixelflinger2/llvm_texture.cpp
@@ -0,0 +1,531 @@
+/**
+ **
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <stack>
+
+#include "src/pixelflinger2/pixelflinger2.h"
+
+#include <llvm/Support/IRBuilder.h>
+#include <llvm/Module.h>
+
+#include "src/pixelflinger2/llvm_helper.h"
+
+using namespace llvm;
+
+// texture data is int pointer to surface (will cast to short for 16bpp), index is linear texel index,
+// format is GGLPixelFormat for surface, return type is <4 x i32> rgba
+static Value * pointSample(IRBuilder<> & builder, Value * textureData, Value * index, const GGLPixelFormat format)
+{
+ Value * texel = NULL;
+ switch (format) {
+ case GGL_PIXEL_FORMAT_RGBA_8888:
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel");
+ break;
+ case GGL_PIXEL_FORMAT_RGBX_8888:
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel");
+ texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
+ break;
+ case GGL_PIXEL_FORMAT_RGB_565: {
+ textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(), 0));
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel565");
+ texel = builder.CreateZExt(texel, Type::getInt32Ty(builder.getContext()));
+
+ Value * b = builder.CreateAnd(texel, builder.getInt32(0x1f));
+ b = builder.CreateShl(b, builder.getInt32(3));
+ b = builder.CreateOr(b, builder.CreateLShr(b, builder.getInt32(5)));
+
+ Value * g = builder.CreateAnd(texel, builder.getInt32(0x7e0));
+ g = builder.CreateShl(g, builder.getInt32(5));
+ g = builder.CreateOr(g, builder.CreateLShr(g, builder.getInt32(6)));
+ g = builder.CreateAnd(g, builder.getInt32(0xff00));
+
+ Value * r = builder.CreateAnd(texel, builder.getInt32(0xF800));
+ r = builder.CreateShl(r, builder.getInt32(8));
+ r = builder.CreateOr(r, builder.CreateLShr(r, builder.getInt32(5)));
+ r = builder.CreateAnd(r, builder.getInt32(0xff0000));
+
+ texel = builder.CreateOr(r, builder.CreateOr(g, b));
+ texel = builder.CreateOr(texel, builder.getInt32(0xff000000), name("texel"));
+ break;
+ }
+ case GGL_PIXEL_FORMAT_A_8: {
+ textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel_a8");
+ texel = builder.CreateZExt(texel, builder.getInt32Ty());
+ texel = builder.CreateShl(texel, builder.getInt32(24));
+ break;
+ }
+ case GGL_PIXEL_FORMAT_L_8: {
+ textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt8Ty(),0));
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel_l8");
+ texel = builder.CreateZExt(texel, builder.getInt32Ty());
+ texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
+ texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
+ texel = builder.CreateOr(texel, builder.getInt32(0xff000000));
+ break;
+ }
+ case GGL_PIXEL_FORMAT_LA_88: {
+ textureData = builder.CreateBitCast(textureData, PointerType::get(builder.getInt16Ty(),0));
+ textureData = builder.CreateGEP(textureData, index);
+ texel = builder.CreateLoad(textureData, "texel_la8");
+ texel = builder.CreateZExt(texel, builder.getInt32Ty());
+ Value * alpha = builder.CreateAnd(texel, builder.getInt32(0xff00));
+ texel = builder.CreateAnd(texel, builder.getInt32(0xff));
+ texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
+ texel = builder.CreateOr(texel, builder.CreateShl(texel, 8));
+ texel = builder.CreateOr(texel, builder.CreateShl(alpha, 16));
+ break;
+ }
+ case GGL_PIXEL_FORMAT_UNKNOWN: // usually means texture not set yet
+ LOGD("pf2: pointSample: unknown format, default to 0xffff00ff \n");
+ texel = builder.getInt32(0xffff00ff);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ Value * channels = Constant::getNullValue(intVecType(builder));
+
+// if (dstDesc && dstDesc->IsInt32Color()) {
+// channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
+// channels = builder.CreateBitCast(channels, floatVecType(builder));
+// return channels;
+// } else if (!dstDesc || dstDesc->IsVectorType()) {
+ channels = builder.CreateInsertElement(channels, texel, builder.getInt32(0));
+ channels = builder.CreateInsertElement(channels, texel, builder.getInt32(1));
+ channels = builder.CreateInsertElement(channels, texel, builder.getInt32(2));
+ channels = builder.CreateInsertElement(channels, texel, builder.getInt32(3));
+// if (dstDesc && dstDesc->IsVectorType(Fixed8)) {
+// channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
+// channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
+// channels = builder.CreateBitCast(channels, floatVecType(builder));
+// } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
+// channels = builder.CreateShl(channels, constIntVec(builder, 8, 0, 0, 0));
+// channels = builder.CreateLShr(channels, constIntVec(builder, 0, 0, 8, 16));
+// channels = builder.CreateAnd(channels, constIntVec(builder, 0xff00, 0xff00, 0xff00, 0xff00));
+// channels = builder.CreateBitCast(channels, floatVecType(builder));
+// } else if (!dstDesc || dstDesc->IsVectorType(Float)) { // no analysis done in vertex shader, so use default float [0,1] output
+ channels = builder.CreateLShr(channels, constIntVec(builder, 0, 8, 16, 24));
+ channels = builder.CreateAnd(channels, constIntVec(builder, 0xff, 0xff, 0xff, 0xff));
+// channels = builder.CreateUIToFP(channels, floatVecType(builder));
+// channels = builder.CreateFMul(channels, constFloatVec(builder, 1 / 255.0f, 1 / 255.0f,
+// 1 / 255.0f, 1 / 255.0f));
+// } else
+// assert(0);
+// } else
+// assert(0);
+
+ return channels;
+}
+
+static const unsigned SHIFT = 16;
+
+// w = width - 1, h = height - 1; similar to pointSample; returns <4 x i32> rgba
+static Value * linearSample(IRBuilder<> & builder, Value * textureData, Value * indexOffset,
+ Value * x0, Value * y0, Value * xLerp, Value * yLerp,
+ Value * w, Value * h, Value * width, Value * height,
+ const GGLPixelFormat format/*, const RegDesc * dstDesc*/)
+{
+ // TODO: linear filtering needs to be fixed for texcoord outside of [0,1]
+ Value * x1 = builder.CreateAdd(x0, builder.getInt32(1));
+ x1 = minIntScalar(builder, x1, w);
+ Value * y1 = builder.CreateAdd(y0, builder.getInt32(1));
+ y1 = minIntScalar(builder, y1, h);
+
+// RegDesc regDesc;
+// regDesc.SetVectorType(Fixed8);
+
+ Value * index = builder.CreateMul(y0, width);
+ index = builder.CreateAdd(index, x0);
+ index = builder.CreateAdd(index, indexOffset);
+ Value * s0 = pointSample(builder, textureData, index, format/*, &regDesc*/);
+// s0 = builder.CreateBitCast(s0, intVecType(builder));
+
+ index = builder.CreateMul(y0, width);
+ index = builder.CreateAdd(index, x1);
+ index = builder.CreateAdd(index, indexOffset);
+ Value * s1 = pointSample(builder, textureData, index, format/*, &regDesc*/);
+// s1 = builder.CreateBitCast(s1, intVecType(builder));
+
+ index = builder.CreateMul(y1, width);
+ index = builder.CreateAdd(index, x1);
+ index = builder.CreateAdd(index, indexOffset);
+ Value * s2 = pointSample(builder, textureData, index, format/*, &regDesc*/);
+// s2 = builder.CreateBitCast(s2, intVecType(builder));
+
+ index = builder.CreateMul(y1, width);
+ index = builder.CreateAdd(index, x0);
+ index = builder.CreateAdd(index, indexOffset);
+ Value * s3 = pointSample(builder, textureData, index, format/*, &regDesc*/);
+// s3 = builder.CreateBitCast(s3, intVecType(builder));
+
+ Value * xLerpVec = intVec(builder, xLerp, xLerp, xLerp, xLerp);
+
+ Value * h0 = builder.CreateMul(builder.CreateSub(s1, s0), xLerpVec);
+ // arithmetic shift right, since it's the result of subtraction, which could be negative
+ h0 = builder.CreateAShr(h0, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
+ h0 = builder.CreateAdd(h0, s0);
+
+ Value * h1 = builder.CreateMul(builder.CreateSub(s2, s3), xLerpVec);
+ h1 = builder.CreateAShr(h1, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
+ h1 = builder.CreateAdd(h1, s3);
+
+ Value * sample = builder.CreateMul(builder.CreateSub(h1, h0),
+ intVec(builder, yLerp, yLerp, yLerp, yLerp));
+ sample = builder.CreateAShr(sample, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
+ sample = builder.CreateAdd(sample, h0);
+
+ return sample;
+// if (!dstDesc || dstDesc->IsVectorType(Float)) {
+// sample = builder.CreateUIToFP(sample, floatVecType(builder));
+// return builder.CreateFMul(sample, constFloatVec(builder, 1 / 255.0f, 1 / 255.0f,
+// 1 / 255.0f, 1 / 255.0f));
+// } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
+// sample = builder.CreateShl(sample, constIntVec(builder, 8, 8, 8, 8));
+// return builder.CreateBitCast(sample, floatVecType(builder));
+// } else if (dstDesc && dstDesc->IsVectorType(Fixed8))
+// return builder.CreateBitCast(sample, floatVecType(builder));
+// else if (dstDesc && dstDesc->IsInt32Color()) {
+// sample = builder.CreateShl(sample, constIntVec(builder, 0, 8, 16, 24));
+// std::vector<llvm::Value*> samples = extractVector(sample);
+// samples[0] = builder.CreateOr(samples[0], samples[1]);
+// samples[0] = builder.CreateOr(samples[0], samples[2]);
+// samples[0] = builder.CreateOr(samples[0], samples[3]);
+// sample = builder.CreateInsertElement(sample, samples[0], builder.getInt32(0));
+// return builder.CreateBitCast(sample, floatVecType(builder));
+// } else
+// assert(0);
+}
+
+// dim is size - 1, since [0.0f,1.0f]->[0, size - 1]
+static Value * texcoordWrap(IRBuilder<> & builder, const unsigned wrap,
+ /*const ChannelType type,*/ Value * r, Value * size, Value * dim,
+ Value ** texelLerp)
+{
+ const Type * intType = Type::getInt32Ty(builder.getContext());
+ Value * tc = NULL;
+ Value * odd = NULL;
+// if (Float == type) {
+ // convert float to fixed16 so that 16LSB are the remainder, and bit 16 is one
+ // mantissa is the amount between two texels, used for linear interpolation
+ tc = ConstantFP::get(builder.getContext(), APFloat(float(1 << SHIFT)));
+ tc = builder.CreateFMul(tc, r);
+ tc = builder.CreateFPToSI(tc, intType);
+// } else if (Fixed16 == type) {
+// assert(16 == SHIFT);
+// tc = builder.CreateBitCast(r, Type::getInt32Ty(builder.getContext()));
+// } else
+// assert(0);
+
+ odd = builder.CreateAnd(tc, builder.getInt32(1 << SHIFT), name("tc_odd"));
+
+ if (0 == wrap || 2 == wrap) // just the mantissa for wrap and mirrored
+ tc = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
+
+ tc = builder.CreateMul(tc, dim);
+
+ *texelLerp = builder.CreateAnd(tc, builder.getInt32((1 << SHIFT) - 1));
+
+ tc = builder.CreateLShr(tc, builder.getInt32(SHIFT));
+
+ if (0 == wrap) // GL_REPEAT
+ { } else if (1 == wrap) { // GL_CLAMP_TO_EDGE
+ tc = maxIntScalar(builder, tc, builder.getInt32(0));
+ tc = minIntScalar(builder, tc, dim);
+ } else if (2 == wrap) { // GL_MIRRORER_REPEAT
+ Value * tcPtr = builder.CreateAlloca(intType);
+ builder.CreateStore(tc, tcPtr);
+ odd = builder.CreateICmpNE(odd, builder.getInt32(0));
+
+ CondBranch condBranch(builder);
+ condBranch.ifCond(odd);
+
+ tc = builder.CreateSub(dim, tc, name("tc_mirrored"));
+ builder.CreateStore(tc, tcPtr);
+
+ condBranch.endif();
+
+ tc = builder.CreateLoad(tcPtr);
+ } else
+ assert(0);
+
+ return tc;
+}
+
+Value * tex2D(IRBuilder<> & builder, Value * in1, const unsigned sampler,
+ /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
+ const GGLState * gglCtx)
+{
+ const Type * intType = builder.getInt32Ty();
+ const PointerType * intPointerType = PointerType::get(intType, 0);
+
+ llvm::Module * module = builder.GetInsertBlock()->getParent()->getParent();
+ std::vector<Value * > texcoords = extractVector(builder, in1);
+
+ Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
+ if (!textureDimensions)
+ textureDimensions = new GlobalVariable(*module, intType, true,
+ GlobalValue::ExternalLinkage,
+ NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
+ Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
+ sampler * 2);
+ textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
+ Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
+ sampler * 2 + 1);
+ textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
+ Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
+ Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
+// ChannelType sType = Float, tType = Float;
+// if (in1Desc) {
+// sType = in1Desc->channels[0];
+// tType = in1Desc->channels[1];
+// }
+
+ Value * xLerp = NULL, * yLerp = NULL;
+ Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
+ /*sType, */texcoords[0], textureWidth, textureW, &xLerp);
+ Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
+ /*tType, */texcoords[1], textureHeight, textureH, &yLerp);
+
+ Value * index = builder.CreateMul(y, textureWidth);
+ index = builder.CreateAdd(index, x);
+
+ Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
+ if (!textureData)
+ textureData = new GlobalVariable(*module, intPointerType,
+ true, GlobalValue::ExternalLinkage,
+ NULL, _PF2_TEXTURE_DATA_NAME_);
+
+ textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
+ textureData = builder.CreateLoad(textureData);
+
+ if (0 == gglCtx->textureState.textures[sampler].minFilter &&
+ 0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
+ Value * ret = pointSample(builder, textureData, index,
+ gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
+ return intColorVecToFloatColorVec(builder, ret);
+ } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
+ 1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
+ Value * ret = linearSample(builder, textureData, builder.getInt32(0), x, y, xLerp, yLerp,
+ textureW, textureH, textureWidth, textureHeight,
+ gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
+ return intColorVecToFloatColorVec(builder, ret);
+ } else
+ assert(!"unsupported texture filter");
+ return NULL;
+}
+
+// only positive float; used in cube map since major axis is positive
+static Value * FCmpGT(IRBuilder<> & builder, Value * lhs, Value * rhs)
+{
+ const Type * const intType = Type::getInt32Ty(builder.getContext());
+ lhs = builder.CreateBitCast(lhs, intType);
+ rhs = builder.CreateBitCast(rhs, intType);
+ return builder.CreateICmpUGT(lhs, rhs);
+}
+
+static Value * FPositive(IRBuilder<> & builder, Value * val)
+{
+ // float cmp faster here
+ return builder.CreateFCmpOGE(val, Constant::getNullValue(builder.getFloatTy()));
+ //val = builder.CreateBitCast(val, Type::getInt32Ty(builder.getContext()));
+ //return builder.CreateICmpSGE(val, storage->constantInt(0));
+ //val = builder.CreateAnd(val, storage->constantInt(0x80000000));
+ //return builder.CreateICmpNE(val, storage->constantInt(0));
+}
+
+static Value * Fabs(IRBuilder<> & builder, Value * val)
+{
+ val = builder.CreateBitCast(val, builder.getInt32Ty());
+ val = builder.CreateAnd(val, builder.getInt32(~0x80000000));
+ return builder.CreateBitCast(val, builder.getFloatTy());
+ //return builder.CreateICmpSGE(val, storage->constantInt(0));
+}
+
+Value * texCube(IRBuilder<> & builder, Value * in1, const unsigned sampler,
+ /*const RegDesc * in1Desc, const RegDesc * dstDesc,*/
+ const GGLState * gglCtx)
+{
+// if (in1Desc) // the major axis determination code is only float for now
+// assert(in1Desc->IsVectorType(Float));
+
+ const Type * const intType = builder.getInt32Ty();
+ const PointerType * const intPointerType = PointerType::get(intType, 0);
+ const Type * const floatType = builder.getFloatTy();
+
+ Constant * const float1 = constFloat(builder, 1.0f);
+ Constant * const float0_5 = constFloat(builder, 0.5f);
+
+ Module * module = builder.GetInsertBlock()->getParent()->getParent();
+ std::vector<Value * > texcoords = extractVector(builder, in1);
+
+ Value * textureDimensions = module->getGlobalVariable(_PF2_TEXTURE_DIMENSIONS_NAME_);
+ if (!textureDimensions)
+ textureDimensions = new GlobalVariable(*module, intType, true,
+ GlobalValue::ExternalLinkage,
+ NULL, _PF2_TEXTURE_DIMENSIONS_NAME_);
+ Value * textureWidth = builder.CreateConstInBoundsGEP1_32(textureDimensions,
+ sampler * 2);
+ textureWidth = builder.CreateLoad(textureWidth, name("textureWidth"));
+ Value * textureHeight = builder.CreateConstInBoundsGEP1_32(textureDimensions,
+ sampler * 2 + 1);
+ textureHeight = builder.CreateLoad(textureHeight, name("textureHeight"));
+ Value * textureW = builder.CreateSub(textureWidth, builder.getInt32(1));
+ Value * textureH = builder.CreateSub(textureHeight, builder.getInt32(1));
+
+ Value * mx = Fabs(builder, texcoords[0]), * my = Fabs(builder, texcoords[1]);
+ Value * mz = Fabs(builder, texcoords[2]);
+ Value * sPtr = builder.CreateAlloca(floatType);
+ Value * tPtr = builder.CreateAlloca(floatType);
+ Value * maPtr = builder.CreateAlloca(floatType);
+ Value * facePtr = builder.CreateAlloca(intType);
+
+ Value * mxGmyCmp = FCmpGT(builder, mx, my);
+ Value * mxGmzCmp = FCmpGT(builder, mx, mz);
+
+ CondBranch condBranch(builder);
+ condBranch.ifCond(builder.CreateAnd(mxGmyCmp, mxGmzCmp)); // if (mx > my && mx > mz)
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ condBranch.ifCond(FPositive(builder, texcoords[0]));
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore(builder.CreateFNeg(texcoords[2]), sPtr);
+ builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
+ builder.CreateStore(builder.getInt32(0), facePtr);
+ }
+ condBranch.elseop();
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore((texcoords[2]), sPtr);
+ builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
+ builder.CreateStore(builder.getInt32(1), facePtr);
+ }
+ condBranch.endif(); // end if (x >= 0)
+// m_storage->setCurrentBlock(currentBlock(), false);
+
+ builder.CreateStore(mx, maPtr);
+ }
+ condBranch.elseop(); // !(mx > my && mx > mz)
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ Value * myGmxCmp = FCmpGT(builder, my, mx);
+ Value * myGmzCmp = FCmpGT(builder, my, mz);
+ condBranch.ifCond(builder.CreateAnd(myGmxCmp, myGmzCmp)); // my > mx && my > mz
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ condBranch.ifCond(FPositive(builder, texcoords[1]));
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore((texcoords[0]), sPtr);
+ builder.CreateStore((texcoords[2]), tPtr);
+ builder.CreateStore(builder.getInt32(2), facePtr);
+ }
+ condBranch.elseop();
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore(texcoords[0], sPtr);
+ builder.CreateStore(builder.CreateFNeg(texcoords[2]), tPtr);
+ builder.CreateStore(builder.getInt32(3), facePtr);
+ }
+ condBranch.endif();
+// m_storage->setCurrentBlock(currentBlock(), false);
+
+ builder.CreateStore(my, maPtr);
+ }
+ condBranch.elseop(); // !(my > mx && my > mz)
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ //ifCond(builder.CreateFCmpOGE(texcoords[2], float0, name("zPositive")));
+ condBranch.ifCond(FPositive(builder, texcoords[2]));
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore((texcoords[0]), sPtr);
+ builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
+ builder.CreateStore(builder.getInt32(4), facePtr);
+ }
+ condBranch.elseop();
+// m_storage->setCurrentBlock(currentBlock(), false);
+ {
+ builder.CreateStore(builder.CreateFNeg(texcoords[0]), sPtr);
+ builder.CreateStore(builder.CreateFNeg(texcoords[1]), tPtr);
+ builder.CreateStore(builder.getInt32(5), facePtr);
+ }
+ condBranch.endif(); // end if (x >= 0)
+// m_storage->setCurrentBlock(currentBlock(), false);
+
+ builder.CreateStore(mz, maPtr);
+ }
+ condBranch.endif();
+// m_storage->setCurrentBlock(currentBlock(), false);
+ }
+ condBranch.endif();
+// m_storage->setCurrentBlock(currentBlock(), false);
+
+
+ Value * s = builder.CreateLoad(sPtr);
+ Value * t = builder.CreateLoad(tPtr);
+ Value * ma = builder.CreateLoad(maPtr);
+ Value * face = builder.CreateLoad(facePtr);
+
+ s = builder.CreateFDiv(s, ma);
+ s = builder.CreateFAdd(s, float1);
+ s = builder.CreateFMul(s, float0_5);
+
+ t = builder.CreateFDiv(t, ma);
+ t = builder.CreateFAdd(t, float1);
+ t = builder.CreateFMul(t, float0_5);
+
+// ChannelType sType = Float, tType = Float;
+ Value * xLerp = NULL, * yLerp = NULL;
+ Value * x = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapS,
+ /*sType, */s, textureWidth, textureW, &xLerp);
+ Value * y = texcoordWrap(builder, gglCtx->textureState.textures[sampler].wrapT,
+ /*tType, */t, textureHeight, textureH, &yLerp);
+ Value * indexOffset = builder.CreateMul(builder.CreateMul(textureHeight, textureWidth), face);
+ Value * index = builder.CreateAdd(builder.CreateMul(y, textureWidth), x);
+
+ Value * textureData = module->getGlobalVariable(_PF2_TEXTURE_DATA_NAME_);
+ if (!textureData)
+ textureData = new GlobalVariable(*module, intPointerType,
+ true, GlobalValue::ExternalLinkage,
+ NULL, _PF2_TEXTURE_DATA_NAME_);
+
+ textureData = builder.CreateConstInBoundsGEP1_32(textureData, sampler);
+ textureData = builder.CreateLoad(textureData);
+
+ if (0 == gglCtx->textureState.textures[sampler].minFilter &&
+ 0 == gglCtx->textureState.textures[sampler].magFilter) { // GL_NEAREST
+ textureData = pointSample(builder, textureData, builder.CreateAdd(indexOffset, index),
+ gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
+ return intColorVecToFloatColorVec(builder, textureData);
+
+ } else if (1 == gglCtx->textureState.textures[sampler].minFilter &&
+ 1 == gglCtx->textureState.textures[sampler].magFilter) { // GL_LINEAR
+ textureData = linearSample(builder, textureData, indexOffset, x, y, xLerp, yLerp,
+ textureW, textureH, textureWidth, textureHeight,
+ gglCtx->textureState.textures[sampler].format/*, dstDesc*/);
+ return intColorVecToFloatColorVec(builder, textureData);
+ } else
+ assert(!"unsupported texture filter");
+ return NULL;
+}