Fixed render time regression in Blender Internal
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 21 Jan 2013 08:49:42 +0000 (08:49 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 21 Jan 2013 08:49:42 +0000 (08:49 +0000)
It was caused by image threading safe commit and it was noticeable
only on really multi-core CPU (like dual-socket Xeon stations), was
not visible on core i7 machine.

The reason of slowdown was spinlock around image buffer referencing,
which lead to lots of cores waiting for single core and using image
buffer after it was referenced was not so much longer than doing
reference itself.

The most clear solution here seemed to be introducing Image Pool
which will contain list of loaded and referenced image buffers, so
all threads could skip lock if the pool is used for reading only.
Lock only needed in cases when buffer for requested image user is
missing in the pool. This lock will happen only once per image so
overall amount of locks is much less that it was before.

To operate with pool:
- BKE_image_pool_new() creates new pool
- BKE_image_pool_free() destroys pool and dereferences all image
  buffers which were loaded to it
- BKE_image_pool_acquire_ibuf() returns image buffer for given
  image and user. Pool could be NULL and in this case fallback to
  BKE_image_acquire_ibuf will happen.

  This helps to avoid lots to if(poll) checks in image sampling
  code.

- BKE_image_pool_release_ibuf releases image buffer. In fact, it
  will only do something if pool is NULL, in all other case it'll
  equal to DoNothing operation.

30 files changed:
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/smoke.c
source/blender/compositor/operations/COM_TextureOperation.cpp
source/blender/compositor/operations/COM_TextureOperation.h
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_image_2d.c
source/blender/editors/sculpt_paint/paint_intern.h
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/makesrna/intern/rna_texture_api.c
source/blender/modifiers/intern/MOD_util.c
source/blender/nodes/shader/nodes/node_shader_texture.c
source/blender/nodes/texture/nodes/node_texture_proc.c
source/blender/nodes/texture/nodes/node_texture_texture.c
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/envmap.h
source/blender/render/intern/include/pixelshading.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_texture.c
source/blender/render/intern/source/renderdatabase.c

index 597f2f2..bfee5e8 100644 (file)
@@ -44,6 +44,7 @@ struct anim;
 struct Scene;
 struct Object;
 struct ImageFormatData;
+struct ImagePool;
 struct Main;
 
 #define IMA_MAX_SPACE       64
@@ -146,6 +147,11 @@ int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
 struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r);
 void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
 
+struct ImagePool *BKE_image_pool_new(void);
+void BKE_image_pool_free(struct ImagePool *pool);
+struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool);
+void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool);
+
 /* returns a new image or NULL if it can't load */
 struct Image *BKE_image_load(const char *filepath);
 /* returns existing Image when filename/type is same (frame optional) */
index 078923e..211b618 100644 (file)
@@ -47,6 +47,7 @@ struct Paint;
 struct PBVH;
 struct Scene;
 struct StrokeCache;
+struct ImagePool;
 
 extern const char PAINT_CURSOR_SCULPT[3];
 extern const char PAINT_CURSOR_VERTEX_PAINT[3];
@@ -116,6 +117,7 @@ typedef struct SculptSession {
        
        /* Used to cache the render of the active texture */
        unsigned int texcache_side, *texcache, texcache_actual;
+       struct ImagePool *tex_pool;
 
        /* Layer brush persistence between strokes */
        float (*layer_co)[3]; /* Copy of the mesh vertices' locations */
index fff51ab..c92c52a 100644 (file)
@@ -1483,7 +1483,9 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
                /* for vertex surface loop through tfaces and find uv color
                 *  that provides highest alpha */
                if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
-                       #pragma omp parallel for schedule(static)
+                       struct ImagePool *pool = BKE_image_pool_new();
+
+                       #pragma omp parallel for schedule(static) shared(pool)
                        for (i = 0; i < numOfFaces; i++) {
                                int numOfVert = (mface[i].v4) ? 4 : 3;
                                float uv[3] = {0.0f};
@@ -1496,7 +1498,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
                                        uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f;
                                        uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f;
 
-                                       multitex_ext_safe(tex, uv, &texres);
+                                       multitex_ext_safe(tex, uv, &texres, pool);
 
                                        if (texres.tin > pPoint[*vert].alpha) {
                                                copy_v3_v3(pPoint[*vert].color, &texres.tr);
@@ -1504,6 +1506,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
                                        }
                                }
                        }
+                       BKE_image_pool_free(pool);
                }
                else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
                        ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
@@ -1529,7 +1532,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
                                uv_final[0] = uv_final[0] * 2.0f - 1.0f;
                                uv_final[1] = uv_final[1] * 2.0f - 1.0f;
                                        
