• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
pointSample(IRBuilder<> & builder,Value * textureData,Value * index,const GGLPixelFormat format)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
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)143 static Value * linearSample(IRBuilder<> & builder, Value * textureData, Value * indexOffset,
144                             Value * x0, Value * y0, Value * xLerp, Value * yLerp,
145                             Value * w, Value * h,  Value * width, Value * height,
146                             const GGLPixelFormat format/*, const RegDesc * dstDesc*/)
147 {
148    // TODO: linear filtering needs to be fixed for texcoord outside of [0,1]
149    Value * x1 = builder.CreateAdd(x0, builder.getInt32(1));
150    x1 = minIntScalar(builder, x1, w);
151    Value * y1 = builder.CreateAdd(y0, builder.getInt32(1));
152    y1 = minIntScalar(builder, y1, h);
153 
154 //   RegDesc regDesc;
155 //   regDesc.SetVectorType(Fixed8);
156 
157    Value * index = builder.CreateMul(y0, width);
158    index = builder.CreateAdd(index, x0);
159    index = builder.CreateAdd(index, indexOffset);
160    Value * s0 = pointSample(builder, textureData, index, format/*, &regDesc*/);
161 //   s0 = builder.CreateBitCast(s0, intVecType(builder));
162 
163    index = builder.CreateMul(y0, width);
164    index = builder.CreateAdd(index, x1);
165    index = builder.CreateAdd(index, indexOffset);
166    Value * s1 = pointSample(builder, textureData, index, format/*, &regDesc*/);
167 //   s1 = builder.CreateBitCast(s1, intVecType(builder));
168 
169    index = builder.CreateMul(y1, width);
170    index = builder.CreateAdd(index, x1);
171    index = builder.CreateAdd(index, indexOffset);
172    Value * s2 = pointSample(builder, textureData, index, format/*, &regDesc*/);
173 //   s2 = builder.CreateBitCast(s2, intVecType(builder));
174 
175    index = builder.CreateMul(y1, width);
176    index = builder.CreateAdd(index, x0);
177    index = builder.CreateAdd(index, indexOffset);
178    Value * s3 = pointSample(builder, textureData, index, format/*, &regDesc*/);
179 //   s3 = builder.CreateBitCast(s3, intVecType(builder));
180 
181    Value * xLerpVec = intVec(builder, xLerp, xLerp, xLerp, xLerp);
182 
183    Value * h0 = builder.CreateMul(builder.CreateSub(s1, s0), xLerpVec);
184    // arithmetic shift right, since it's the result of subtraction, which could be negative
185    h0 = builder.CreateAShr(h0, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
186    h0 = builder.CreateAdd(h0, s0);
187 
188    Value * h1 = builder.CreateMul(builder.CreateSub(s2, s3), xLerpVec);
189    h1 = builder.CreateAShr(h1, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
190    h1 = builder.CreateAdd(h1, s3);
191 
192    Value * sample = builder.CreateMul(builder.CreateSub(h1, h0),
193                                       intVec(builder, yLerp, yLerp, yLerp, yLerp));
194    sample = builder.CreateAShr(sample, constIntVec(builder, SHIFT, SHIFT, SHIFT, SHIFT));
195    sample = builder.CreateAdd(sample, h0);
196 
197    return sample;
198 //   if (!dstDesc || dstDesc->IsVectorType(Float)) {
199 //      sample = builder.CreateUIToFP(sample, floatVecType(builder));
200 //      return builder.CreateFMul(sample, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
201 //                                1 / 255.0f, 1 / 255.0f));
202 //   } else if (dstDesc && dstDesc->IsVectorType(Fixed16)) {
203 //      sample = builder.CreateShl(sample, constIntVec(builder, 8, 8, 8, 8));
204 //      return builder.CreateBitCast(sample, floatVecType(builder));
205 //   } else if (dstDesc && dstDesc->IsVectorType(Fixed8))
206 //      return builder.CreateBitCast(sample, floatVecType(builder));
207 //   else if (dstDesc && dstDesc->IsInt32Color()) {
208 //      sample = builder.CreateShl(sample, constIntVec(builder, 0, 8, 16, 24));
209 //      std::vector<llvm::Value*> samples = extractVector(sample);
210 //      samples[0] = builder.CreateOr(samples[0], samples[1]);
211 //      samples[0] = builder.CreateOr(samples[0], samples[2]);
212 //      samples[0] = builder.CreateOr(samples[0], samples[3]);
213 //      sample = builder.CreateInsertElement(sample, samples[0], builder.getInt32(0));
214 //      return builder.CreateBitCast(sample, floatVecType(builder));
215 //   } else
216 //      assert(0);
217 }
218 
219 // dim is size - 1, since [0.0f,1.0f]->[0, size - 1]
texcoordWrap(IRBuilder<> & builder,const unsigned wrap,Value * r,Value * size,Value * dim,Value ** texelLerp)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 
tex2D(IRBuilder<> & builder,Value * in1,const unsigned sampler,const GGLState * gglCtx)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
FCmpGT(IRBuilder<> & builder,Value * lhs,Value * rhs)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 
FPositive(IRBuilder<> & builder,Value * val)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 
Fabs(IRBuilder<> & builder,Value * val)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 
texCube(IRBuilder<> & builder,Value * in1,const unsigned sampler,const GGLState * gglCtx)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