Cleanup: manually remove header text not handled by automation
[blender.git] / source / blender / render / intern / source / imagetexture.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file blender/render/intern/source/imagetexture.c
21  *  \ingroup render
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <math.h>
28 #include <float.h>
29 #ifndef WIN32
30 #include <unistd.h>
31 #else
32 #include <io.h>
33 #endif
34
35 #include "IMB_imbuf_types.h"
36 #include "IMB_imbuf.h"
37
38 #include "DNA_image_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_texture_types.h"
41
42 #include "BLI_math.h"
43 #include "BLI_blenlib.h"
44 #include "BLI_threads.h"
45 #include "BLI_utildefines.h"
46
47 #include "BKE_image.h"
48
49 #include "RE_render_ext.h"
50 #include "RE_shader_ext.h"
51
52 #include "render_types.h"
53 #include "texture.h"
54
55 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend);
56
57 /* *********** IMAGEWRAPPING ****************** */
58
59
60 /* x and y have to be checked for image size */
61 static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
62 {
63         int ofs = y * ibuf->x + x;
64
65         if (ibuf->rect_float) {
66                 if (ibuf->channels==4) {
67                         const float *fp= ibuf->rect_float + 4*ofs;
68                         copy_v4_v4(col, fp);
69                 }
70                 else if (ibuf->channels==3) {
71                         const float *fp= ibuf->rect_float + 3*ofs;
72                         copy_v3_v3(col, fp);
73                         col[3]= 1.0f;
74                 }
75                 else {
76                         const float *fp= ibuf->rect_float + ofs;
77                         col[0]= col[1]= col[2]= col[3]= *fp;
78                 }
79         }
80         else {
81                 const char *rect = (char *)( ibuf->rect+ ofs);
82
83                 col[0] = ((float)rect[0])*(1.0f/255.0f);
84                 col[1] = ((float)rect[1])*(1.0f/255.0f);
85                 col[2] = ((float)rect[2])*(1.0f/255.0f);
86                 col[3] = ((float)rect[3])*(1.0f/255.0f);
87
88                 /* bytes are internally straight, however render pipeline seems to expect premul */
89                 col[0] *= col[3];
90                 col[1] *= col[3];
91                 col[2] *= col[3];
92         }
93 }
94
95 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
96 {
97         float fx, fy, val1, val2, val3;
98         int x, y, retval;
99         int xi, yi; /* original values */
100
101         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
102
103         /* we need to set retval OK, otherwise texture code generates normals itself... */
104         retval= texres->nor ? 3 : 1;
105
106         /* quick tests */
107         if (ibuf==NULL && ima==NULL)
108                 return retval;
109         if (ima) {
110
111                 /* hack for icon render */
112                 if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
113                         return retval;
114
115                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
116
117                 ima->flag|= IMA_USED_FOR_RENDER;
118         }
119         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
120                 if (ima)
121                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
122                 return retval;
123         }
124
125         /* setup mapping */
126         if (tex->imaflag & TEX_IMAROT) {
127                 fy= texvec[0];
128                 fx= texvec[1];
129         }
130         else {
131                 fx= texvec[0];
132                 fy= texvec[1];
133         }
134
135         if (tex->extend == TEX_CHECKER) {
136                 int xs, ys;
137
138                 xs= (int)floor(fx);
139                 ys= (int)floor(fy);
140                 fx-= xs;
141                 fy-= ys;
142
143                 if ( (tex->flag & TEX_CHECKER_ODD) == 0) {
144                         if ((xs + ys) & 1) {
145                                 /* pass */
146                         }
147                         else {
148                                 if (ima)
149                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
150                                 return retval;
151                         }
152                 }
153                 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
154                         if ((xs+ys) & 1) {
155                                 if (ima)
156                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
157                                 return retval;
158                         }
159                 }
160                 /* scale around center, (0.5, 0.5) */
161                 if (tex->checkerdist<1.0f) {
162                         fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
163                         fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
164                 }
165         }
166
167         x= xi= (int)floorf(fx*ibuf->x);
168         y= yi= (int)floorf(fy*ibuf->y);
169
170         if (tex->extend == TEX_CLIPCUBE) {
171                 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
172                         if (ima)
173                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
174                         return retval;
175                 }
176         }
177         else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
178                 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
179                         if (ima)
180                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
181                         return retval;
182                 }
183         }
184         else {
185                 if (tex->extend==TEX_EXTEND) {
186                         if (x>=ibuf->x) x = ibuf->x-1;
187                         else if (x<0) x= 0;
188                 }
189                 else {
190                         x= x % ibuf->x;
191                         if (x<0) x+= ibuf->x;
192                 }
193                 if (tex->extend==TEX_EXTEND) {
194                         if (y>=ibuf->y) y = ibuf->y-1;
195                         else if (y<0) y= 0;
196                 }
197                 else {
198                         y= y % ibuf->y;
199                         if (y<0) y+= ibuf->y;
200                 }
201         }
202
203         /* keep this before interpolation [#29761] */
204         if (ima) {
205                 if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
206                         if ((tex->imaflag & TEX_CALCALPHA) == 0) {
207                                 texres->talpha = true;
208                         }
209                 }
210         }
211
212         /* interpolate */
213         if (tex->imaflag & TEX_INTERPOL) {
214                 float filterx, filtery;
215                 filterx = (0.5f * tex->filtersize) / ibuf->x;
216                 filtery = (0.5f * tex->filtersize) / ibuf->y;
217
218                 /* important that this value is wrapped [#27782]
219                  * this applies the modifications made by the checks above,
220                  * back to the floating point values */
221                 fx -= (float)(xi - x) / (float)ibuf->x;
222                 fy -= (float)(yi - y) / (float)ibuf->y;
223
224                 boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND));
225         }
226         else { /* no filtering */
227                 ibuf_get_color(&texres->tr, ibuf, x, y);
228         }
229
230         if (texres->nor) {
231                 if (tex->imaflag & TEX_NORMALMAP) {
232                         /* qdn: normal from color
233                          * The invert of the red channel is to make
234                          * the normal map compliant with the outside world.
235                          * It needs to be done because in Blender
236                          * the normal used in the renderer points inward. It is generated
237                          * this way in calc_vertexnormals(). Should this ever change
238                          * this negate must be removed. */
239                         texres->nor[0] = -2.f*(texres->tr - 0.5f);
240                         texres->nor[1] = 2.f*(texres->tg - 0.5f);
241                         texres->nor[2] = 2.f*(texres->tb - 0.5f);
242                 }
243                 else {
244                         /* bump: take three samples */
245                         val1= texres->tr+texres->tg+texres->tb;
246
247                         if (x<ibuf->x-1) {
248                                 float col[4];
249                                 ibuf_get_color(col, ibuf, x+1, y);
250                                 val2= (col[0]+col[1]+col[2]);
251                         }
252                         else {
253                                 val2= val1;
254                         }
255
256                         if (y<ibuf->y-1) {
257                                 float col[4];
258                                 ibuf_get_color(col, ibuf, x, y+1);
259                                 val3 = (col[0]+col[1]+col[2]);
260                         }
261                         else {
262                                 val3 = val1;
263                         }
264
265                         /* do not mix up x and y here! */
266                         texres->nor[0]= (val1-val2);
267                         texres->nor[1]= (val1-val3);
268                 }
269         }
270
271         if (texres->talpha) {
272                 texres->tin = texres->ta;
273         }
274         else if (tex->imaflag & TEX_CALCALPHA) {
275                 texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb);
276         }
277         else {
278                 texres->ta = texres->tin = 1.0;
279         }
280
281         if (tex->flag & TEX_NEGALPHA) {
282                 texres->ta = 1.0f - texres->ta;
283         }
284
285         /* de-premul, this is being premulled in shade_input_do_shade()
286          * do not de-premul for generated alpha, it is already in straight */
287         if (texres->ta!=1.0f && texres->ta>1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
288                 fx= 1.0f/texres->ta;
289                 texres->tr*= fx;
290                 texres->tg*= fx;
291                 texres->tb*= fx;
292         }
293
294         if (ima)
295                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
296
297         BRICONTRGB;
298
299         return retval;
300 }
301
302 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
303 {
304         rctf *rf, *newrct;
305         short a;
306
307         a= *count;
308         rf= stack;
309         for (;a>0;a--) {
310                 if (rf->xmin<x1) {
311                         if (rf->xmax<x1) {
312                                 rf->xmin+= (x2-x1);
313                                 rf->xmax+= (x2-x1);
314                         }
315                         else {
316                                 if (rf->xmax>x2) rf->xmax = x2;
317                                 newrct= stack+ *count;
318                                 (*count)++;
319
320                                 newrct->xmax = x2;
321                                 newrct->xmin = rf->xmin+(x2-x1);
322                                 newrct->ymin = rf->ymin;
323                                 newrct->ymax = rf->ymax;
324
325                                 if (newrct->xmin ==newrct->xmax) (*count)--;
326
327                                 rf->xmin = x1;
328                         }
329                 }
330                 else if (rf->xmax>x2) {
331                         if (rf->xmin>x2) {
332                                 rf->xmin-= (x2-x1);
333                                 rf->xmax-= (x2-x1);
334                         }
335                         else {
336                                 if (rf->xmin<x1) rf->xmin = x1;
337                                 newrct= stack+ *count;
338                                 (*count)++;
339
340                                 newrct->xmin = x1;
341                                 newrct->xmax = rf->xmax-(x2-x1);
342                                 newrct->ymin = rf->ymin;
343                                 newrct->ymax = rf->ymax;
344
345                                 if (newrct->xmin ==newrct->xmax) (*count)--;
346
347                                 rf->xmax = x2;
348                         }
349                 }
350                 rf++;
351         }
352
353 }
354
355 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
356 {
357         rctf *rf, *newrct;
358         short a;
359
360         a= *count;
361         rf= stack;
362         for (;a>0;a--) {
363                 if (rf->ymin<y1) {
364                         if (rf->ymax<y1) {
365                                 rf->ymin+= (y2-y1);
366                                 rf->ymax+= (y2-y1);
367                         }
368                         else {
369                                 if (rf->ymax>y2) rf->ymax = y2;
370                                 newrct= stack+ *count;
371                                 (*count)++;
372
373                                 newrct->ymax = y2;
374                                 newrct->ymin = rf->ymin+(y2-y1);
375                                 newrct->xmin = rf->xmin;
376                                 newrct->xmax = rf->xmax;
377
378                                 if (newrct->ymin==newrct->ymax) (*count)--;
379
380                                 rf->ymin = y1;
381                         }
382                 }
383                 else if (rf->ymax>y2) {
384                         if (rf->ymin>y2) {
385                                 rf->ymin-= (y2-y1);
386                                 rf->ymax-= (y2-y1);
387                         }
388                         else {
389                                 if (rf->ymin<y1) rf->ymin = y1;
390                                 newrct= stack+ *count;
391                                 (*count)++;
392
393                                 newrct->ymin = y1;
394                                 newrct->ymax = rf->ymax-(y2-y1);
395                                 newrct->xmin = rf->xmin;
396                                 newrct->xmax = rf->xmax;
397
398                                 if (newrct->ymin==newrct->ymax) (*count)--;
399
400                                 rf->ymax = y2;
401                         }
402                 }
403                 rf++;
404         }
405 }
406
407 static float square_rctf(rctf *rf)
408 {
409         float x, y;
410
411         x = BLI_rctf_size_x(rf);
412         y = BLI_rctf_size_y(rf);
413         return x * y;
414 }
415
416 static float clipx_rctf(rctf *rf, float x1, float x2)
417 {
418         float size;
419
420         size = BLI_rctf_size_x(rf);
421
422         if (rf->xmin<x1) {
423                 rf->xmin = x1;
424         }
425         if (rf->xmax>x2) {
426                 rf->xmax = x2;
427         }
428         if (rf->xmin > rf->xmax) {
429                 rf->xmin = rf->xmax;
430                 return 0.0;
431         }
432         else if (size != 0.0f) {
433                 return BLI_rctf_size_x(rf) / size;
434         }
435         return 1.0;
436 }
437
438 static float clipy_rctf(rctf *rf, float y1, float y2)
439 {
440         float size;
441
442         size = BLI_rctf_size_y(rf);
443
444         if (rf->ymin<y1) {
445                 rf->ymin = y1;
446         }
447         if (rf->ymax>y2) {
448                 rf->ymax = y2;
449         }
450
451         if (rf->ymin > rf->ymax) {
452                 rf->ymin = rf->ymax;
453                 return 0.0;
454         }
455         else if (size != 0.0f) {
456                 return BLI_rctf_size_y(rf) / size;
457         }
458         return 1.0;
459
460 }
461
462 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
463 {
464         /* sample box, is clipped already, and minx etc. have been set at ibuf size.
465          * Enlarge with antialiased edges of the pixels */
466
467         float muly, mulx, div, col[4];
468         int x, y, startx, endx, starty, endy;
469
470         startx= (int)floor(rf->xmin);
471         endx= (int)floor(rf->xmax);
472         starty= (int)floor(rf->ymin);
473         endy= (int)floor(rf->ymax);
474
475         if (startx < 0) startx= 0;
476         if (starty < 0) starty= 0;
477         if (endx>=ibuf->x) endx= ibuf->x-1;
478         if (endy>=ibuf->y) endy= ibuf->y-1;
479
480         if (starty==endy && startx==endx) {
481                 ibuf_get_color(&texres->tr, ibuf, startx, starty);
482         }
483         else {
484                 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
485                 for (y=starty; y<=endy; y++) {
486
487                         muly= 1.0;
488
489                         if (starty==endy) {
490                                 /* pass */
491                         }
492                         else {
493                                 if (y==starty) muly= 1.0f-(rf->ymin - y);
494                                 if (y==endy) muly= (rf->ymax - y);
495                         }
496
497                         if (startx==endx) {
498                                 mulx= muly;
499
500                                 ibuf_get_color(col, ibuf, startx, y);
501
502                                 texres->ta+= mulx*col[3];
503                                 texres->tr+= mulx*col[0];
504                                 texres->tg+= mulx*col[1];
505                                 texres->tb+= mulx*col[2];
506                                 div+= mulx;
507                         }
508                         else {
509                                 for (x=startx; x<=endx; x++) {
510                                         mulx= muly;
511                                         if (x==startx) mulx*= 1.0f-(rf->xmin - x);
512                                         if (x==endx) mulx*= (rf->xmax - x);
513
514                                         ibuf_get_color(col, ibuf, x, y);
515
516                                         if (mulx==1.0f) {
517                                                 texres->ta+= col[3];
518                                                 texres->tr+= col[0];
519                                                 texres->tg+= col[1];
520                                                 texres->tb+= col[2];
521                                                 div+= 1.0f;
522                                         }
523                                         else {
524                                                 texres->ta+= mulx*col[3];
525                                                 texres->tr+= mulx*col[0];
526                                                 texres->tg+= mulx*col[1];
527                                                 texres->tb+= mulx*col[2];
528                                                 div+= mulx;
529                                         }
530                                 }
531                         }
532                 }
533
534                 if (div!=0.0f) {
535                         div= 1.0f/div;
536                         texres->tb*= div;
537                         texres->tg*= div;
538                         texres->tr*= div;
539                         texres->ta*= div;
540                 }
541                 else {
542                         texres->tr= texres->tg= texres->tb= texres->ta= 0.0f;
543                 }
544         }
545 }
546
547 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
548 {
549         /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
550          * Enlarge with antialiased edges of pixels.
551          * If variable 'imaprepeat' has been set, the
552          * clipped-away parts are sampled as well.
553          */
554         /* note: actually minx etc isn't in the proper range... this due to filter size and offset vectors for bump */
555         /* note: talpha must be initialized */
556         /* note: even when 'imaprepeat' is set, this can only repeat once in any direction.
557          * the point which min/max is derived from is assumed to be wrapped */
558         TexResult texr;
559         rctf *rf, stack[8];
560         float opp, tot, alphaclip= 1.0;
561         short count=1;
562
563         rf= stack;
564         rf->xmin = minx*(ibuf->x);
565         rf->xmax = maxx*(ibuf->x);
566         rf->ymin = miny*(ibuf->y);
567         rf->ymax = maxy*(ibuf->y);
568
569         texr.talpha= texres->talpha;    /* is read by boxsample_clip */
570
571         if (imapextend) {
572                 CLAMP(rf->xmin, 0.0f, ibuf->x-1);
573                 CLAMP(rf->xmax, 0.0f, ibuf->x-1);
574         }
575         else if (imaprepeat)
576                 clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
577         else {
578                 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
579
580                 if (alphaclip<=0.0f) {
581                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
582                         return;
583                 }
584         }
585
586         if (imapextend) {
587                 CLAMP(rf->ymin, 0.0f, ibuf->y-1);
588                 CLAMP(rf->ymax, 0.0f, ibuf->y-1);
589         }
590         else if (imaprepeat)
591                 clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
592         else {
593                 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
594
595                 if (alphaclip<=0.0f) {
596                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
597                         return;
598                 }
599         }
600
601         if (count>1) {
602                 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
603                 while (count--) {
604                         boxsampleclip(ibuf, rf, &texr);
605
606                         opp= square_rctf(rf);
607                         tot+= opp;
608
609                         texres->tr+= opp*texr.tr;
610                         texres->tg+= opp*texr.tg;
611                         texres->tb+= opp*texr.tb;
612                         if (texres->talpha) texres->ta+= opp*texr.ta;
613                         rf++;
614                 }
615                 if (tot!= 0.0f) {
616                         texres->tr/= tot;
617                         texres->tg/= tot;
618                         texres->tb/= tot;
619                         if (texres->talpha) texres->ta/= tot;
620                 }
621         }
622         else
623                 boxsampleclip(ibuf, rf, texres);
624
625         if (texres->talpha==0) texres->ta= 1.0;
626
627         if (alphaclip!=1.0f) {
628                 /* premul it all */
629                 texres->tr*= alphaclip;
630                 texres->tg*= alphaclip;
631                 texres->tb*= alphaclip;
632                 texres->ta*= alphaclip;
633         }
634 }
635
636 /*-----------------------------------------------------------------------------------------------------------------
637  * from here, some functions only used for the new filtering */
638
639 /* anisotropic filters, data struct used instead of long line of (possibly unused) func args */
640 typedef struct afdata_t {
641         float dxt[2], dyt[2];
642         int intpol, extflag;
643         /* feline only */
644         float majrad, minrad, theta;
645         int iProbes;
646         float dusc, dvsc;
647 } afdata_t;
648
649 /* this only used here to make it easier to pass extend flags as single int */
650 enum {TXC_XMIR = 1, TXC_YMIR, TXC_REPT, TXC_EXTD};
651
652 /* similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
653  * returns true if out of range in clipmode */
654 static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
655 {
656         int clip = 0;
657         switch (extflag) {
658                 case TXC_XMIR:  /* y rep */
659                         x %= 2*ibuf->x;
660                         x += x < 0 ? 2*ibuf->x : 0;
661                         x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x;
662                         y %= ibuf->y;
663                         y += y < 0 ? ibuf->y : 0;
664                         break;
665                 case TXC_YMIR:  /* x rep */
666                         x %= ibuf->x;
667                         x += x < 0 ? ibuf->x : 0;
668                         y %= 2*ibuf->y;
669                         y += y < 0 ? 2*ibuf->y : 0;
670                         y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y;
671                         break;
672                 case TXC_EXTD:
673                         x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
674                         y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
675                         break;
676                 case TXC_REPT:
677                         x %= ibuf->x;
678                         x += (x < 0) ? ibuf->x : 0;
679                         y %= ibuf->y;
680                         y += (y < 0) ? ibuf->y : 0;
681                         break;
682                 default:
683                 {       /* as extend, if clipped, set alpha to 0.0 */
684                         if (x < 0) { x = 0;  } /* TXF alpha: clip = 1; } */
685                         if (x >= ibuf->x) { x = ibuf->x - 1; } /* TXF alpha:  clip = 1; } */
686                         if (y < 0) { y = 0; } /* TXF alpha:  clip = 1; } */
687                         if (y >= ibuf->y) { y = ibuf->y - 1; } /* TXF alpha:  clip = 1; } */
688                 }
689         }
690
691         if (ibuf->rect_float) {
692                 const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
693                 if (ibuf->channels == 1)
694                         col[0] = col[1] = col[2] = col[3] = *fp;
695                 else {
696                         col[0] = fp[0];
697                         col[1] = fp[1];
698                         col[2] = fp[2];
699                         col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
700                 }
701         }
702         else {
703                 const char *rect = (char *)(ibuf->rect + x + y*ibuf->x);
704                 float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
705                 col[0] = rect[0] * inv_alpha_fac;
706                 col[1] = rect[1] * inv_alpha_fac;
707                 col[2] = rect[2] * inv_alpha_fac;
708                 col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
709         }
710         return clip;
711 }
712
713 /* as above + bilerp */
714 static int ibuf_get_color_clip_bilerp(float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
715 {
716         if (intpol) {
717                 float c00[4], c01[4], c10[4], c11[4];
718                 const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
719                 const float uf = u - ufl, vf = v - vfl;
720                 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
721                 const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
722                 int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
723                 clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
724                 clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
725                 clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
726                 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
727                 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
728                 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
729                 col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
730                 return clip;
731         }
732         return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
733 }
734
735 static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
736 {
737         int xs, ys, clip = 0;
738         float tc[4], xsd, ysd, cw = 0.f;
739         const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1];
740         const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1];
741         int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f);
742         int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f);
743         const int minsam = AFD->intpol ? 2 : 4;
744         xsam = CLAMPIS(xsam, minsam, ibuf->x*2);
745         ysam = CLAMPIS(ysam, minsam, ibuf->y*2);
746         xsd = 1.f / xsam;
747         ysd = 1.f / ysam;
748         texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
749         for (ys=0; ys<ysam; ++ys) {
750                 for (xs=0; xs<xsam; ++xs) {
751                         const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f;
752                         const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f;
753                         const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0];
754                         const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1];
755                         const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag);
756                         clip |= out;
757                         cw += out ? 0.f : 1.f;
758                         texr->tr += tc[0];
759                         texr->tg += tc[1];
760                         texr->tb += tc[2];
761                         texr->ta += texr->talpha ? tc[3] : 0.f;
762                 }
763         }
764         xsd *= ysd;
765         texr->tr *= xsd;
766         texr->tg *= xsd;
767         texr->tb *= xsd;
768         /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
769         texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
770 }
771
772 typedef struct ReadEWAData {
773         ImBuf *ibuf;
774         afdata_t *AFD;
775 } ReadEWAData;
776
777 static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
778 {
779         ReadEWAData *data = (ReadEWAData *) userdata;
780         ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
781 }
782
783 static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
784 {
785         ReadEWAData data;
786         float uv[2] = {fx, fy};
787         data.ibuf = ibuf;
788         data.AFD = AFD;
789         BLI_ewa_filter(ibuf->x, ibuf->y,
790                        AFD->intpol != 0,
791                        texr->talpha,
792                        uv, AFD->dxt, AFD->dyt,
793                        ewa_read_pixel_cb,
794                        &data,
795                        &texr->tr);
796
797 }
798
799 static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD)
800 {
801         const int maxn = AFD->iProbes - 1;
802         const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
803         float du = maxn ? cosf(AFD->theta)*ll : 0.f;
804         float dv = maxn ? sinf(AFD->theta)*ll : 0.f;
805         /* const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad); */
806         const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
807         float d; /* TXF alpha: cw = 0.f; */
808         int n; /* TXF alpha: clip = 0; */
809         /* have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.) */
810         du *= AFD->dusc;
811         dv *= AFD->dvsc;
812         d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
813         for (n=-maxn; n<=maxn; n+=2) {
814                 float tc[4];
815                 const float hn = n*0.5f;
816                 const float u = fx + hn*du, v = fy + hn*dv;
817                 /*const float wt = expf(n*n*D);
818                  * can use ewa table here too */
819                 const float wt = EWA_WTS[(int)(n*n*D)];
820                 /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag);
821                 /* TXF alpha: clip |= out;
822                  * TXF alpha: cw += out ? 0.f : wt; */
823                 texr->tr += tc[0]*wt;
824                 texr->tg += tc[1]*wt;
825                 texr->tb += tc[2]*wt;
826                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
827                 d += wt;
828         }
829
830         d = 1.f/d;
831         texr->tr *= d;
832         texr->tg *= d;
833         texr->tb *= d;
834         /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */
835         texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
836 }
837 #undef EWA_MAXIDX
838
839 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
840 {
841         float alphaclip;
842         rctf rf;
843
844         /* TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
845          * if this is actually correct for the all the filtering algorithms .. */
846
847         if (!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
848                 rf.xmin = minx*(ibuf->x);
849                 rf.xmax = maxx*(ibuf->x);
850                 rf.ymin = miny*(ibuf->y);
851                 rf.ymax = maxy*(ibuf->y);
852
853                 alphaclip  = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
854                 alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
855                 alphaclip  = max_ff(alphaclip, 0.0f);
856
857                 if (alphaclip!=1.0f) {
858                         /* premul it all */
859                         texres->tr*= alphaclip;
860                         texres->tg*= alphaclip;
861                         texres->tb*= alphaclip;
862                         texres->ta*= alphaclip;
863                 }
864         }
865 }
866
867 static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
868 {
869         if (tex->imaflag & TEX_MIPMAP) {
870                 if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
871                         BLI_thread_lock(LOCK_IMAGE);
872                         if (ibuf->userflags & IB_MIPMAP_INVALID) {
873                                 IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
874                                 ibuf->userflags &= ~IB_MIPMAP_INVALID;
875                         }
876                         BLI_thread_unlock(LOCK_IMAGE);
877                 }
878                 if (ibuf->mipmap[0] == NULL) {
879                         BLI_thread_lock(LOCK_IMAGE);
880                         if (ibuf->mipmap[0] == NULL)
881                                 IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
882                         BLI_thread_unlock(LOCK_IMAGE);
883                 }
884                 /* if no mipmap could be made, fall back on non-mipmap render */
885                 if (ibuf->mipmap[0] == NULL) {
886                         tex->imaflag &= ~TEX_MIPMAP;
887                 }
888         }
889 }
890
891 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, const bool skip_load_image)
892 {
893         TexResult texr;
894         float fx, fy, minx, maxx, miny, maxy;
895         float maxd, val1, val2, val3;
896         int curmap, retval, intpol, extflag = 0;
897         afdata_t AFD;
898
899         void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
900         switch (tex->texfilter) {
901                 case TXF_EWA:
902                         filterfunc = ewa_eval;
903                         break;
904                 case TXF_FELINE:
905                         filterfunc = feline_eval;
906                         break;
907                 case TXF_AREA:
908                 default:
909                         filterfunc = area_sample;
910         }
911
912         texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
913
914         /* we need to set retval OK, otherwise texture code generates normals itself... */
915         retval = texres->nor ? 3 : 1;
916
917         /* quick tests */
918         if (ibuf==NULL && ima==NULL) return retval;
919
920         if (ima) {      /* hack for icon render */
921                 if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
922                         return retval;
923                 }
924                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
925         }
926
927         if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
928                 if (ima)
929                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
930                 return retval;
931         }
932
933         if (ima) {
934                 ima->flag |= IMA_USED_FOR_RENDER;
935         }
936
937         /* mipmap test */
938         image_mipmap_test(tex, ibuf);
939
940         if (ima) {
941                 if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
942                         if ((tex->imaflag & TEX_CALCALPHA) == 0) {
943                                 texres->talpha = 1;
944                         }
945                 }
946         }
947         texr.talpha = texres->talpha;
948
949         if (tex->imaflag & TEX_IMAROT) {
950                 fy = texvec[0];
951                 fx = texvec[1];
952         }
953         else {
954                 fx = texvec[0];
955                 fy = texvec[1];
956         }
957
958         /* pixel coordinates */
959         minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
960         maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
961         miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
962         maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
963
964         /* tex_sharper has been removed */
965         minx = (maxx - minx)*0.5f;
966         miny = (maxy - miny)*0.5f;
967
968         if (tex->imaflag & TEX_FILTER_MIN) {
969                 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
970                 const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
971                 if (addval > minx) minx = addval;
972                 if (addval > miny) miny = addval;
973         }
974         else if (tex->filtersize != 1.f) {
975                 minx *= tex->filtersize;
976                 miny *= tex->filtersize;
977                 dxt[0] *= tex->filtersize;
978                 dxt[1] *= tex->filtersize;
979                 dyt[0] *= tex->filtersize;
980                 dyt[1] *= tex->filtersize;
981         }
982
983         if (tex->imaflag & TEX_IMAROT) {
984                 float t;
985                 SWAP(float, minx, miny);
986                 /* must rotate dxt/dyt 90 deg
987                  * yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
988                  * but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. */
989                 t = dxt[0];
990                 dxt[0] = dxt[1];
991                 dxt[1] = -t;
992                 t = dyt[0];
993                 dyt[0] = dyt[1];
994                 dyt[1] = -t;
995         }
996
997         /* side faces of unit-cube */
998         minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
999         miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
1000
1001         /* repeat and clip */
1002
1003         if (tex->extend == TEX_REPEAT) {
1004                 if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
1005                         extflag = TXC_EXTD;
1006                 else if (tex->flag & TEX_REPEAT_XMIR)
1007                         extflag = TXC_XMIR;
1008                 else if (tex->flag & TEX_REPEAT_YMIR)
1009                         extflag = TXC_YMIR;
1010                 else
1011                         extflag = TXC_REPT;
1012         }
1013         else if (tex->extend == TEX_EXTEND)
1014                 extflag = TXC_EXTD;
1015
1016         if (tex->extend == TEX_CHECKER) {
1017                 int xs = (int)floorf(fx), ys = (int)floorf(fy);
1018                 /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1019                 if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1020                         fx -= xs;
1021                         fy -= ys;
1022                 }
1023                 else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
1024                          (tex->flag & TEX_CHECKER_EVEN) == 0)
1025                 {
1026                         if (ima)
1027                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1028                         return retval;
1029                 }
1030                 else {
1031                         int xs1 = (int)floorf(fx - minx);
1032                         int ys1 = (int)floorf(fy - miny);
1033                         int xs2 = (int)floorf(fx + minx);
1034                         int ys2 = (int)floorf(fy + miny);
1035                         if ((xs1 != xs2) || (ys1 != ys2)) {
1036                                 if (tex->flag & TEX_CHECKER_ODD) {
1037                                         fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
1038                                         fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
1039                                 }
1040                                 if (tex->flag & TEX_CHECKER_EVEN) {
1041                                         fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
1042                                         fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
1043                                 }
1044                         }
1045                         else {
1046                                 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
1047                                         if (ima)
1048                                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1049                                         return retval;
1050                                 }
1051                                 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
1052                                         if (ima)
1053                                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1054                                         return retval;
1055                                 }
1056                                 fx -= xs;
1057                                 fy -= ys;
1058                         }
1059                 }
1060                 /* scale around center, (0.5, 0.5) */
1061                 if (tex->checkerdist < 1.f) {
1062                         const float omcd = 1.f / (1.f - tex->checkerdist);
1063                         fx = (fx - 0.5f)*omcd + 0.5f;
1064                         fy = (fy - 0.5f)*omcd + 0.5f;
1065                         minx *= omcd;
1066                         miny *= omcd;
1067                 }
1068         }
1069
1070         if (tex->extend == TEX_CLIPCUBE) {
1071                 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) {
1072                         if (ima)
1073                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1074                         return retval;
1075                 }
1076         }
1077         else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
1078                 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
1079                         if (ima)
1080                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1081                         return retval;
1082                 }
1083         }
1084         else {
1085                 if (tex->extend == TEX_EXTEND) {
1086                         fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
1087                         fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
1088                 }
1089                 else {
1090                         fx -= floorf(fx);
1091                         fy -= floorf(fy);
1092                 }
1093         }
1094
1095         intpol = tex->imaflag & TEX_INTERPOL;
1096
1097         /* struct common data */
1098         copy_v2_v2(AFD.dxt, dxt);
1099         copy_v2_v2(AFD.dyt, dyt);
1100         AFD.intpol = intpol;
1101         AFD.extflag = extflag;
1102
1103         /* brecht: added stupid clamping here, large dx/dy can give very large
1104          * filter sizes which take ages to render, it may be better to do this
1105          * more intelligently later in the code .. probably it's not noticeable */
1106         if (AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f)
1107                 mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
1108         if (AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
1109                 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
1110
1111         /* choice: */
1112         if (tex->imaflag & TEX_MIPMAP) {
1113                 ImBuf *previbuf, *curibuf;
1114                 float levf;
1115                 int maxlev;
1116                 ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
1117
1118                 /* modify ellipse minor axis if too eccentric, use for area sampling as well
1119                  * scaling dxt/dyt as done in pbrt is not the same
1120                  * (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) */
1121                 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1122                 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1123                 const float A = Vx*Vx + Vy*Vy;
1124                 const float B = -2.f*(Ux*Vx + Uy*Vy);
1125                 const float C = Ux*Ux + Uy*Uy;
1126                 const float F = A*C - B*B*0.25f;
1127                 float a, b, th, ecc;
1128                 BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1129                 if (tex->texfilter == TXF_FELINE) {
1130                         float fProbes;
1131                         a *= ff;
1132                         b *= ff;
1133                         a = max_ff(a, 1.0f);
1134                         b = max_ff(b, 1.0f);
1135                         fProbes = 2.f*(a / b) - 1.f;
1136                         AFD.iProbes = round_fl_to_int(fProbes);
1137                         AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
1138                         if (AFD.iProbes < fProbes)
1139                                 b = 2.f*a / (float)(AFD.iProbes + 1);
1140                         AFD.majrad = a/ff;
1141                         AFD.minrad = b/ff;
1142                         AFD.theta = th;
1143                         AFD.dusc = 1.f/ff;
1144                         AFD.dvsc = ff / (float)ibuf->y;
1145                 }
1146                 else {  /* EWA & area */
1147                         if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
1148                         b *= ff;
1149                 }
1150                 maxd = max_ff(b, 1e-8f);
1151                 levf = ((float)M_LOG2E) * logf(maxd);
1152
1153                 curmap = 0;
1154                 maxlev = 1;
1155                 mipmaps[0] = ibuf;
1156                 while (curmap < IMB_MIPMAP_LEVELS) {
1157                         mipmaps[curmap + 1] = ibuf->mipmap[curmap];
1158                         if (ibuf->mipmap[curmap]) maxlev++;
1159                         curmap++;
1160                 }
1161
1162                 /* mipmap level */
1163                 if (levf < 0.f) {  /* original image only */
1164                         previbuf = curibuf = mipmaps[0];
1165                         levf = 0.f;
1166                 }
1167                 else if (levf >= maxlev - 1) {
1168                         previbuf = curibuf = mipmaps[maxlev - 1];
1169                         levf = 0.f;
1170                         if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
1171                 }
1172                 else {
1173                         const int lev = isnan(levf) ? 0 : (int)levf;
1174                         curibuf = mipmaps[lev];
1175                         previbuf = mipmaps[lev + 1];
1176                         levf -= floorf(levf);
1177                 }
1178
1179                 /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1180
1181                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1182                         /* color & normal */
1183                         filterfunc(texres, curibuf, fx, fy, &AFD);
1184                         val1 = texres->tr + texres->tg + texres->tb;
1185                         filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
1186                         val2 = texr.tr + texr.tg + texr.tb;
1187                         filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
1188                         val3 = texr.tr + texr.tg + texr.tb;
1189                         /* don't switch x or y! */
1190                         texres->nor[0] = val1 - val2;
1191                         texres->nor[1] = val1 - val3;
1192                         if (previbuf != curibuf) {  /* interpolate */
1193                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1194                                 /* rgb */
1195                                 texres->tr += levf*(texr.tr - texres->tr);
1196                                 texres->tg += levf*(texr.tg - texres->tg);
1197                                 texres->tb += levf*(texr.tb - texres->tb);
1198                                 texres->ta += levf*(texr.ta - texres->ta);
1199                                 /* normal */
1200                                 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
1201                                 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
1202                                 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
1203                                 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
1204                                 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
1205                                 texres->nor[0] = val1 - val2;  /* vals have been interpolated above! */
1206                                 texres->nor[1] = val1 - val3;
1207                         }
1208                 }
1209                 else {  /* color */
1210                         filterfunc(texres, curibuf, fx, fy, &AFD);
1211                         if (previbuf != curibuf) {  /* interpolate */
1212                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1213                                 texres->tr += levf*(texr.tr - texres->tr);
1214                                 texres->tg += levf*(texr.tg - texres->tg);
1215                                 texres->tb += levf*(texr.tb - texres->tb);
1216                                 texres->ta += levf*(texr.ta - texres->ta);
1217                         }
1218
1219                         if (tex->texfilter != TXF_EWA) {
1220                                 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1221                         }
1222                 }
1223         }
1224         else {  /* no mipmap */
1225                 /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
1226                 if (tex->texfilter == TXF_FELINE) {
1227                         const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1228                         const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1229                         const float A = Vx*Vx + Vy*Vy;
1230                         const float B = -2.f*(Ux*Vx + Uy*Vy);
1231                         const float C = Ux*Ux + Uy*Uy;
1232                         const float F = A*C - B*B*0.25f;
1233                         float a, b, th, ecc, fProbes;
1234                         BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1235                         a *= ff;
1236                         b *= ff;
1237                         a = max_ff(a, 1.0f);
1238                         b = max_ff(b, 1.0f);
1239                         fProbes = 2.f*(a / b) - 1.f;
1240                         /* no limit to number of Probes here */
1241                         AFD.iProbes = round_fl_to_int(fProbes);
1242                         if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
1243                         AFD.majrad = a/ff;
1244                         AFD.minrad = b/ff;
1245                         AFD.theta = th;
1246                         AFD.dusc = 1.f/ff;
1247                         AFD.dvsc = ff / (float)ibuf->y;
1248                 }
1249                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1250                         /* color & normal */
1251                         filterfunc(texres, ibuf, fx, fy, &AFD);
1252                         val1 = texres->tr + texres->tg + texres->tb;
1253                         filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
1254                         val2 = texr.tr + texr.tg + texr.tb;
1255                         filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
1256                         val3 = texr.tr + texr.tg + texr.tb;
1257                         /* don't switch x or y! */
1258                         texres->nor[0] = val1 - val2;
1259                         texres->nor[1] = val1 - val3;
1260                 }
1261                 else {
1262                         filterfunc(texres, ibuf, fx, fy, &AFD);
1263                         if (tex->texfilter != TXF_EWA) {
1264                                 alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1265                         }
1266                 }
1267         }
1268
1269         if (tex->imaflag & TEX_CALCALPHA)
1270                 texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
1271         else
1272                 texres->tin = texres->ta;
1273         if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
1274
1275         if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {    /* normal from color */
1276                 /* The invert of the red channel is to make
1277                  * the normal map compliant with the outside world.
1278                  * It needs to be done because in Blender
1279                  * the normal used in the renderer points inward. It is generated
1280                  * this way in calc_vertexnormals(). Should this ever change
1281                  * this negate must be removed. */
1282                 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1283                 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1284                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1285         }
1286
1287         /* de-premul, this is being premulled in shade_input_do_shade()
1288          * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
1289          * also disabled in imagewraposa() to be able to compare results with blender's default texture filtering */
1290
1291         /* brecht: tried to fix this, see "TXF alpha" comments */
1292
1293         /* do not de-premul for generated alpha, it is already in straight */
1294         if (texres->ta!=1.0f && texres->ta>1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
1295                 fx = 1.f/texres->ta;
1296                 texres->tr *= fx;
1297                 texres->tg *= fx;
1298                 texres->tb *= fx;
1299         }
1300
1301         if (ima)
1302                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1303
1304         BRICONTRGB;
1305
1306         return retval;
1307 }
1308
1309
1310 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, const bool skip_load_image)
1311 {
1312         TexResult texr;
1313         float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
1314         float maxd, pixsize, val1, val2, val3;
1315         int curmap, retval, imaprepeat, imapextend;
1316
1317         /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
1318          * make a local copy here so that original vecs remain untouched */
1319         copy_v2_v2(dxt, DXT);
1320         copy_v2_v2(dyt, DYT);
1321
1322         /* anisotropic filtering */
1323         if (tex->texfilter != TXF_BOX)
1324                 return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
1325
1326         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
1327
1328         /* we need to set retval OK, otherwise texture code generates normals itself... */
1329         retval = texres->nor ? 3 : 1;
1330
1331         /* quick tests */
1332         if (ibuf==NULL && ima==NULL)
1333                 return retval;
1334         if (ima) {
1335
1336                 /* hack for icon render */
1337                 if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
1338                         return retval;
1339
1340                 ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
1341
1342                 ima->flag|= IMA_USED_FOR_RENDER;
1343         }
1344         if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
1345                 if (ima)
1346                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1347                 return retval;
1348         }
1349
1350         /* mipmap test */
1351         image_mipmap_test(tex, ibuf);
1352
1353         if (ima) {
1354                 if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
1355                         if ((tex->imaflag & TEX_CALCALPHA) == 0) {
1356                                 texres->talpha = true;
1357                         }
1358                 }
1359         }
1360
1361         texr.talpha= texres->talpha;
1362
1363         if (tex->imaflag & TEX_IMAROT) {
1364                 fy= texvec[0];
1365                 fx= texvec[1];
1366         }
1367         else {
1368                 fx= texvec[0];
1369                 fy= texvec[1];
1370         }
1371
1372         /* pixel coordinates */
1373
1374         minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1375         maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
1376         miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1377         maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
1378
1379         /* tex_sharper has been removed */
1380         minx= (maxx-minx)/2.0f;
1381         miny= (maxy-miny)/2.0f;
1382
1383         if (tex->imaflag & TEX_FILTER_MIN) {
1384                 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
1385                 float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);
1386
1387                 if (addval > minx)
1388                         minx= addval;
1389                 if (addval > miny)
1390                         miny= addval;
1391         }
1392         else if (tex->filtersize!=1.0f) {
1393                 minx*= tex->filtersize;
1394                 miny*= tex->filtersize;
1395
1396                 dxt[0]*= tex->filtersize;
1397                 dxt[1]*= tex->filtersize;
1398                 dyt[0]*= tex->filtersize;
1399                 dyt[1]*= tex->filtersize;
1400         }
1401
1402         if (tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
1403
1404         if (minx>0.25f) minx= 0.25f;
1405         else if (minx<0.00001f) minx= 0.00001f; /* side faces of unit-cube */
1406         if (miny>0.25f) miny= 0.25f;
1407         else if (miny<0.00001f) miny= 0.00001f;
1408
1409
1410         /* repeat and clip */
1411         imaprepeat= (tex->extend==TEX_REPEAT);
1412         imapextend= (tex->extend==TEX_EXTEND);
1413
1414         if (tex->extend == TEX_REPEAT) {
1415                 if (tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
1416                         imaprepeat= 0;
1417                         imapextend= 1;
1418                 }
1419         }
1420
1421         if (tex->extend == TEX_CHECKER) {
1422                 int xs, ys, xs1, ys1, xs2, ys2, boundary;
1423
1424                 xs= (int)floor(fx);
1425                 ys= (int)floor(fy);
1426
1427                 /* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
1428                 if ( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
1429                         fx-= xs;
1430                         fy-= ys;
1431                 }
1432                 else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
1433                          (tex->flag & TEX_CHECKER_EVEN) == 0)
1434                 {
1435                         if (ima)
1436                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1437                         return retval;
1438                 }
1439                 else {
1440
1441                         xs1= (int)floor(fx-minx);
1442                         ys1= (int)floor(fy-miny);
1443                         xs2= (int)floor(fx+minx);
1444                         ys2= (int)floor(fy+miny);
1445                         boundary= (xs1!=xs2) || (ys1!=ys2);
1446
1447                         if (boundary==0) {
1448                                 if ( (tex->flag & TEX_CHECKER_ODD)==0) {
1449                                         if ((xs + ys) & 1) {
1450                                                 /* pass */
1451                                         }
1452                                         else {
1453                                                 if (ima)
1454                                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1455                                                 return retval;
1456                                         }
1457                                 }
1458                                 if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
1459                                         if ((xs + ys) & 1) {
1460                                                 if (ima)
1461                                                         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1462                                                 return retval;
1463                                         }
1464                                 }
1465                                 fx-= xs;
1466                                 fy-= ys;
1467                         }
1468                         else {
1469                                 if (tex->flag & TEX_CHECKER_ODD) {
1470                                         if ((xs1+ys) & 1) fx-= xs2;
1471                                         else fx-= xs1;
1472
1473                                         if ((ys1+xs) & 1) fy-= ys2;
1474                                         else fy-= ys1;
1475                                 }
1476                                 if (tex->flag & TEX_CHECKER_EVEN) {
1477                                         if ((xs1+ys) & 1) fx-= xs1;
1478                                         else fx-= xs2;
1479
1480                                         if ((ys1+xs) & 1) fy-= ys1;
1481                                         else fy-= ys2;
1482                                 }
1483                         }
1484                 }
1485
1486                 /* scale around center, (0.5, 0.5) */
1487                 if (tex->checkerdist<1.0f) {
1488                         fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1489                         fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
1490                         minx/= (1.0f-tex->checkerdist);
1491                         miny/= (1.0f-tex->checkerdist);
1492                 }
1493         }
1494
1495         if (tex->extend == TEX_CLIPCUBE) {
1496                 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) {
1497                         if (ima)
1498                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1499                         return retval;
1500                 }
1501         }
1502         else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
1503                 if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
1504                         if (ima)
1505                                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1506                         return retval;
1507                 }
1508         }
1509         else {
1510                 if (imapextend) {
1511                         if (fx>1.0f) fx = 1.0f;
1512                         else if (fx<0.0f) fx= 0.0f;
1513                 }
1514                 else {
1515                         if (fx>1.0f) fx -= (int)(fx);
1516                         else if (fx<0.0f) fx+= 1-(int)(fx);
1517                 }
1518
1519                 if (imapextend) {
1520                         if (fy>1.0f) fy = 1.0f;
1521                         else if (fy<0.0f) fy= 0.0f;
1522                 }
1523                 else {
1524                         if (fy>1.0f) fy -= (int)(fy);
1525                         else if (fy<0.0f) fy+= 1-(int)(fy);
1526                 }
1527         }
1528
1529         /* choice:  */
1530         if (tex->imaflag & TEX_MIPMAP) {
1531                 ImBuf *previbuf, *curibuf;
1532                 float bumpscale;
1533
1534                 dx = minx;
1535                 dy = miny;
1536                 maxd = max_ff(dx, dy);
1537                 if (maxd > 0.5f) maxd = 0.5f;
1538
1539                 pixsize = 1.0f / (float) MIN2(ibuf->x, ibuf->y);
1540
1541                 bumpscale= pixsize/maxd;
1542                 if (bumpscale>1.0f) bumpscale= 1.0f;
1543                 else bumpscale*=bumpscale;
1544
1545                 curmap= 0;
1546                 previbuf= curibuf= ibuf;
1547                 while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
1548                         if (maxd < pixsize) break;
1549                         previbuf= curibuf;
1550                         curibuf= ibuf->mipmap[curmap];
1551                         pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
1552                         curmap++;
1553                 }
1554
1555                 if (previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
1556                         /* sample at least 1 pixel */
1557                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1558                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1559                 }
1560
1561                 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1562                         /* a bit extra filter */
1563                         //minx*= 1.35f;
1564                         //miny*= 1.35f;
1565
1566                         boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1567                         val1= texres->tr+texres->tg+texres->tb;
1568                         boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1569                         val2= texr.tr + texr.tg + texr.tb;
1570                         boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1571                         val3= texr.tr + texr.tg + texr.tb;
1572
1573                         /* don't switch x or y! */
1574                         texres->nor[0]= (val1-val2);
1575                         texres->nor[1]= (val1-val3);
1576
1577                         if (previbuf!=curibuf) {  /* interpolate */
1578
1579                                 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend);
1580
1581                                 /* calc rgb */
1582                                 dx= 2.0f*(pixsize-maxd)/pixsize;
1583                                 if (dx>=1.0f) {
1584                                         texres->ta= texr.ta; texres->tb= texr.tb;
1585                                         texres->tg= texr.tg; texres->tr= texr.tr;
1586                                 }
1587                                 else {
1588                                         dy= 1.0f-dx;
1589                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1590                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1591                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1592                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1593                                 }
1594
1595                                 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
1596                                 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1597                                 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
1598                                 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1599                                 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
1600
1601                                 texres->nor[0]= (val1-val2);    /* vals have been interpolated above! */
1602                                 texres->nor[1]= (val1-val3);
1603
1604                                 if (dx<1.0f) {
1605                                         dy= 1.0f-dx;
1606                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1607                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1608                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1609                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1610                                 }
1611                         }
1612                         texres->nor[0]*= bumpscale;
1613                         texres->nor[1]*= bumpscale;
1614                 }
1615                 else {
1616                         maxx= fx+minx;
1617                         minx= fx-minx;
1618                         maxy= fy+miny;
1619                         miny= fy-miny;
1620
1621                         boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
1622
1623                         if (previbuf!=curibuf) {  /* interpolate */
1624                                 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
1625
1626                                 fx= 2.0f*(pixsize-maxd)/pixsize;
1627
1628                                 if (fx>=1.0f) {
1629                                         texres->ta= texr.ta; texres->tb= texr.tb;
1630                                         texres->tg= texr.tg; texres->tr= texr.tr;
1631                                 }
1632                                 else {
1633                                         fy= 1.0f-fx;
1634                                         texres->tb= fy*texres->tb+ fx*texr.tb;
1635                                         texres->tg= fy*texres->tg+ fx*texr.tg;
1636                                         texres->tr= fy*texres->tr+ fx*texr.tr;
1637                                         texres->ta= fy*texres->ta+ fx*texr.ta;
1638                                 }
1639                         }
1640                 }
1641         }
1642         else {
1643                 const int intpol = tex->imaflag & TEX_INTERPOL;
1644                 if (intpol) {
1645                         /* sample 1 pixel minimum */
1646                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1647                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1648                 }
1649
1650                 if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1651                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1652                         val1= texres->tr+texres->tg+texres->tb;
1653                         boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
1654                         val2= texr.tr + texr.tg + texr.tb;
1655                         boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
1656                         val3= texr.tr + texr.tg + texr.tb;
1657
1658                         /* don't switch x or y! */
1659                         texres->nor[0]= (val1-val2);
1660                         texres->nor[1]= (val1-val3);
1661                 }
1662                 else
1663                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
1664         }
1665
1666         if (tex->imaflag & TEX_CALCALPHA) {
1667                 texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
1668         }
1669         else {
1670                 texres->tin = texres->ta;
1671         }
1672
1673         if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
1674
1675         if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
1676                 /* qdn: normal from color
1677                  * The invert of the red channel is to make
1678                  * the normal map compliant with the outside world.
1679                  * It needs to be done because in Blender
1680                  * the normal used in the renderer points inward. It is generated
1681                  * this way in calc_vertexnormals(). Should this ever change
1682                  * this negate must be removed. */
1683                 texres->nor[0] = -2.f*(texres->tr - 0.5f);
1684                 texres->nor[1] = 2.f*(texres->tg - 0.5f);
1685                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1686         }
1687
1688         /* de-premul, this is being premulled in shade_input_do_shade() */
1689         /* do not de-premul for generated alpha, it is already in straight */
1690         if (texres->ta!=1.0f && texres->ta>1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
1691                 mul_v3_fl(&texres->tr, 1.0f / texres->ta);
1692         }
1693
1694         if (ima)
1695                 BKE_image_pool_release_ibuf(ima, ibuf, pool);
1696
1697         BRICONTRGB;
1698
1699         return retval;
1700 }
1701
1702 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
1703 {
1704         TexResult texres;
1705         ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
1706
1707         if (UNLIKELY(ibuf == NULL)) {
1708                 zero_v4(result);
1709                 return;
1710         }
1711
1712         texres.talpha = true; /* boxsample expects to be initialized */
1713         boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
1714         copy_v4_v4(result, &texres.tr);
1715
1716         ima->flag|= IMA_USED_FOR_RENDER;
1717
1718         BKE_image_pool_release_ibuf(ima, ibuf, pool);
1719 }
1720
1721 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
1722 {
1723         TexResult texres = {0};
1724         afdata_t AFD;
1725
1726         AFD.dxt[0] = dx; AFD.dxt[1] = dx;
1727         AFD.dyt[0] = dy; AFD.dyt[1] = dy;
1728         //copy_v2_v2(AFD.dxt, dx);
1729         //copy_v2_v2(AFD.dyt, dy);
1730
1731         AFD.intpol = 1;
1732         AFD.extflag = TXC_EXTD;
1733
1734         ewa_eval(&texres, ibuf, fx, fy, &AFD);
1735
1736         copy_v4_v4(result, &texres.tr);
1737 }