-                               multitex_ext_safe(tex, uv_final, &texres);
+                               multitex_ext_safe(tex, uv_final, &texres, NULL);
 
                                /* apply color */
                                copy_v3_v3(pPoint[i].color, &texres.tr);
index 1f6db19..1880cb4 100644 (file)
@@ -769,7 +769,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
                mul_m4_v3(eff->ob->imat, tex_co);
        }
 
-       hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result);
+       hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL);
 
        if (hasrgb && mode==PFIELD_TEX_RGB) {
                force[0] = (0.5f - result->tr) * strength;
@@ -780,15 +780,15 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
                strength/=nabla;
 
                tex_co[0] += nabla;
-               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1);
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL);
 
                tex_co[0] -= nabla;
                tex_co[1] += nabla;
-               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2);
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL);
 
                tex_co[1] -= nabla;
                tex_co[2] += nabla;
-               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3);
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL);
 
                if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
                        /* generate intensity if texture only has rgb value */
index 5124406..90158f8 100644 (file)
@@ -2811,6 +2811,28 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
        return ibuf;
 }
 
+static void image_get_fame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
+{
+       int frame = 0, index = 0;
+
+       /* see if we already have an appropriate ibuf, with image source and type */
+       if (ima->source == IMA_SRC_MOVIE) {
+               frame = iuser ? iuser->framenr : ima->lastframe;
+       }
+       else if (ima->source == IMA_SRC_SEQUENCE) {
+               if (ima->type == IMA_TYPE_IMAGE) {
+                       frame = iuser ? iuser->framenr : ima->lastframe;
+               }
+               else if (ima->type == IMA_TYPE_MULTILAYER) {
+                       frame = iuser ? iuser->framenr : ima->lastframe;
+                       index = iuser ? iuser->multi_index : IMA_NO_INDEX;
+               }
+       }
+
+       *frame_r = frame;
+       *index_r = index;
+}
+
 static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
 {
        ImBuf *ibuf = NULL;
@@ -3037,6 +3059,119 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
        return ibuf != NULL;
 }
 
+/* ******** Pool for image buffers ********  */
+
+typedef struct ImagePoolEntry {
+       struct ImagePoolEntry *next, *prev;
+       Image *image;
+       ImBuf *ibuf;
+       int index;
+       int frame;
+} ImagePoolEntry;
+
+typedef struct ImagePool {
+       ListBase image_buffers;
+} ImagePool;
+
+ImagePool *BKE_image_pool_new(void)
+{
+       ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
+
+       return pool;
+}
+
+void BKE_image_pool_free(ImagePool *pool)
+{
+       ImagePoolEntry *entry, *next_entry;
+
+       /* use single lock to dereference all the image buffers */
+       BLI_spin_lock(&image_spin);
+
+       for (entry = pool->image_buffers.first; entry; entry = next_entry) {
+               next_entry = entry->next;
+
+               if (entry->ibuf)
+                       IMB_freeImBuf(entry->ibuf);
+
+               MEM_freeN(entry);
+       }
+
+       BLI_spin_unlock(&image_spin);
+
+       MEM_freeN(pool);
+}
+
+BLI_INLINE ImBuf *image_pool_find_entry(ImagePool *pool, Image *image, int frame, int index, int *found)
+{
+       ImagePoolEntry *entry;
+
+       *found = FALSE;
+
+       for (entry = pool->image_buffers.first; entry; entry = entry->next) {
+               if (entry->image == image && entry->frame == frame && entry->index == index) {
+                       *found = TRUE;
+                       return entry->ibuf;
+               }
+       }
+
+       return NULL;
+}
+
+ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
+{
+       ImBuf *ibuf;
+       int index, frame, found;
+
+       if (pool == NULL) {
+               /* pool could be NULL, in this case use general acquire function */
+               return BKE_image_acquire_ibuf(ima, iuser, NULL);
+       }
+
+       image_get_fame_and_index(ima, iuser, &frame, &index);
+
+       ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+       if (found)
+               return ibuf;
+
+       BLI_spin_lock(&image_spin);
+
+       ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+
+       /* will also create entry even in cases image buffer failed to load,
+        * prevents trying to load the same buggy file multiple times
+        */
+       if (!found) {
+               ImagePoolEntry *entry;
+
+               ibuf = image_acquire_ibuf(ima, iuser, NULL);
+
+               if (ibuf)
+                       IMB_refImBuf(ibuf);
+
+               entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry");
+               entry->image = ima;
+               entry->frame = frame;
+               entry->index = index;
+               entry->ibuf = ibuf;
+
+               BLI_addtail(&pool->image_buffers, entry);
+       }
+
+       BLI_spin_unlock(&image_spin);
+
+       return ibuf;
+}
+
+void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
+{
+       /* if pool wasn't actually used, use general release stuff,
+        * for pools image buffers will be dereferenced on pool free
+        */
+       if (pool == NULL) {
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+       }
+}
+
 int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range)
 {
        const int len = (iuser->fie_ima * iuser->frames) / 2;
index b2371da..05031dd 100644 (file)
@@ -83,6 +83,7 @@
 #include "BKE_fcurve.h"
 #include "BKE_group.h"
 #include "BKE_icons.h"
+#include "BKE_image.h"
 #include "BKE_key.h"
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
@@ -308,6 +309,9 @@ void free_sculptsession(Object *ob)
                if (ss->texcache)
                        MEM_freeN(ss->texcache);
 
+               if (ss->tex_pool)
+                       BKE_image_pool_free(ss->tex_pool);
+
                if (ss->layer_co)
                        MEM_freeN(ss->layer_co);
 
index 2563fc2..be36e30 100644 (file)
@@ -1060,7 +1060,7 @@ static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres)
        int result_type;
 
        /* no node textures for now */
