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/*, ®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]
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