| /** |
| ** |
| ** 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/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 |
| ALOGD("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/*, ®Desc*/); |
| // 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/*, ®Desc*/); |
| // 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/*, ®Desc*/); |
| // 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/*, ®Desc*/); |
| // 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) |
| { |
| 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) |
| { |
| Type * intType = builder.getInt32Ty(); |
| 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) |
| { |
| 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)); |
| |
| Type * const intType = builder.getInt32Ty(); |
| PointerType * const intPointerType = PointerType::get(intType, 0); |
| 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; |
| } |