-       result_type = multitex_ext_safe(texture, tex_co, texres);
+       result_type = multitex_ext_safe(texture, tex_co, texres, NULL);
 
        /* if the texture gave an RGB value, we assume it didn't give a valid
         * intensity, since this is in the context of modifiers don't use perceptual color conversion.
index f8d6c0c..23a3abe 100644 (file)
@@ -23,6 +23,7 @@
 #include "COM_TextureOperation.h"
 
 #include "BLI_listbase.h"
+#include "BKE_image.h"
 
 TextureBaseOperation::TextureBaseOperation() : NodeOperation()
 {
@@ -46,11 +47,14 @@ void TextureBaseOperation::initExecution()
 {
        this->m_inputOffset = getInputSocketReader(0);
        this->m_inputSize = getInputSocketReader(1);
+       this->m_pool = BKE_image_pool_new();
 }
 void TextureBaseOperation::deinitExecution()
 {
        this->m_inputSize = NULL;
        this->m_inputOffset = NULL;
+       BKE_image_pool_free(this->m_pool);
+       this->m_pool = NULL;
 }
 
 void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
@@ -95,7 +99,7 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel
        vec[1] = textureSize[1] * (v + textureOffset[1]);
        vec[2] = textureSize[2] * textureOffset[2];
 
-       retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres);
+       retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool);
 
        if (texres.talpha)
                output[3] = texres.ta;
index f8435ec..227ad37 100644 (file)
@@ -45,6 +45,7 @@ private:
        const RenderData *m_rd;
        SocketReader *m_inputSize;
        SocketReader *m_inputOffset;
+       struct ImagePool *m_pool;
 
 protected:
 
index 280e967..ffea5af 100644 (file)
@@ -43,6 +43,7 @@
 
 #include "BKE_brush.h"
 #include "BKE_context.h"
+#include "BKE_image.h"
 #include "BKE_paint.h"
 
 #include "WM_api.h"
@@ -143,6 +144,8 @@ static int load_tex(Brush *br, ViewContext *vc)
            !same_snap(&snap, br, vc);
 
        if (refresh) {
+               struct ImagePool *pool = NULL;
+
                if (br->mtex.tex && br->mtex.tex->preview)
                        tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0];
 
@@ -182,6 +185,9 @@ static int load_tex(Brush *br, ViewContext *vc)
 
                buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
 
+               if (br->mtex.tex)
+                       pool = BKE_image_pool_new();
+
                #pragma omp parallel for schedule(static)
                for (j = 0; j < size; j++) {
                        int i;
@@ -232,7 +238,7 @@ static int load_tex(Brush *br, ViewContext *vc)
                                        x += br->mtex.ofs[0];
                                        y += br->mtex.ofs[1];
 
-                                       avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1;
+                                       avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y, pool) : 1;
 
                                        avg += br->texture_sample_bias;
 
@@ -247,6 +253,9 @@ static int load_tex(Brush *br, ViewContext *vc)
                        }
                }
 
+               if (pool)
+                       BKE_image_pool_free(pool);
+
                if (!overlay_texture)
                        glGenTextures(1, &overlay_texture);
        }
index c8cd380..0b76c88 100644 (file)
@@ -540,7 +540,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
                                co[2] = 0.0f;
                                
                                /* This is copied from displace modifier code */
