Fix #34156: Spec. and Alpha Intensity OpenGL issue
[blender.git] / source / blender / render / intern / source / imagetexture.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributors: 2004/2005/2006 Blender Foundation, full recode
22  *
23  * ***** END GPL/BL DUAL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/imagetexture.c
27  *  \ingroup render
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <math.h>
34 #include <float.h>
35 #ifndef WIN32 
36 #include <unistd.h>
37 #else
38 #include <io.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "IMB_imbuf_types.h"
44 #include "IMB_imbuf.h"
45
46 #include "DNA_image_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_texture_types.h"
49
50 #include "BLI_math.h"
51 #include "BLI_blenlib.h"
52 #include "BLI_threads.h"
53 #include "BLI_utildefines.h"
54
55 #include "BKE_global.h"
56 #include "BKE_main.h"
57 #include "BKE_image.h"
58 #include "BKE_texture.h"
59 #include "BKE_library.h"
60
61 #include "RE_render_ext.h"
62
63 #include "renderpipeline.h"
64 #include "render_types.h"
65 #include "texture.h"
66
67 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
68 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
69 /* only to be used here in this file, it's for speed */
70 extern struct Render R;
71 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
72
73 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend);
74
75 /* *********** IMAGEWRAPPING ****************** */
76
77
78 /* x and y have to be checked for image size */
79 static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
80 {
81         int ofs = y * ibuf->x + x;
82         
83         if (ibuf->rect_float) {
84                 if (ibuf->channels==4) {
85                         float *fp= ibuf->rect_float + 4*ofs;
86                         copy_v4_v4(col, fp);
87                 }
88                 else if (ibuf->channels==3) {
89                         float *fp= ibuf->rect_float + 3*ofs;
90                         copy_v3_v3(col, fp);
91                         col[3]= 1.0f;
92                 }
93                 else {
94                         float *fp= ibuf->rect_float + ofs;
95                         col[0]= col[1]= col[2]= col[3]= *fp;
96                 }
97         }
98         else {
99                 char *rect = (char *)( ibuf->rect+ ofs);
100
101                 col[0] = ((float)rect[0])*(1.0f/255.0f);
102                 col[1] = ((float)rect[1])*(1.0f/255.0f);
103                 col[2] = ((float)rect[2])*(1.0f/255.0f);
104                 col[3] = ((float)rect[3])*(1.0f/255.0f);
105
106                 /* bytes are internally straight, however render pipeline seems to expect premul */
107                 col[0] *= col[3];
108                 col[1] *= col[3];
109                 col[2] *= col[3];
110         }
111 }
112
113 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
114 {
115         float fx, fy, val1, val2, val3;
116         int x, y, retval;
117         int xi, yi; /* original values */
118
119         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
120         
121         /* we need to set retval OK, otherwise texture code generates normals itself... */
122         retval= texres->nor?3:1;
123         
124         /* quick tests */
125         if (ibuf==NULL && ima==NULL)
126                 return retval;
127         if (ima) {
128                 
129                 /* hack for icon render */
130                 if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
131                         return retval;
132
133                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
134
135                 ima->flag|= IMA_USED_FOR_RENDER;
136         }
137         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
138                 if (ima)
139                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
140                 return retval;
141         }
142         
143         /* setup mapping */
144         if (tex->imaflag & TEX_IMAROT) {
145                 fy= texvec[0];
146                 fx= texvec[1];
147         }
148         else {
149                 fx= texvec[0];
150                 fy= texvec[1];
151         }
152         
153         if (tex->extend == TEX_CHECKER) {
154                 int xs, ys;
155                 
156                 xs= (int)floor(fx);
157                 ys= (int)floor(fy);
158                 fx-= xs;
159                 fy-= ys;
160
161                 if ( (tex->flag & TEX_CHECKER_ODD) == 0) {
162                         if ((xs + ys) & 1) {
163                                 /* pass */
164                         }
165                         else {
166                                 if (ima)
167                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
168                                 return retval;
169                         }
170                 }
171                 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
172                         if ((xs+ys) & 1) {
173                                 if (ima)
174                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
175                                 return retval;
176                         }
177                 }
178                 /* scale around center, (0.5, 0.5) */
179                 if (tex->checkerdist<1.0f) {
180                         fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
181                         fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
182                 }
183         }
184
185         x= xi= (int)floorf(fx*ibuf->x);
186         y= yi= (int)floorf(fy*ibuf->y);
187
188         if (tex->extend == TEX_CLIPCUBE) {
189                 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
190                         if (ima)
191                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
192                         return retval;
193                 }
194         }
195         else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
196                 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
197                         if (ima)
198                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
199                         return retval;
200                 }
201         }
202         else {
203                 if (tex->extend==TEX_EXTEND) {
204                         if (x>=ibuf->x) x = ibuf->x-1;
205                         else if (x<0) x= 0;
206                 }
207                 else {
208                         x= x % ibuf->x;
209                         if (x<0) x+= ibuf->x;
210                 }
211                 if (tex->extend==TEX_EXTEND) {
212                         if (y>=ibuf->y) y = ibuf->y-1;
213                         else if (y<0) y= 0;
214                 }
215                 else {
216                         y= y % ibuf->y;
217                         if (y<0) y+= ibuf->y;
218                 }
219         }
220         
221         /* warning, no return before setting back! */
222         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
223                 ibuf->rect+= (ibuf->x*ibuf->y);
224         }
225
226         /* keep this before interpolation [#29761] */
227         if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
228                 if ((tex->imaflag & TEX_CALCALPHA) == 0) {
229                         texres->talpha = TRUE;
230                 }
231         }
232
233         /* interpolate */
234         if (tex->imaflag & TEX_INTERPOL) {
235                 float filterx, filtery;
236                 filterx = (0.5f * tex->filtersize) / ibuf->x;
237                 filtery = (0.5f * tex->filtersize) / ibuf->y;
238
239                 /* important that this value is wrapped [#27782]
240                  * this applies the modifications made by the checks above,
241                  * back to the floating point values */
242                 fx -= (float)(xi - x) / (float)ibuf->x;
243                 fy -= (float)(yi - y) / (float)ibuf->y;
244
245                 boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND));
246         }
247         else { /* no filtering */
248                 ibuf_get_color(&texres->tr, ibuf, x, y);
249         }
250         
251         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
252                 ibuf->rect-= (ibuf->x*ibuf->y);
253         }
254
255         if (texres->nor) {
256                 if (tex->imaflag & TEX_NORMALMAP) {
257                         /* qdn: normal from color
258                          * The invert of the red channel is to make
259                          * the normal map compliant with the outside world.
260                          * It needs to be done because in Blender
261                          * the normal used in the renderer points inward. It is generated
262                          * this way in calc_vertexnormals(). Should this ever change
263                          * this negate must be removed. */
264                         texres->nor[0] = -2.f*(texres->tr - 0.5f);
265                         texres->nor[1] = 2.f*(texres->tg - 0.5f);
266                         texres->nor[2] = 2.f*(texres->tb - 0.5f);
267                 }
268                 else {
269                         /* bump: take three samples */
270                         val1= texres->tr+texres->tg+texres->tb;
271
272                         if (x<ibuf->x-1) {
273                                 float col[4];
274                                 ibuf_get_color(col, ibuf, x+1, y);
275                                 val2= (col[0]+col[1]+col[2]);
276                         }
277                         else val2= val1;
278
279                         if (y<ibuf->y-1) {
280                                 float col[4];
281                                 ibuf_get_color(col, ibuf, x, y+1);
282                                 val3= (col[0]+col[1]+col[2]);
283                         }
284                         else val3= val1;
285
286                         /* do not mix up x and y here! */
287                         texres->nor[0]= (val1-val2);
288                         texres->nor[1]= (val1-val3);
289                 }
290         }
291
292         if (texres->talpha) texres->tin= texres->ta;
293         else if (tex->imaflag & TEX_CALCALPHA) {
294                 texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb);
295         }
296         else texres->ta= texres->tin= 1.0;
297         
298         if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
299
300         /* de-premul, this is being premulled in shade_input_do_shade() */
301         if (texres->ta!=1.0f && texres->ta>1e-4f) {
302                 fx= 1.0f/texres->ta;
303                 texres->tr*= fx;
304                 texres->tg*= fx;
305                 texres->tb*= fx;
306         }
307
308         if (ima)
309                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
310
311         BRICONTRGB;
312         
313         return retval;
314 }
315
316 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
317 {
318         rctf *rf, *newrct;
319         short a;
320
321         a= *count;
322         rf= stack;
323         for (;a>0;a--) {
324                 if (rf->xmin<x1) {
325                         if (rf->xmax<x1) {
326                                 rf->xmin+= (x2-x1);
327                                 rf->xmax+= (x2-x1);
328                         }
329                         else {
330                                 if (rf->xmax>x2) rf->xmax = x2;
331                                 newrct= stack+ *count;
332                                 (*count)++;
333
334                                 newrct->xmax = x2;
335                                 newrct->xmin = rf->xmin+(x2-x1);
336                                 newrct->ymin = rf->ymin;
337                                 newrct->ymax = rf->ymax;
338                                 
339                                 if (newrct->xmin ==newrct->xmax) (*count)--;
340                                 
341                                 rf->xmin = x1;
342                         }
343                 }
344                 else if (rf->xmax>x2) {
345                         if (rf->xmin>x2) {
346                                 rf->xmin-= (x2-x1);
347                                 rf->xmax-= (x2-x1);
348                         }
349                         else {
350                                 if (rf->xmin<x1) rf->xmin = x1;
351                                 newrct= stack+ *count;
352                                 (*count)++;
353
354                                 newrct->xmin = x1;
355                                 newrct->xmax = rf->xmax-(x2-x1);
356                                 newrct->ymin = rf->ymin;
357                                 newrct->ymax = rf->ymax;
358
359                                 if (newrct->xmin ==newrct->xmax) (*count)--;
360
361                                 rf->xmax = x2;
362                         }
363                 }
364                 rf++;
365         }
366
367 }
368
369 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
370 {
371         rctf *rf, *newrct;
372         short a;
373
374         a= *count;
375         rf= stack;
376         for (;a>0;a--) {
377                 if (rf->ymin<y1) {
378                         if (rf->ymax<y1) {
379                                 rf->ymin+= (y2-y1);
380                                 rf->ymax+= (y2-y1);
381                         }
382                         else {
383                                 if (rf->ymax>y2) rf->ymax = y2;
384                                 newrct= stack+ *count;
385                                 (*count)++;
386
387                                 newrct->ymax = y2;
388                                 newrct->ymin = rf->ymin+(y2-y1);
389                                 newrct->xmin = rf->xmin;
390                                 newrct->xmax = rf->xmax;
391
392                                 if (newrct->ymin==newrct->ymax) (*count)--;
393
394                                 rf->ymin = y1;
395                         }
396                 }
397                 else if (rf->ymax>y2) {
398                         if (rf->ymin>y2) {
399                                 rf->ymin-= (y2-y1);
400                                 rf->ymax-= (y2-y1);
401                         }
402                         else {
403                                 if (rf->ymin<y1) rf->ymin = y1;
404                                 newrct= stack+ *count;
405                                 (*count)++;
406
407                                 newrct->ymin = y1;
408                                 newrct->ymax = rf->ymax-(y2-y1);
409                                 newrct->xmin = rf->xmin;
410                                 newrct->xmax = rf->xmax;
411
412                                 if (newrct->ymin==newrct->ymax) (*count)--;
413
414                                 rf->ymax = y2;
415                         }
416                 }
417                 rf++;
418         }
419 }
420
421 static float square_rctf(rctf *rf)
422 {
423         float x, y;
424
425         x = BLI_rctf_size_x(rf);
426         y = BLI_rctf_size_y(rf);
427         return x * y;
428 }
429
430 static float clipx_rctf(rctf *rf, float x1, float x2)
431 {
432         float size;
433
434         size = BLI_rctf_size_x(rf);
435
436         if (rf->xmin<x1) {
437                 rf->xmin = x1;
438         }
439         if (rf->xmax>x2) {
440                 rf->xmax = x2;
441         }
442         if (rf->xmin > rf->xmax) {
443                 rf->xmin = rf->xmax;
444                 return 0.0;
445         }
446         else if (size != 0.0f) {
447                 return BLI_rctf_size_x(rf) / size;
448         }
449         return 1.0;
450 }
451
452 static float clipy_rctf(rctf *rf, float y1, float y2)
453 {
454         float size;
455
456         size = BLI_rctf_size_y(rf);
457
458         if (rf->ymin<y1) {
459                 rf->ymin = y1;
460         }
461         if (rf->ymax>y2) {
462                 rf->ymax = y2;
463         }
464
465         if (rf->ymin > rf->ymax) {
466                 rf->ymin = rf->ymax;
467                 return 0.0;
468         }
469         else if (size != 0.0f) {
470                 return BLI_rctf_size_y(rf) / size;
471         }
472         return 1.0;
473
474 }
475
476 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
477 {
478         /* sample box, is clipped already, and minx etc. have been set at ibuf size.
479          * Enlarge with antialiased edges of the pixels */
480
481         float muly, mulx, div, col[4];
482         int x, y, startx, endx, starty, endy;
483
484         startx= (int)floor(rf->xmin);
485         endx= (int)floor(rf->xmax);
486         starty= (int)floor(rf->ymin);
487         endy= (int)floor(rf->ymax);
488
489         if (startx < 0) startx= 0;
490         if (starty < 0) starty= 0;
491         if (endx>=ibuf->x) endx= ibuf->x-1;
492         if (endy>=ibuf->y) endy= ibuf->y-1;
493
494         if (starty==endy && startx==endx) {
495                 ibuf_get_color(&texres->tr, ibuf, startx, starty);
496         }
497         else {
498                 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
499                 for (y=starty; y<=endy; y++) {
500                         
501                         muly= 1.0;
502
503                         if (starty==endy) {
504                                 /* pass */
505                         }
506                         else {
507                                 if (y==starty) muly= 1.0f-(rf->ymin - y);
508                                 if (y==endy) muly= (rf->ymax - y);
509                         }
510                         
511                         if (startx==endx) {
512                                 mulx= muly;
513                                 
514                                 ibuf_get_color(col, ibuf, startx, y);
515
516                                 texres->ta+= mulx*col[3];
517                                 texres->tr+= mulx*col[0];
518                                 texres->tg+= mulx*col[1];
519                                 texres->tb+= mulx*col[2];
520                                 div+= mulx;
521                         }
522                         else {
523                                 for (x=startx; x<=endx; x++) {
524                                         mulx= muly;
525                                         if (x==startx) mulx*= 1.0f-(rf->xmin - x);
526                                         if (x==endx) mulx*= (rf->xmax - x);
527
528                                         ibuf_get_color(col, ibuf, x, y);
529                                         
530                                         if (mulx==1.0f) {
531                                                 texres->ta+= col[3];
532                                                 texres->tr+= col[0];
533                                                 texres->tg+= col[1];
534                                                 texres->tb+= col[2];
535                                                 div+= 1.0f;
536                                         }
537                                         else {
538                                                 texres->ta+= mulx*col[3];
539                                                 texres->tr+= mulx*col[0];
540                                                 texres->tg+= mulx*col[1];
541                                                 texres->tb+= mulx*col[2];
542                                                 div+= mulx;
543                                         }
544                                 }
545                         }
546                 }
547
548                 if (div!=0.0f) {
549                         div= 1.0f/div;
550                         texres->tb*= div;
551                         texres->tg*= div;
552                         texres->tr*= div;
553                         texres->ta*= div;
554                 }
555                 else {
556                         texres->tr= texres->tg= texres->tb= texres->ta= 0.0f;
557                 }
558         }
559 }
560
561 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
562 {
563         /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
564          * Enlarge with antialiased edges of pixels.
565          * If variable 'imaprepeat' has been set, the
566          * clipped-away parts are sampled as well.
567          */
568         /* note: actually minx etc isn't in the proper range... this due to filter size and offset vectors for bump */
569         /* note: talpha must be initialized */
570         /* note: even when 'imaprepeat' is set, this can only repeat once in any direction.
571          * the point which min/max is derived from is assumed to be wrapped */
572         TexResult texr;
573         rctf *rf, stack[8];
574         float opp, tot, alphaclip= 1.0;
575         short count=1;
576
577         rf= stack;
578         rf->xmin = minx*(ibuf->x);
579         rf->xmax = maxx*(ibuf->x);
580         rf->ymin = miny*(ibuf->y);
581         rf->ymax = maxy*(ibuf->y);
582
583         texr.talpha= texres->talpha;    /* is read by boxsample_clip */
584         
585         if (imapextend) {
586                 CLAMP(rf->xmin, 0.0f, ibuf->x-1);
587                 CLAMP(rf->xmax, 0.0f, ibuf->x-1);
588         }
589         else if (imaprepeat)
590                 clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
591         else {
592                 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
593
594                 if (alphaclip<=0.0f) {
595                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
596                         return;
597                 }
598         }
599
600         if (imapextend) {
601                 CLAMP(rf->ymin, 0.0f, ibuf->y-1);
602                 CLAMP(rf->ymax, 0.0f, ibuf->y-1);
603         }
604         else if (imaprepeat)
605                 clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
606         else {
607                 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
608
609                 if (alphaclip<=0.0f) {
610                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
611                         return;
612                 }
613         }
614
615         if (count>1) {
616                 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
617                 while (count--) {
618                         boxsampleclip(ibuf, rf, &texr);
619                         
620                         opp= square_rctf(rf);
621                         tot+= opp;
622
623                         texres->tr+= opp*texr.tr;
624                         texres->tg+= opp*texr.tg;
625                         texres->tb+= opp*texr.tb;
626                         if (texres->talpha) texres->ta+= opp*texr.ta;
627                         rf++;
628                 }
629                 if (tot!= 0.0f) {
630                         texres->tr/= tot;
631                         texres->tg/= tot;
632                         texres->tb/= tot;
633                         if (texres->talpha) texres->ta/= tot;
634                 }
635         }
636         else
637                 boxsampleclip(ibuf, rf, texres);
638
639         if (texres->talpha==0) texres->ta= 1.0;
640         
641         if (alphaclip!=1.0f) {
642                 /* premul it all */
643                 texres->tr*= alphaclip;
644                 texres->tg*= alphaclip;
645                 texres->tb*= alphaclip;
646                 texres->ta*= alphaclip;
647         }
648 }       
649
650 /*-----------------------------------------------------------------------------------------------------------------
651  * from here, some functions only used for the new filtering */
652
653 /* anisotropic filters, data struct used instead of long line of (possibly unused) func args */
654 typedef struct afdata_t {
655         float dxt[2], dyt[2];
656         int intpol, extflag;
657         /* feline only */
658         float majrad, minrad, theta;
659         int iProbes;
660         float dusc, dvsc;
661 } afdata_t;
662
663 /* this only used here to make it easier to pass extend flags as single int */
664 enum {TXC_XMIR = 1, TXC_YMIR, TXC_REPT, TXC_EXTD};
665
666 /* similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
667  * returns true if out of range in clipmode */
668 static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
669 {
670         int clip = 0;
671         switch (extflag) {
672                 case TXC_XMIR:  /* y rep */
673                         x %= 2*ibuf->x;
674                         x += x < 0 ? 2*ibuf->x : 0;
675                         x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x;
676                         y %= ibuf->y;
677                         y += y < 0 ? ibuf->y : 0;
678                         break;
679                 case TXC_YMIR:  /* x rep */
680                         x %= ibuf->x;
681                         x += x < 0 ? ibuf->x : 0;
682                         y %= 2*ibuf->y;
683                         y += y < 0 ? 2*ibuf->y : 0;
684                         y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y;
685                         break;
686                 case TXC_EXTD:
687                         x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
688                         y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
689                         break;
690                 case TXC_REPT:
691                         x %= ibuf->x;
692                         x += (x < 0) ? ibuf->x : 0;
693                         y %= ibuf->y;
694                         y += (y < 0) ? ibuf->y : 0;
695                         break;
696                 default:
697                 {       /* as extend, if clipped, set alpha to 0.0 */
698                         if (x < 0) { x = 0;  } /* TXF alpha: clip = 1; } */
699                         if (x >= ibuf->x) { x = ibuf->x - 1; } /* TXF alpha:  clip = 1; } */
700                         if (y < 0) { y = 0; } /* TXF alpha:  clip = 1; } */
701                         if (y >= ibuf->y) { y = ibuf->y - 1; } /* TXF alpha:  clip = 1; } */
702                 }
703         }
704
705         if (ibuf->rect_float) {
706                 const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
707                 if (ibuf->channels == 1)
708                         col[0] = col[1] = col[2] = col[3] = *fp;
709                 else {
710                         col[0] = fp[0];
711                         col[1] = fp[1];
712                         col[2] = fp[2];
713                         col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
714                 }
715         }
716         else {
717                 char *rect = (char *)(ibuf->rect + x + y*ibuf->x);
718                 float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
719                 col[0] = rect[0] * inv_alpha_fac;
720                 col[1] = rect[1] * inv_alpha_fac;
721                 col[2] = rect[2] * inv_alpha_fac;
722                 col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
723         }
724         return clip;
725 }
726
727 /* as above + bilerp */
728 static int ibuf_get_color_clip_bilerp(float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
729 {
730         if (intpol) {
731                 float c00[4], c01[4], c10[4], c11[4];
732                 const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
733                 const float uf = u - ufl, vf = v - vfl;
734                 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
735                 const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
736                 int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
737                 clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
738                 clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
739                 clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
740                 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
741                 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
742                 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
743                 col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
744                 return clip;
745         }
746         return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
747 }
748
749 static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
750 {
751         int xs, ys, clip = 0;
752         float tc[4], xsd, ysd, cw = 0.f;
753         const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1];
754         const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1];
755         int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f);
756         int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f);
757         const int minsam = AFD->intpol ? 2 : 4;
758         xsam = CLAMPIS(xsam, minsam, ibuf->x*2);
759         ysam = CLAMPIS(ysam, minsam, ibuf->y*2);
760         xsd = 1.f / xsam;
761         ysd = 1.f / ysam;
762         texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
763         for (ys=0; ys<ysam; ++ys) {
764                 for (xs=0; xs<xsam; ++xs) {
765                         const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f;
766                         const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f;
767                         const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0];
768                         const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1];
769                         const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag);
770                         clip |= out;
771                         cw += out ? 0.f : 1.f;
772                         texr->tr += tc[0];
773                         texr->tg += tc[1];
774                         texr->tb += tc[2];
775                         texr->ta += texr->talpha ? tc[3] : 0.f;
776                 }
777         }
778         xsd *= ysd;
779         texr->tr *= xsd;
780         texr->tg *= xsd;
781         texr->tb *= xsd;
782         /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
783         texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
784 }
785
786 /* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
787  * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */
788 #define EWA_MAXIDX 255
789 static float EWA_WTS[EWA_MAXIDX + 1] = {
790         1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
791         0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
792         0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
793         0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
794         0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
795         0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
796         0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
797         0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
798         0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
799         0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
800         0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
801         0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
802         0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
803         0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
804         0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
805         0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
806         0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
807         0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
808         0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
809         0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
810         0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
811         0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
812         0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
813         0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
814         0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
815         0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
816         0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
817         0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
818         0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
819         0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
820         0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
821         0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
822 };
823
824 /* test if a float value is 'nan'
825  * there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
826  * and may not be supported by other compilers either */
827 #ifndef ISNAN
828 #define ISNAN(x) ((x) != (x))
829 #endif
830 //static int ISNAN(float x) { return (x != x); }
831
832 static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F)
833 {
834         float ct2 = cosf(th);
835         const float st2 = 1.0f - ct2 * ct2;     /* <- sin(th)^2 */
836         ct2 *= ct2;
837         *A = a2*st2 + b2*ct2;
838         *B = (b2 - a2)*sinf(2.f*th);
839         *C = a2*ct2 + b2*st2;
840         *F = a2*b2;
841 }
842
843 /* all tests here are done to make sure possible overflows are hopefully minimized */
844 static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc)
845 {
846         if (F <= 1e-5f) {       /* use arbitrary major radius, zero minor, infinite eccentricity */
847                 *a = sqrtf(A > C ? A : C);
848                 *b = 0.f;
849                 *ecc = 1e10f;
850                 *th = 0.5f*(atan2f(B, A - C) + (float)M_PI);
851         }
852         else {
853                 const float AmC = A - C, ApC = A + C, F2 = F*2.f;
854                 const float r = sqrtf(AmC*AmC + B*B);
855                 float d = ApC - r;
856                 *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
857                 d = ApC + r;
858                 if (d <= 0.f) {
859                         *b = 0.f;
860                         *ecc = 1e10f;
861                 }
862                 else {
863                         *b = sqrtf(F2 / d);
864                         *ecc = *a / *b;
865                 }
866                 /* incr theta by 0.5*pi (angle of major axis) */
867                 *th = 0.5f*(atan2f(B, AmC) + (float)M_PI);
868         }
869 }
870
871 static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
872 {
873         /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
874          * scaling by aspect ratio alone does the opposite, so try something in between instead... */
875         const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff;
876         const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q;
877         float A = Vx*Vx + Vy*Vy;
878         float B = -2.f*(Ux*Vx + Uy*Vy);
879         float C = Ux*Ux + Uy*Uy;
880         float F = A*C - B*B*0.25f;
881         float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; /* TXF alpha: cw = 0.f; */
882         int u, v, u1, u2, v1, v2; /* TXF alpha: clip = 0; */
883
884         /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
885          * so the ellipse always covers at least some texels. But since the filter is now always larger,
886          * it also means that everywhere else it's also more blurry then ideally should be the case.
887          * So instead here the ellipse radii are modified instead whenever either is too low.
888          * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
889          * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
890          * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */
891         const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2;
892         imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
893         if ((b2 = b*b) < rmin) {
894                 if ((a2 = a*a) < rmin) {
895                         B = 0.f;
896                         A = C = rmin;
897                         F = A*C;
898                 }
899                 else {
900                         b2 = rmin;
901                         radangle2imp(a2, b2, th, &A, &B, &C, &F);
902                 }
903         }
904
905         ue = ff*sqrtf(C);
906         ve = ff*sqrtf(A);
907         d = (float)(EWA_MAXIDX + 1) / (F*ff2);
908         A *= d;
909         B *= d;
910         C *= d;
911
912         U0 = fx*ibuf->x;
913         V0 = fy*ibuf->y;
914         u1 = (int)(floorf(U0 - ue));
915         u2 = (int)(ceilf(U0 + ue));
916         v1 = (int)(floorf(V0 - ve));
917         v2 = (int)(ceilf(V0 + ve));
918         U0 -= 0.5f;
919         V0 -= 0.5f;
920         DDQ = 2.f*A;
921         U = u1 - U0;
922         ac1 = A*(2.f*U + 1.f);
923         ac2 = A*U*U;
924         BU = B*U;
925
926         d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
927         for (v=v1; v<=v2; ++v) {
928                 const float V = v - V0;
929                 float DQ = ac1 + B*V;
930                 float Q = (C*V + BU)*V + ac2;
931                 for (u=u1; u<=u2; ++u) {
932                         if (Q < (float)(EWA_MAXIDX + 1)) {
933                                 float tc[4];
934                                 const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
935                                 /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag);
936                                 /* TXF alpha: clip |= out;
937                                  * TXF alpha: cw += out ? 0.f : wt; */
938                                 texr->tr += tc[0]*wt;
939                                 texr->tg += tc[1]*wt;
940                                 texr->tb += tc[2]*wt;
941                                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
942                                 d += wt;
943                         }
944                         Q += DQ;
945                         DQ += DDQ;
946                 }
947         }
948
949         /* d should hopefully never be zero anymore */
950         d = 1.f/d;
951         texr->tr *= d;
952         texr->tg *= d;
953         texr->tb *= d;
954         /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
955         texr->ta = texr->talpha ? texr->ta*d : 1.f; /* TXF alpha (clip ? cw*d : 1.f); */
956 }
957
958 static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
959 {
960         const int maxn = AFD->iProbes - 1;
961         const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
962         float du = maxn ? cosf(AFD->theta)*ll : 0.f;
963         float dv = maxn ? sinf(AFD->theta)*ll : 0.f;
964         /* const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); */
965         const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
966         float d; /* TXF alpha: cw = 0.f; */
967         int n; /* TXF alpha: clip = 0; */
968         /* have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) */
969         du *= AFD->dusc;
970         dv *= AFD->dvsc;
971         d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
972         for (n=-maxn; n<=maxn; n+=2) {
973                 float tc[4];
974                 const float hn = n*0.5f;
975                 const float u = fx + hn*du, v = fy + hn*dv;
976                 /*const float wt = expf(n*n*D);
977                  * can use ewa table here too */
978                 const float wt = EWA_WTS[(int)(n*n*D)];
979                 /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag);
980                 /* TXF alpha: clip |= out;
981                  * TXF alpha: cw += out ? 0.f : wt; */
982                 texr->tr += tc[0]*wt;
983                 texr->tg += tc[1]*wt;
984                 texr->tb += tc[2]*wt;
985                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
986                 d += wt;
987         }
988
989         d = 1.f/d;
990         texr->tr *= d;
991         texr->tg *= d;
992         texr->tb *= d;
993         /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
994         texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
995 }
996 #undef EWA_MAXIDX
997
998 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
999 {
1000         float alphaclip;
1001         rctf rf;
1002
1003         /* TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
1004          * if this is actually correct for the all the filtering algorithms .. */
1005
1006         if (!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
1007                 rf.xmin = minx*(ibuf->x);
1008                 rf.xmax = maxx*(ibuf->x);
1009                 rf.ymin = miny*(ibuf->y);
1010                 rf.ymax = maxy*(ibuf->y);
1011
1012                 alphaclip  = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
1013                 alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
1014                 alphaclip  = max_ff(alphaclip, 0.0f);
1015
1016                 if (alphaclip!=1.0f) {
1017                         /* premul it all */
1018                         texres->tr*= alphaclip;
1019                         texres->tg*= alphaclip;
1020                         texres->tb*= alphaclip;
1021                         texres->ta*= alphaclip;
1022                 }
1023         }
1024 }
1025
1026 static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
1027 {
1028         if (tex->imaflag & TEX_MIPMAP) {
1029                 if ((ibuf->flags & IB_fields) == 0) {
1030                         
1031                         if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
1032                                 BLI_lock_thread(LOCK_IMAGE);
1033                                 if (ibuf->userflags & IB_MIPMAP_INVALID) {
1034                                         IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1035                                         ibuf->userflags &= ~IB_MIPMAP_INVALID;
1036                                 }
1037                                 BLI_unlock_thread(LOCK_IMAGE);
1038                         }
1039                         if (ibuf->mipmap[0] == NULL) {
1040                                 BLI_lock_thread(LOCK_IMAGE);
1041                                 if (ibuf->mipmap[0] == NULL) 
1042                                         IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1043                                 BLI_unlock_thread(LOCK_IMAGE);
1044                         }
1045                 }
1046         }
1047         
1048 }
1049
1050 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool)
1051 {
1052         TexResult texr;
1053         float fx, fy, minx, maxx, miny, maxy;
1054         float maxd, val1, val2, val3;
1055         int curmap, retval, intpol, extflag = 0;
1056         afdata_t AFD;
1057
1058         void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
1059         switch (tex->texfilter) {
1060                 case TXF_EWA:
1061                         filterfunc = ewa_eval;
1062                         break;
1063                 case TXF_FELINE:
1064                         filterfunc = feline_eval;
1065                         break;
1066                 case TXF_AREA:
1067                 default:
1068                         filterfunc = area_sample;
1069         }
1070
1071         texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
1072
1073         /* we need to set retval OK, otherwise texture code generates normals itself... */
1074         retval = texres->nor ? 3 : 1;
1075
1076         /* quick tests */
1077         if (ibuf==NULL && ima==NULL) return retval;
1078
1079         if (ima) {      /* hack for icon render */
1080                 if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
1081                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
1082         }
1083
1084         if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
1085                 if (ima)
1086                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1087                 return retval;
1088         }
1089
1090         if (ima) {
1091                 ima->flag |= IMA_USED_FOR_RENDER;
1092         }
1093
1094         /* mipmap test */
1095         image_mipmap_test(tex, ibuf);
1096         
1097         if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
1098                 if ((tex->imaflag & TEX_CALCALPHA) == 0)
1099                         texres->talpha = 1;
1100         }
1101         texr.talpha = texres->talpha;
1102
1103         if (tex->imaflag & TEX_IMAROT) {
1104                 fy = texvec[0];
1105                 fx = texvec[1];
1106         }
1107         else {
1108                 fx = texvec[0];
1109                 fy = texvec[1];
1110         }
1111
1112         if (ibuf->flags & IB_fields) {
1113                 if (R.r.mode & R_FIELDS) {                      /* field render */
1114                         if (R.flag & R_SEC_FIELD) {             /* correction for 2nd field */
1115                                 /* fac1= 0.5/( (float)ibuf->y ); */
1116                                 /* fy-= fac1; */
1117                         }
1118                         else    /* first field */
1119                                 fy += 0.5f/( (float)ibuf->y );
1120                 }
1121         }
1122
1123         /* pixel coordinates */
1124         minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1125         maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1126         miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1127         maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1128
1129         /* tex_sharper has been removed */
1130         minx = (maxx - minx)*0.5f;
1131         miny = (maxy - miny)*0.5f;
1132
1133         if (tex->imaflag & TEX_FILTER_MIN) {
1134                 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
1135                 const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
1136                 if (addval > minx) minx = addval;
1137                 if (addval > miny) miny = addval;
1138         }
1139         else if (tex->filtersize != 1.f) {
1140                 minx *= tex->filtersize;
1141                 miny *= tex->filtersize;
1142                 dxt[0] *= tex->filtersize;
1143                 dxt[1] *= tex->filtersize;
1144                 dyt[0] *= tex->filtersize;
1145                 dyt[1] *= tex->filtersize;
1146         }
1147
1148         if (tex->imaflag & TEX_IMAROT) {
1149                 float t;
1150                 SWAP(float, minx, miny);
1151                 /* must rotate dxt/dyt 90 deg
1152                  * yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
1153                  * but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. */
1154                 t = dxt[0];
1155                 dxt[0] = dxt[1];
1156                 dxt[1] = -t;
1157                 t = dyt[0];
1158                 dyt[0] = dyt[1];
1159                 dyt[1] = -t;
1160         }
1161
1162         /* side faces of unit-cube */
1163         minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
1164         miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
1165
1166         /* repeat and clip */
1167
1168         if (tex->extend == TEX_REPEAT) {
1169                 if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
1170                         extflag = TXC_EXTD;
1171                 else if (tex->flag & TEX_REPEAT_XMIR)
1172                         extflag = TXC_XMIR;
1173                 else if (tex->flag & TEX_REPEAT_YMIR)
1174                         extflag = TXC_YMIR;
1175                 else
1176                         extflag = TXC_REPT;
1177         }
1178         else if (tex->extend == TEX_EXTEND)
1179                 extflag = TXC_EXTD;
1180
1181         if (tex->extend == TEX_CHECKER) {
1182                 int xs = (int)floorf(fx), ys = (int)floorf(fy);
1183                 /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1184                 if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1185                         fx -= xs;
1186                         fy -= ys;
1187                 }
1188                 else {
1189                         int xs1 = (int)floorf(fx - minx);
1190                         int ys1 = (int)floorf(fy - miny);
1191                         int xs2 = (int)floorf(fx + minx);
1192                         int ys2 = (int)floorf(fy + miny);
1193                         if ((xs1 != xs2) || (ys1 != ys2)) {
1194                                 if (tex->flag & TEX_CHECKER_ODD) {
1195                                         fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
1196                                         fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
1197                                 }
1198                                 if (tex->flag & TEX_CHECKER_EVEN) {
1199                                         fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
1200                                         fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
1201                                 }
1202                         }
1203                         else {
1204                                 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
1205                                         if (ima)
1206                                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1207                                         return retval;
1208                                 }
1209                                 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
1210                                         if (ima)
1211                                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1212                                         return retval;
1213                                 }
1214                                 fx -= xs;
1215                                 fy -= ys;
1216                         }
1217                 }
1218                 /* scale around center, (0.5, 0.5) */
1219                 if (tex->checkerdist < 1.f) {
1220                         const float omcd = 1.f / (1.f - tex->checkerdist);
1221                         fx = (fx - 0.5f)*omcd + 0.5f;
1222                         fy = (fy - 0.5f)*omcd + 0.5f;
1223                         minx *= omcd;
1224                         miny *= omcd;
1225                 }
1226         }
1227
1228         if (tex->extend == TEX_CLIPCUBE) {
1229                 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) {
1230                         if (ima)
1231                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1232                         return retval;
1233                 }
1234         }
1235         else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
1236                 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
1237                         if (ima)
1238                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1239                         return retval;
1240                 }
1241         }
1242         else {
1243                 if (tex->extend == TEX_EXTEND) {
1244                         fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
1245                         fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
1246                 }
1247                 else {
1248                         fx -= floorf(fx);
1249                         fy -= floorf(fy);
1250                 }
1251         }
1252
1253         intpol = tex->imaflag & TEX_INTERPOL;
1254
1255         /* warning no return! */
1256         if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1257                 ibuf->rect += ibuf->x*ibuf->y;
1258
1259         /* struct common data */
1260         copy_v2_v2(AFD.dxt, dxt);
1261         copy_v2_v2(AFD.dyt, dyt);
1262         AFD.intpol = intpol;
1263         AFD.extflag = extflag;
1264
1265         /* brecht: added stupid clamping here, large dx/dy can give very large
1266          * filter sizes which take ages to render, it may be better to do this
1267          * more intelligently later in the code .. probably it's not noticeable */
1268         if (AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f)
1269                 mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
1270         if (AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
1271                 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
1272
1273         /* choice: */
1274         if (tex->imaflag & TEX_MIPMAP) {
1275                 ImBuf *previbuf, *curibuf;
1276                 float levf;
1277                 int maxlev;
1278                 ImBuf *mipmaps[IB_MIPMAP_LEVELS + 1];
1279
1280                 /* modify ellipse minor axis if too eccentric, use for area sampling as well
1281                  * scaling dxt/dyt as done in pbrt is not the same
1282                  * (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) */
1283                 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1284                 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1285                 const float A = Vx*Vx + Vy*Vy;
1286                 const float B = -2.f*(Ux*Vx + Uy*Vy);
1287                 const float C = Ux*Ux + Uy*Uy;
1288                 const float F = A*C - B*B*0.25f;
1289                 float a, b, th, ecc;
1290                 imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1291                 if (tex->texfilter == TXF_FELINE) {
1292                         float fProbes;
1293                         a *= ff;
1294                         b *= ff;
1295                         a = max_ff(a, 1.0f);
1296                         b = max_ff(b, 1.0f);
1297                         fProbes = 2.f*(a / b) - 1.f;
1298                         AFD.iProbes = (int)floorf(fProbes + 0.5f);
1299                         AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
1300                         if (AFD.iProbes < fProbes)
1301                                 b = 2.f*a / (float)(AFD.iProbes + 1);
1302                         AFD.majrad = a/ff;
1303                         AFD.minrad = b/ff;
1304                         AFD.theta = th;
1305                         AFD.dusc = 1.f/ff;
1306                         AFD.dvsc = ff / (float)ibuf->y;
1307                 }
1308                 else {  /* EWA & area */
1309                         if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
1310                         b *= ff;
1311                 }
1312                 maxd = max_ff(b, 1e-8f);
1313                 levf = ((float)M_LOG2E) * logf(maxd);
1314
1315                 curmap = 0;
1316                 maxlev = 1;
1317                 mipmaps[0] = ibuf;
1318                 while (curmap < IB_MIPMAP_LEVELS) {
1319                         mipmaps[curmap + 1] = ibuf->mipmap[curmap];
1320                         if (ibuf->mipmap[curmap]) maxlev++;
1321                         curmap++;
1322                 }
1323
1324                 /* mipmap level */
1325                 if (levf < 0.f) {  /* original image only */
1326                         previbuf = curibuf = mipmaps[0];
1327                         levf = 0.f;
1328                 }
1329                 else if (levf >= maxlev - 1) {
1330                         previbuf = curibuf = mipmaps[maxlev - 1];
1331                         levf = 0.f;
1332                         if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
1333                 }
1334                 else {
1335                         const int lev = ISNAN(levf) ? 0 : (int)levf;
1336                         curibuf = mipmaps[lev];
1337                         previbuf = mipmaps[lev + 1];
1338                         levf -= floorf(levf);
1339                 }
1340
1341                 /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1342
1343                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1344                         /* color & normal */
1345                         filterfunc(texres, curibuf, fx, fy, &AFD);
1346                         val1 = texres->tr + texres->tg + texres->tb;
1347                         filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
1348                         val2 = texr.tr + texr.tg + texr.tb;
1349                         filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
1350                         val3 = texr.tr + texr.tg + texr.tb;
1351                         /* don't switch x or y! */
1352                         texres->nor[0] = val1 - val2;
1353                         texres->nor[1] = val1 - val3;
1354                         if (previbuf != curibuf) {  /* interpolate */
1355                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1356                                 /* rgb */
1357                                 texres->tr += levf*(texr.tr - texres->tr);
1358                                 texres->tg += levf*(texr.tg - texres->tg);
1359                                 texres->tb += levf*(texr.tb - texres->tb);
1360                                 texres->ta += levf*(texr.ta - texres->ta);
1361                                 /* normal */
1362                                 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
1363                                 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
1364                                 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
1365                                 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
1366                                 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
1367                                 texres->nor[0] = val1 - val2;  /* vals have been interpolated above! */
1368                                 texres->nor[1] = val1 - val3;
1369                         }
1370                 }
1371                 else {  /* color */
1372                         filterfunc(texres, curibuf, fx, fy, &AFD);
1373                         if (previbuf != curibuf) {  /* interpolate */
1374                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1375                                 texres->tr += levf*(texr.tr - texres->tr);
1376                                 texres->tg += levf*(texr.tg - texres->tg);
1377                                 texres->tb += levf*(texr.tb - texres->tb);
1378                                 texres->ta += levf*(texr.ta - texres->ta);
1379                         }
1380
1381                         alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1382                 }
1383         }
1384         else {  /* no mipmap */
1385                 /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1386                 if (tex->texfilter == TXF_FELINE) {
1387                         const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1388                         const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1389                         const float A = Vx*Vx + Vy*Vy;
1390                         const float B = -2.f*(Ux*Vx + Uy*Vy);
1391                         const float C = Ux*Ux + Uy*Uy;
1392                         const float F = A*C - B*B*0.25f;
1393                         float a, b, th, ecc, fProbes;
1394                         imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1395                         a *= ff;
1396                         b *= ff;
1397                         a = max_ff(a, 1.0f);
1398                         b = max_ff(b, 1.0f);
1399                         fProbes = 2.f*(a / b) - 1.f;
1400                         /* no limit to number of Probes here */
1401                         AFD.iProbes = (int)floorf(fProbes + 0.5f);
1402                         if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
1403                         AFD.majrad = a/ff;
1404                         AFD.minrad = b/ff;
1405                         AFD.theta = th;
1406                         AFD.dusc = 1.f/ff;
1407                         AFD.dvsc = ff / (float)ibuf->y;
1408                 }
1409                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1410                         /* color & normal */
1411                         filterfunc(texres, ibuf, fx, fy, &AFD);
1412                         val1 = texres->tr + texres->tg + texres->tb;
1413                         filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
1414                         val2 = texr.tr + texr.tg + texr.tb;
1415                         filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
1416                         val3 = texr.tr + texr.tg + texr.tb;
1417                         /* don't switch x or y! */
1418                         texres->nor[0] = val1 - val2;
1419                         texres->nor[1] = val1 - val3;
1420                 }
1421                 else {
1422                         filterfunc(texres, ibuf, fx, fy, &AFD);
1423                         alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1424                 }
1425         }
1426
1427         if (tex->imaflag & TEX_CALCALPHA)
1428                 texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
1429         else
1430                 texres->tin = texres->ta;
1431         if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
1432         
1433         if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1434                 ibuf->rect -= ibuf->x*ibuf->y;
1435
1436         if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {    /* normal from color */
1437                 /* The invert of the red channel is to make
1438                  * the normal map compliant with the outside world.
1439                  * It needs to be done because in Blender
1440                  * the normal used in the renderer points inward. It is generated
1441                  * this way in calc_vertexnormals(). Should this ever change
1442                  * this negate must be removed. */
1443                 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1444                 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1445                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1446         }
1447
1448         /* de-premul, this is being premulled in shade_input_do_shade()
1449          * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
1450          * also disabled in imagewraposa() to be able to compare results with blender's default texture filtering */
1451
1452         /* brecht: tried to fix this, see "TXF alpha" comments */
1453
1454         if (texres->ta != 1.f && (texres->ta > 1e-4f)) {
1455                 fx = 1.f/texres->ta;
1456                 texres->tr *= fx;
1457                 texres->tg *= fx;
1458                 texres->tb *= fx;
1459         }
1460
1461         if (ima)
1462                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1463
1464         BRICONTRGB;
1465         
1466         return retval;
1467 }
1468
1469
1470 int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool)
1471 {
1472         TexResult texr;
1473         float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
1474         float maxd, pixsize, val1, val2, val3;
1475         int curmap, retval, imaprepeat, imapextend;
1476
1477         /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
1478          * make a local copy here so that original vecs remain untouched */
1479         copy_v2_v2(dxt, DXT);
1480         copy_v2_v2(dyt, DYT);
1481
1482         /* anisotropic filtering */
1483         if (tex->texfilter != TXF_BOX)
1484                 return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
1485
1486         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
1487         
1488         /* we need to set retval OK, otherwise texture code generates normals itself... */
1489         retval= texres->nor?3:1;
1490         
1491         /* quick tests */
1492         if (ibuf==NULL && ima==NULL)
1493                 return retval;
1494         if (ima) {
1495
1496                 /* hack for icon render */
1497                 if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
1498                         return retval;
1499                 
1500                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
1501
1502                 ima->flag|= IMA_USED_FOR_RENDER;
1503         }
1504         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
1505                 if (ima)
1506                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1507                 return retval;
1508         }
1509         
1510         /* mipmap test */
1511         image_mipmap_test(tex, ibuf);
1512
1513         if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
1514                 if ((tex->imaflag & TEX_CALCALPHA) == 0) {
1515                         texres->talpha = TRUE;
1516                 }
1517         }
1518         
1519         texr.talpha= texres->talpha;
1520         
1521         if (tex->imaflag & TEX_IMAROT) {
1522                 fy= texvec[0];
1523                 fx= texvec[1];
1524         }
1525         else {
1526                 fx= texvec[0];
1527                 fy= texvec[1];
1528         }
1529         
1530         if (ibuf->flags & IB_fields) {
1531                 if (R.r.mode & R_FIELDS) {                      /* field render */
1532                         if (R.flag & R_SEC_FIELD) {             /* correction for 2nd field */
1533                                 /* fac1= 0.5/( (float)ibuf->y ); */
1534                                 /* fy-= fac1; */
1535                         }
1536                         else {                          /* first field */
1537                                 fy+= 0.5f/( (float)ibuf->y );
1538                         }
1539                 }
1540         }
1541         
1542         /* pixel coordinates */
1543
1544         minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1545         maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1546         miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1547         maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1548
1549         /* tex_sharper has been removed */
1550         minx= (maxx-minx)/2.0f;
1551         miny= (maxy-miny)/2.0f;
1552         
1553         if (tex->imaflag & TEX_FILTER_MIN) {
1554                 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
1555                 float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);
1556
1557                 if (addval > minx)
1558                         minx= addval;
1559                 if (addval > miny)
1560                         miny= addval;
1561         }
1562         else if (tex->filtersize!=1.0f) {
1563                 minx*= tex->filtersize;
1564                 miny*= tex->filtersize;
1565                 
1566                 dxt[0]*= tex->filtersize;
1567                 dxt[1]*= tex->filtersize;
1568                 dyt[0]*= tex->filtersize;
1569                 dyt[1]*= tex->filtersize;
1570         }
1571
1572         if (tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
1573         
1574         if (minx>0.25f) minx= 0.25f;
1575         else if (minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */
1576         if (miny>0.25f) miny= 0.25f;
1577         else if (miny<0.00001f) miny= 0.00001f;
1578
1579         
1580         /* repeat and clip */
1581         imaprepeat= (tex->extend==TEX_REPEAT);
1582         imapextend= (tex->extend==TEX_EXTEND);
1583
1584         if (tex->extend == TEX_REPEAT) {
1585                 if (tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
1586                         imaprepeat= 0;
1587                         imapextend= 1;
1588                 }
1589         }
1590
1591         if (tex->extend == TEX_CHECKER) {
1592                 int xs, ys, xs1, ys1, xs2, ys2, boundary;
1593                 
1594                 xs= (int)floor(fx);
1595                 ys= (int)floor(fy);
1596                 
1597                 /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1598                 if ( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
1599                         fx-= xs;
1600                         fy-= ys;
1601                 }
1602                 else {
1603                         
1604                         xs1= (int)floor(fx-minx);
1605                         ys1= (int)floor(fy-miny);
1606                         xs2= (int)floor(fx+minx);
1607                         ys2= (int)floor(fy+miny);
1608                         boundary= (xs1!=xs2) || (ys1!=ys2);
1609
1610                         if (boundary==0) {
1611                                 if ( (tex->flag & TEX_CHECKER_ODD)==0) {
1612                                         if ((xs + ys) & 1) {
1613                                                 /* pass */
1614                                         }
1615                                         else {
1616                                                 if (ima)
1617                                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1618                                                 return retval;
1619                                         }
1620                                 }
1621                                 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
1622                                         if ((xs + ys) & 1) {
1623                                                 if (ima)
1624                                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1625                                                 return retval;
1626                                         }
1627                                 }
1628                                 fx-= xs;
1629                                 fy-= ys;
1630                         }
1631                         else {
1632                                 if (tex->flag & TEX_CHECKER_ODD) {
1633                                         if ((xs1+ys) & 1) fx-= xs2;
1634                                         else fx-= xs1;
1635                                         
1636                                         if ((ys1+xs) & 1) fy-= ys2;
1637                                         else fy-= ys1;
1638                                 }
1639                                 if (tex->flag & TEX_CHECKER_EVEN) {
1640                                         if ((xs1+ys) & 1) fx-= xs1;
1641                                         else fx-= xs2;
1642                                         
1643                                         if ((ys1+xs) & 1) fy-= ys1;
1644                                         else fy-= ys2;
1645                                 }
1646                         }
1647                 }
1648
1649                 /* scale around center, (0.5, 0.5) */
1650                 if (tex->checkerdist<1.0f) {
1651                         fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1652                         fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1653                         minx/= (1.0f-tex->checkerdist);
1654                         miny/= (1.0f-tex->checkerdist);
1655                 }
1656         }
1657
1658         if (tex->extend == TEX_CLIPCUBE) {
1659                 if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
1660                         if (ima)
1661                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1662                         return retval;
1663                 }
1664         }
1665         else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
1666                 if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
1667                         if (ima)
1668                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1669                         return retval;
1670                 }
1671         }
1672         else {
1673                 if (imapextend) {
1674                         if (fx>1.0f) fx = 1.0f;
1675                         else if (fx<0.0f) fx= 0.0f;
1676                 }
1677                 else {
1678                         if (fx>1.0f) fx -= (int)(fx);
1679                         else if (fx<0.0f) fx+= 1-(int)(fx);
1680                 }
1681                 
1682                 if (imapextend) {
1683                         if (fy>1.0f) fy = 1.0f;
1684                         else if (fy<0.0f) fy= 0.0f;
1685                 }
1686                 else {
1687                         if (fy>1.0f) fy -= (int)(fy);
1688                         else if (fy<0.0f) fy+= 1-(int)(fy);
1689                 }
1690         }
1691
1692         /* warning no return! */
1693         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1694                 ibuf->rect+= (ibuf->x*ibuf->y);
1695         }
1696
1697         /* choice:  */
1698         if (tex->imaflag & TEX_MIPMAP) {
1699                 ImBuf *previbuf, *curibuf;
1700                 float bumpscale;
1701                 
1702                 dx = minx;
1703                 dy = miny;
1704                 maxd = max_ff(dx, dy);
1705                 if (maxd > 0.5f) maxd = 0.5f;
1706
1707                 pixsize = 1.0f / (float) MIN2(ibuf->x, ibuf->y);
1708                 
1709                 bumpscale= pixsize/maxd;
1710                 if (bumpscale>1.0f) bumpscale= 1.0f;
1711                 else bumpscale*=bumpscale;
1712                 
1713                 curmap= 0;
1714                 previbuf= curibuf= ibuf;
1715                 while (curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
1716                         if (maxd < pixsize) break;
1717                         previbuf= curibuf;
1718                         curibuf= ibuf->mipmap[curmap];
1719                         pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
1720                         curmap++;
1721                 }
1722
1723                 if (previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
1724                         /* sample at least 1 pixel */
1725                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1726                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1727                 }
1728                 
1729                 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1730                         /* a bit extra filter */
1731                         //minx*= 1.35f;
1732                         //miny*= 1.35f;
1733                         
1734                         boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1735                         val1= texres->tr+texres->tg+texres->tb;
1736                         boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1737                         val2= texr.tr + texr.tg + texr.tb;
1738                         boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1739                         val3= texr.tr + texr.tg + texr.tb;
1740
1741                         /* don't switch x or y! */
1742                         texres->nor[0]= (val1-val2);
1743                         texres->nor[1]= (val1-val3);
1744                         
1745                         if (previbuf!=curibuf) {  /* interpolate */
1746                                 
1747                                 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend);
1748                                 
1749                                 /* calc rgb */
1750                                 dx= 2.0f*(pixsize-maxd)/pixsize;
1751                                 if (dx>=1.0f) {
1752                                         texres->ta= texr.ta; texres->tb= texr.tb;
1753                                         texres->tg= texr.tg; texres->tr= texr.tr;
1754                                 }
1755                                 else {
1756                                         dy= 1.0f-dx;
1757                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1758                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1759                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1760                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1761                                 }
1762                                 
1763                                 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
1764                                 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1765                                 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
1766                                 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1767                                 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
1768                                 
1769                                 texres->nor[0]= (val1-val2);    /* vals have been interpolated above! */
1770                                 texres->nor[1]= (val1-val3);
1771                                 
1772                                 if (dx<1.0f) {
1773                                         dy= 1.0f-dx;
1774                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1775                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1776                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1777                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1778                                 }
1779                         }
1780                         texres->nor[0]*= bumpscale;
1781                         texres->nor[1]*= bumpscale;
1782                 }
1783                 else {
1784                         maxx= fx+minx;
1785                         minx= fx-minx;
1786                         maxy= fy+miny;
1787                         miny= fy-miny;
1788
1789                         boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
1790
1791                         if (previbuf!=curibuf) {  /* interpolate */
1792                                 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
1793                                 
1794                                 fx= 2.0f*(pixsize-maxd)/pixsize;
1795                                 
1796                                 if (fx>=1.0f) {
1797                                         texres->ta= texr.ta; texres->tb= texr.tb;
1798                                         texres->tg= texr.tg; texres->tr= texr.tr;
1799                                 }
1800                                 else {
1801                                         fy= 1.0f-fx;
1802                                         texres->tb= fy*texres->tb+ fx*texr.tb;
1803                                         texres->tg= fy*texres->tg+ fx*texr.tg;
1804                                         texres->tr= fy*texres->tr+ fx*texr.tr;
1805                                         texres->ta= fy*texres->ta+ fx*texr.ta;
1806                                 }
1807                         }
1808                 }
1809         }
1810         else {
1811                 const int intpol = tex->imaflag & TEX_INTERPOL;
1812                 if (intpol) {
1813                         /* sample 1 pixel minimum */
1814                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1815                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1816                 }
1817
1818                 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1819                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1820                         val1= texres->tr+texres->tg+texres->tb;
1821                         boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1822                         val2= texr.tr + texr.tg + texr.tb;
1823                         boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1824                         val3= texr.tr + texr.tg + texr.tb;
1825
1826                         /* don't switch x or y! */
1827                         texres->nor[0]= (val1-val2);
1828                         texres->nor[1]= (val1-val3);
1829                 }
1830                 else
1831                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1832         }
1833         
1834         if (tex->imaflag & TEX_CALCALPHA) {
1835                 texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
1836         }
1837         else texres->tin= texres->ta;
1838
1839         if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
1840         
1841         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1842                 ibuf->rect-= (ibuf->x*ibuf->y);
1843         }
1844
1845         if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
1846                 /* qdn: normal from color
1847                  * The invert of the red channel is to make
1848                  * the normal map compliant with the outside world.
1849                  * It needs to be done because in Blender
1850                  * the normal used in the renderer points inward. It is generated
1851                  * this way in calc_vertexnormals(). Should this ever change
1852                  * this negate must be removed. */
1853                 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1854                 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1855                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1856         }
1857
1858         /* de-premul, this is being premulled in shade_input_do_shade() */
1859         if (texres->ta != 1.0f && texres->ta > 1e-4f) {
1860                 mul_v3_fl(&texres->tr, 1.0f / texres->ta);
1861         }
1862
1863         if (ima)
1864                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1865
1866         BRICONTRGB;
1867         
1868         return retval;
1869 }
1870
1871 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
1872 {
1873         TexResult texres;
1874         ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
1875         
1876         if (UNLIKELY(ibuf == NULL)) {
1877                 zero_v4(result);
1878                 return;
1879         }
1880         
1881         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
1882                 ibuf->rect+= (ibuf->x*ibuf->y);
1883
1884         texres.talpha = TRUE; /* boxsample expects to be initialized */
1885         boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
1886         copy_v4_v4(result, &texres.tr);
1887         
1888         if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
1889                 ibuf->rect-= (ibuf->x*ibuf->y);
1890
1891         ima->flag|= IMA_USED_FOR_RENDER;
1892
1893         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1894 }
1895
1896 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
1897 {
1898         TexResult texres = {0};
1899         afdata_t AFD;
1900
1901         AFD.dxt[0] = dx; AFD.dxt[1] = dx;
1902         AFD.dyt[0] = dy; AFD.dyt[1] = dy;
1903         //copy_v2_v2(AFD.dxt, dx);
1904         //copy_v2_v2(AFD.dyt, dy);
1905         
1906         AFD.intpol = 1;
1907         AFD.extflag = TXC_EXTD;
1908
1909         ewa_eval(&texres, ibuf, fx, fy, &AFD);
1910         
1911         copy_v4_v4(result, &texres.tr);
1912 }