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