-                               hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
+                               hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL);
                        
                                /* if the texture gave an RGB value, we assume it didn't give a valid
                                 * intensity, so calculate one (formula from do_material_tex).
index 75a95d4..faa9ce0 100644 (file)
@@ -36,6 +36,7 @@ struct ARegion;
 struct bContext;
 struct bglMats;
 struct Brush;
+struct ImagePool;
 struct ListBase;
 struct Mesh;
 struct Object;
@@ -140,7 +141,7 @@ void paint_calc_redraw_planes(float planes[4][4],
 
 void projectf(struct bglMats *mats, const float v[3], float p[2]);
 float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius);
-float paint_get_tex_pixel(struct Brush *br, float u, float v);
+float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool);
 int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface);
 void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]);
 
index e7d13bd..4f15627 100644 (file)
@@ -173,13 +173,13 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
        return len_v3(delta) / scale;
 }
 
-float paint_get_tex_pixel(Brush *br, float u, float v)
+float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool)
 {
        TexResult texres = {0};
        float co[3] = {u, v, 0.0f};
        int hasrgb;
 
-       hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
+       hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres, pool);
 
        if (hasrgb & TEX_RGB)
                texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta;
index d60d683..f49d800 100644 (file)
@@ -56,6 +56,7 @@
 #include "BKE_cdderivedmesh.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_image.h"
 #include "BKE_key.h"
 #include "BKE_library.h"
 #include "BKE_mesh.h"
@@ -983,7 +984,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
                x += br->mtex.ofs[0];
                y += br->mtex.ofs[1];
 
-               avg = paint_get_tex_pixel(br, x, y);
+               avg = paint_get_tex_pixel(br, x, y, ss->tex_pool);
        }
 
        avg += br->texture_sample_bias;
@@ -3376,11 +3377,17 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
                ss->texcache = NULL;
        }
 
+       if (ss->tex_pool) {
+               BKE_image_pool_free(ss->tex_pool);
+               ss->tex_pool = NULL;
+       }
+
        /* Need to allocate a bigger buffer for bigger brush size */
        ss->texcache_side = 2 * radius;
        if (!ss->texcache || ss->texcache_side > ss->texcache_actual) {
                ss->texcache = BKE_brush_gen_texture_cache(brush, radius);
                ss->texcache_actual = ss->texcache_side;
+               ss->tex_pool = BKE_image_pool_new();
        }
 }
 
index 5be9d3a..218fda3 100644 (file)
@@ -71,7 +71,7 @@ static void clear_envmap(struct EnvMap *env, bContext *C)
 static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4])
 {
        TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
-       multitex_ext(tex, value, NULL, NULL, 1, &texres);
+       multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL);
 
        color_r[0] = texres.tr;
        color_r[1] = texres.tg;
index 6c2f688..a94c51a 100644 (file)
@@ -74,7 +74,7 @@ void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
        int result_type;
 
        /* no node textures for now */
-       result_type = multitex_ext_safe(texture, tex_co, texres);
+       result_type = multitex_ext_safe(texture, tex_co, texres, NULL);
 
        /* if the texture gave an RGB value, we assume it didn't give a valid
         * intensity, since this is in the context of modifiers don't use perceptual color conversion.
index b77c7d0..ec238b6 100644 (file)
@@ -72,7 +72,7 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
                        
                        if (in[0]->datatype==NS_OSA_VECTORS) {
                                float *fp= in[0]->data;
-                               retval= multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL);
+                               retval = multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL);
                        }
                        else if (in[0]->datatype==NS_OSA_VALUES) {
                                float *fp= in[0]->data;
@@ -80,14 +80,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
                                
                                dxt[0] = fp[0]; dxt[1] = dxt[2] = 0.0f;
                                dyt[0] = fp[1]; dyt[1] = dyt[2] = 0.0f;
-                               retval= multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL);
+                               retval = multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL);
                        }
                        else
-                               retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL);
+                               retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL);
                }
                else {
                        copy_v3_v3(vec, shi->lo);
-                       retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL);
+                       retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL);
                }
                
                /* stupid exception */
index 8876d98..de2dac2 100644 (file)
@@ -69,7 +69,7 @@ static void do_proc(float *result, TexParams *p, const float col1[4], const floa
                texres.nor = NULL;
        
        textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex,
-                                &texres, thread, 0, p->shi, p->mtex);
+                                &texres, thread, 0, p->shi, p->mtex, NULL);
        
        if (is_normal)
                return;
index cc7367a..f839f48 100644 (file)
@@ -78,7 +78,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
                
                texres.nor = nor;
                textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex,
-                       &texres, thread, 0, p->shi, p->mtex);
+                       &texres, thread, 0, p->shi, p->mtex, NULL);
                
                if (textype & TEX_RGB) {
                        copy_v4_v4(out, &texres.tr);
index 10045a8..4b3e7c2 100644 (file)
@@ -189,14 +189,15 @@ typedef struct ShadeInput {
 struct Tex;
 struct MTex;
 struct ImBuf;
+struct ImagePool;
 
 /* this one uses nodes */
-int    multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres);
+int    multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
 /* nodes disabled */
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres);
+int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool);
 /* only for internal node usage */
 int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres,
-                   const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex);
+                   const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool);
 
 /* shaded view and bake */
 struct Render;
index d0f346f..a6c6d46 100644 (file)
 
 struct Render;
 struct TexResult;
+struct ImagePool;
 
 void make_envmaps(struct Render *re);
-int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres);
+int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
 
 #endif /* __ENVMAP_H__ */
 
index 30d5746..faf8c5f 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef __PIXELSHADING_H__
 #define __PIXELSHADING_H__
 
+struct ImagePool;
+
 /**
  * Render the pixel at (x,y) for object ap. Apply the jitter mask. 
  * Output is given in float collector[4]. The type vector:
index 905b4b4..d65da58 100644 (file)
@@ -62,6 +62,7 @@ struct RayFace;
 struct RenderEngine;
 struct ReportList;
 struct Main;
+struct ImagePool;
 
 #define TABLEINITSIZE 1024
 
@@ -260,6 +261,8 @@ struct Render
        RenderStats i;
 
        struct ReportList *reports;
+
+       struct ImagePool *pool;
 };
 
 /* ------------------------------------------------------------------------- */
@@ -373,6 +376,7 @@ struct halosort {
 /* ------------------------------------------------------------------------- */
 struct Material;
 struct MTFace;
+struct ImagePool;
 
 typedef struct RadFace {
        float unshot[3], totrad[3];
@@ -402,6 +406,7 @@ typedef struct HaloRen {
        int pixels;
        unsigned int lay;
        struct Material *mat;
+       struct ImagePool *pool;
 } HaloRen;
 
 /* ------------------------------------------------------------------------- */
index 4b9fa2d..2dc12f3 100644 (file)
@@ -60,6 +60,7 @@ struct TexResult;
 struct Tex;
 struct Image;
 struct ImBuf;
+struct ImagePool;
 
 /* texture.h */
 
@@ -76,9 +77,9 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima);
 
 /* imagetexture.h */
 
-int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres);
-void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4]);
+int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool);
+int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool);
+void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool);
 
 #endif /* __TEXTURE_H__ */
 
index 05f5f24..73304a0 100644 (file)
@@ -150,6 +150,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
        har->hasize= hasize;
        
        har->zd= 0.0;
+       har->pool = re->pool;
        
        return har;
 }
index be8b7f6..9adae6f 100644 (file)
@@ -668,7 +668,7 @@ static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const
 
 /* ------------------------------------------------------------------------- */
 
-int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres)
+int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
 {
        extern Render R;                /* only in this call */
        /* texvec should be the already reflected normal */
@@ -687,12 +687,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
                env->ima = tex->ima;
                if (env->ima && env->ima->ok) {
                        if (env->cube[1] == NULL) {
-                               ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL);
+                               ImBuf *ibuf_ima = BKE_image_pool_acquire_ibuf(env->ima, NULL, pool);
                                if (ibuf_ima)
                                        envmap_split_ima(env, ibuf_ima);
                                else
                                        env->ok = 0;
-                               BKE_image_release_ibuf(env->ima, ibuf_ima, NULL);
+                               BKE_image_pool_release_ibuf(env->ima, ibuf_ima, pool);
                        }
                }
        }
@@ -720,7 +720,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
                        mul_mat3_m4_v3(R.viewinv, dyt);
                }
                set_dxtdyt(dxts, dyts, dxt, dyt, face);
-               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres);
+               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool);
                
                /* edges? */
                
@@ -737,7 +737,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
                        if (face != face1) {
                                ibuf = env->cube[face1];
                                set_dxtdyt(dxts, dyts, dxt, dyt, face1);
-                               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1);
+                               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool);
                        }
                        else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
                        
@@ -750,7 +750,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
                        if (face != face1) {
                                ibuf = env->cube[face1];
                                set_dxtdyt(dxts, dyts, dxt, dyt, face1);
-                               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2);
+                               imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool);
                        }
                        else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
                        
@@ -766,7 +766,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
                }
        }
        else {
-               imagewrap(tex, NULL, ibuf, sco, texres);
+               imagewrap(tex, NULL, ibuf, sco, texres, pool);
        }
        
        return 1;
index 4aaa624..0a427d5 100644 (file)
@@ -110,7 +110,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
        }
 }
 
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres)
+int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
 {
        float fx, fy, val1, val2, val3;
        int x, y, retval;
@@ -130,13 +130,13 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
                        return retval;
 
-               ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+               ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
 
                ima->flag|= IMA_USED_FOR_RENDER;
        }
        if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
                if (ima)
-                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                return retval;
        }
        
@@ -164,14 +164,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                        }
                        else {
                                if (ima)
-                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                return retval;
                        }
                }
                if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
                        if ((xs+ys) & 1) {
                                if (ima)
-                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                return retval;
                        }
                }
@@ -188,14 +188,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
        if (tex->extend == TEX_CLIPCUBE) {
                if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
        else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
                if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
@@ -302,10 +302,10 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                texres->tg*= fx;
                texres->tb*= fx;
        }
-       
+
        if (ima)
-               BKE_image_release_ibuf(ima, ibuf, NULL);
-       
+               BKE_image_pool_release_ibuf(ima, ibuf, pool);
+
        BRICONTRGB;
        
        return retval;
@@ -1045,7 +1045,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
        
 }
 
-static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres)
+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)
 {
        TexResult texr;
        float fx, fy, minx, maxx, miny, maxy;
@@ -1076,12 +1076,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
 
        if (ima) {      /* hack for icon render */
                if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
-               ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+               ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
        }
 
        if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
                if (ima)
-                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                return retval;
        }
 
@@ -1199,12 +1199,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
                        else {
                                if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
                                        if (ima)
-                                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                        return retval;
                                }
                                if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
                                        if (ima)
-                                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                        return retval;
                                }
                                fx -= xs;
@@ -1224,14 +1224,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
        if (tex->extend == TEX_CLIPCUBE) {
                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) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
        else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
                if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
@@ -1455,7 +1455,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
        }
 
        if (ima)
-               BKE_image_release_ibuf(ima, ibuf, NULL);
+               BKE_image_pool_release_ibuf(ima, ibuf, pool);
 
        BRICONTRGB;
        
@@ -1463,7 +1463,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
 }
 
 
-int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres)
+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)
 {
        TexResult texr;
        float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
@@ -1477,7 +1477,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
 
        /* anisotropic filtering */
        if (tex->texfilter != TXF_BOX)
-               return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres);
+               return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
 
        texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
        
@@ -1493,13 +1493,13 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
                if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
                        return retval;
                
-               ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+               ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
 
                ima->flag|= IMA_USED_FOR_RENDER;
        }
        if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
                if (ima)
-                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                return retval;
        }
        
@@ -1608,14 +1608,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
                                        }
                                        else {
                                                if (ima)
-                                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                                return retval;
                                        }
                                }
                                if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
                                        if ((xs + ys) & 1) {
                                                if (ima)
-                                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                                       BKE_image_pool_release_ibuf(ima, ibuf, pool);
                                                return retval;
                                        }
                                }
@@ -1652,14 +1652,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
        if (tex->extend == TEX_CLIPCUBE) {
                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) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
        else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
                if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
                        if (ima)
-                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(ima, ibuf, pool);
                        return retval;
                }
        }
@@ -1855,17 +1855,17 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
        }
 
        if (ima)
-               BKE_image_release_ibuf(ima, ibuf, NULL);
+               BKE_image_pool_release_ibuf(ima, ibuf, pool);
 
        BRICONTRGB;
        
        return retval;
 }
 
-void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4])
+void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
 {
        TexResult texres;
-       ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
+       ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
        
        if (UNLIKELY(ibuf == NULL)) {
                zero_v4(result);
@@ -1884,7 +1884,7 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu
 
        ima->flag|= IMA_USED_FOR_RENDER;
 
-       BKE_image_release_ibuf(ima, ibuf, NULL);
+       BKE_image_pool_release_ibuf(ima, ibuf, pool);
 }
 
 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
index 5210803..3e9f599 100644 (file)
@@ -1787,6 +1787,8 @@ static void do_render_all_options(Render *re)
        /* ensure no images are in memory from previous animated sequences */
        BKE_image_all_free_anim_ibufs(re->r.cfra);
 
+       re->pool = BKE_image_pool_new();
+
        if (RE_engine_render(re, 1)) {
                /* in this case external render overrides all */
        }
@@ -1811,6 +1813,9 @@ static void do_render_all_options(Render *re)
                renderresult_stampinfo(re);
                re->display_draw(re->ddh, re->result, NULL);
        }
+
+       BKE_image_pool_free(re->pool);
+       re->pool = NULL;
 }
 
 static int check_valid_camera(Scene *scene, Object *camera_override)
@@ -2385,6 +2390,8 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
 
        RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
 
+       re->pool = BKE_image_pool_new();
+
        re->main = bmain;
        re->scene = sce;
        re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
@@ -2394,6 +2401,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
        RE_SetCamera(re, camera);
 
        do_render_3d(re);
+
+       BKE_image_pool_free(re->pool);
+       re->pool = NULL;
 }
 
 /* note; repeated win/disprect calc... solve that nicer, also in compo */
index e3bfd53..01eee46 100644 (file)
@@ -1099,7 +1099,7 @@ static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float
 
 /* ************************************** */
 
-static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output)
+static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool)
 {
        float tmpvec[3];
        int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
@@ -1137,12 +1137,12 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
                                retval = texnoise(tex, texres);
                                break;
                        case TEX_IMAGE:
-                               if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres);
-                               else        retval = imagewrap(tex, tex->ima, NULL, texvec, texres);
+                               if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool);
+                               else        retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool);
                                BKE_image_tag_time(tex->ima); /* tag image as having being used */
                                break;
                        case TEX_ENVMAP:
-                               retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres);
+                               retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool);
                                break;
                        case TEX_MUSGRAVE:
                                /* newnoise: musgrave types */
@@ -1214,7 +1214,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
 
 /* this is called from the shader and texture nodes */
 int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres,
-                   const short thread, short which_output, ShadeInput *shi, MTex *mtex)
+                   const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool)
 {
        if (tex==NULL) {
                memset(texres, 0, sizeof(TexResult));
@@ -1230,16 +1230,16 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
                if (mtex) {
                        /* we have mtex, use it for 2d mapping images only */
                        do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
-                       rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
+                       rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
 
                        if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
-                               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+                               ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
                                
                                /* don't linearize float buffers, assumed to be linear */
                                if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                        IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
 
-                               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
                        }
                }
                else {
@@ -1263,28 +1263,28 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
                        }
                        
                        do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
-                       rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output);
+                       rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool);
 
                        {
-                               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+                               ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
 
                                /* don't linearize float buffers, assumed to be linear */
                                if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                        IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
 
-                               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+                               BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
                        }
                }
 
                return rgbnor;
        }
        else {
-               return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
+               return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
        }
 }
 
 /* this is called for surface shading */
-static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres)
+static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool)
 {
        Tex *tex = mtex->tex;
 
@@ -1295,24 +1295,24 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
                                        tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex);
        }
        else {
-               return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output);
+               return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool);
        }
 }
 
 /* Warning, if the texres's values are not declared zero, check the return value to be sure
  * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */
-int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres)
+int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
 {
-       return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL);
+       return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool);
 }
 
 /* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on) */
-int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres)
+int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool)
 {
        int use_nodes= tex->use_nodes, retval;
        
        tex->use_nodes = FALSE;
-       retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL);
+       retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool);
        tex->use_nodes= use_nodes;
        
        return retval;
@@ -1699,7 +1699,8 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s
 }
 
 static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
-                                   float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3])
+                                   float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
+                                   struct ImagePool *pool)
 {
        TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};  /* temp TexResult */
        float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
@@ -1727,12 +1728,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
        if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) {
                /* in case we have no proper derivatives, fall back to
                 * computing du/dv it based on image size */
-               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+               ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
                if (ibuf) {
                        du = 1.f/(float)ibuf->x;
                        dv = 1.f/(float)ibuf->y;
                }
-               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+               BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
        }
        else if (shi->osatex) {
                /* we have derivatives, can compute proper du/dv */
@@ -1752,7 +1753,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
 
        /* center, main return value */
        texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
-       rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
+       rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
        cd = fromrgb ? (texres->tr + texres->tg + texres->tb)*0.33333333f : texres->tin;
 
        if (mtex->texco == TEXCO_UV) {
@@ -1766,7 +1767,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                tco[1] = co[1] + compat_bump->dvdnu*du;
                tco[2] = 0.f;
                texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
-               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
                ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
 
                /* +v val */
@@ -1774,7 +1775,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                tco[1] = co[1] + compat_bump->dvdnv*du;
                tco[2] = 0.f;
                texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
-               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
                vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
        }
        else {
@@ -1808,7 +1809,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                tco[1] = co[1] + tu[1]*du;
                tco[2] = co[2] + tu[2]*du;
                texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
-               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
                ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
 
                /* +v val */
@@ -1816,7 +1817,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
                tco[1] = co[1] + tv[1]*dv;
                tco[2] = co[2] + tv[2]*dv;
                texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
-               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
                vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
        }
 
@@ -1858,7 +1859,7 @@ static void ntap_bump_init(NTapBump *ntap_bump)
 
 static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
                              float Tnor, const float co[3], const float dx[3], const float dy[3],
-                             float texvec[3], float dxt[3], float dyt[3])
+                             float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool)
 {
        TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};        /* temp TexResult */
 
@@ -1905,20 +1906,20 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
 
        /* resolve image dimensions */
        if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) {
-               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+               ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
                if (ibuf) {
                        dimx = ibuf->x;
                        dimy = ibuf->y;
                        aspect = ((float) dimy) / dimx;
                }
-               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+               BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
        }
        
        if (found_deriv_map) {
                float dBdu, dBdv, auto_bump = 1.0f;
                float s = 1;            /* negate this if flipped texture coordinate */
                texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
-               rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
+               rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
 
                if (shi->obr->ob->derivedFinal) {
                        auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
@@ -1960,14 +1961,14 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
                }
 
                /* use texres for the center sample, set rgbnor */
-               rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres);
+               rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool);
                Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin;
 
                /* use ttexr for the other 2 taps */
-               multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool);
                Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
 
-               multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool);
                Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
 
                dHdx = Hscale*(Hlr - Hll);
@@ -1998,17 +1999,17 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
                }
 
                /* use texres for the center sample, set rgbnor */
-               rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres);
+               rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool);
                /* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */
 
                /* use ttexr for the other taps */
-               multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool);
                Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
-               multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool);
                Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
-               multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool);
                Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
-               multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr);
+               multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool);
                Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
 
                dHdx = Hscale*(Hr - Hl);
@@ -2285,20 +2286,22 @@ void do_material_tex(ShadeInput *shi, Render *re)
                        if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) {
                                if (use_compat_bump) {
                                        rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
-                                                                        &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+                                                                        &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+                                                                        re->pool);
                                }
                                else if (use_ntap_bump) {
                                        rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
-                                                                  &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+                                                                  &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+                                                                  re->pool);
                                }
                                else {
                                        texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
-                                       rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+                                       rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
                                }
                        }
                        else {
                                texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
-                               rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+                               rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
                        }
 
                        /* texture output */
@@ -2402,13 +2405,13 @@ void do_material_tex(ShadeInput *shi, Render *re)
                                /* inverse gamma correction */
                                if (tex->type==TEX_IMAGE) {
                                        Image *ima = tex->ima;
-                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+                                       ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool);
                                        
                                        /* don't linearize float buffers, assumed to be linear */
                                        if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                                IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
 
-                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
                                }
                                
                                if (mtex->mapto & MAP_COL) {
@@ -2737,7 +2740,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
                                else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
                        }
                        
-                       rgbnor= multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output);   /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+                       rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output, re->pool);        /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
                        
                        /* texture output */
 
@@ -2904,7 +2907,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
 
        if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
        
-       rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output);
+       rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool);
 
        /* texture output */
        if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2936,13 +2939,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
                /* inverse gamma correction */
                if (mtex->tex->type==TEX_IMAGE) {
                        Image *ima = mtex->tex->ima;
-                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL);
+                       ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool);
                        
                        /* don't linearize float buffers, assumed to be linear */
                        if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
 
-                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       BKE_image_pool_release_ibuf(ima, ibuf, har->pool);
                }
 
                fact= texres.tin*mtex->colfac;
@@ -3109,7 +3112,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
                        /* texture */
                        if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
                
-                       rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output);
+                       rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool);
                        
                        /* texture output */
                        if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3157,13 +3160,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
                                /* inverse gamma correction */
                                if (tex->type==TEX_IMAGE) {
                                        Image *ima = tex->ima;
-                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+                                       ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
                                        
                                        /* don't linearize float buffers, assumed to be linear */
                                        if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                                IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
 
-                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
                                }
 
                                if (mtex->mapto & WOMAP_HORIZ) {
@@ -3324,7 +3327,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
                                do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
                        }
                        
-                       rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output);
+                       rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool);
 
                        /* texture output */
                        if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3373,13 +3376,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
                                /* inverse gamma correction */
                                if (tex->type==TEX_IMAGE) {
                                        Image *ima = tex->ima;
-                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+                                       ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
                                        
                                        /* don't linearize float buffers, assumed to be linear */
                                        if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
                                                IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
 
-                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
                                }
 
                                /* lamp colors were premultiplied with this */
@@ -3421,7 +3424,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg,
                do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
        }
        
-       rgb= multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output);
+       rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, R.pool);
        
        if (rgb) {
                texr.tin = rgb_to_bw(&texr.tr);
@@ -3485,8 +3488,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
        
        texr.nor= NULL;
        
-       if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr);
-       else imagewrap(tex, ima, NULL, texvec, &texr); 
+       if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool);
+       else imagewrap(tex, ima, NULL, texvec, &texr, R.pool); 
 
        shi->vcol[0]*= texr.tr;
        shi->vcol[1]*= texr.tg;
index 7ca4f01..31424b9 100644 (file)
@@ -1070,6 +1070,8 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
                }
        }
 
+       har->pool = re->pool;
+
        return har;
 }
 
@@ -1223,6 +1225,8 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
                        //}
                }
 
+       har->pool = re->pool;
+
        return har;
 }