Image thread safe improvements
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Nov 2012 15:59:58 +0000 (15:59 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Nov 2012 15:59:58 +0000 (15:59 +0000)
This commit makes BKE_image_acquire_ibuf referencing result, which means once
some area requested for image buffer, it'll be guaranteed this buffer wouldn't
be freed by image signal.

To de-reference buffer BKE_image_release_ibuf should now always be used.

To make referencing working correct we can not rely on result of
image_get_ibuf_threadsafe called outside from thread lock. This is so because
we need to guarantee getting image buffer from list of loaded buffers and it's
referencing happens atomic. Without lock here it is possible that between call
of image_get_ibuf_threadsafe and referencing the buffer IMA_SIGNAL_FREE would
be called. Image signal handling too is blocking now to prevent such a
situation.

Threads are locking by spinlock, which are faster than mutexes. There were some
slowdown reports in the past about render slowdown when using OSX on Xeon CPU.
It shouldn't happen with spin locks, but more tests on different hardware would
be really welcome. So far can not see speed regressions on own computers.

This commit also removes BKE_image_get_ibuf, because it was not so intuitive
when get_ibuf and acquire_ibuf should be used.

Thanks to Ton and Brecht for discussion/review :)

52 files changed:
intern/cycles/kernel/kernel_shader.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/image.c
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/intern/threads.c
source/blender/blenloader/intern/readfile.c
source/blender/collada/ImageExporter.cpp
source/blender/compositor/nodes/COM_ImageNode.cpp
source/blender/compositor/operations/COM_ImageOperation.cpp
source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
source/blender/editors/include/ED_image.h
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_edit.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_opengl.c
source/blender/editors/render/render_preview.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_edit.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_info/info_ops.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_view.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_material.c
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_image_api.c
source/blender/makesrna/intern/rna_space.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/composite/nodes/node_composite_splitViewer.c
source/blender/nodes/composite/nodes/node_composite_viewer.c
source/blender/nodes/shader/nodes/node_shader_tex_environment.c
source/blender/nodes/shader/nodes/node_shader_tex_image.c
source/blender/nodes/shader/nodes/node_shader_texture.c
source/blender/nodes/texture/nodes/node_texture_image.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/rendercore.c
source/blender/render/intern/source/voxeldata.c
source/blender/windowmanager/intern/wm_playanim.c
source/creator/creator.c
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/Ketsji/BL_Texture.cpp

index a2a7419..f935858 100644 (file)
@@ -625,7 +625,7 @@ __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_facto
 #else
        *N = sd->N;
 
-       if(CLOSURE_IS_DIFFUSE(sd->closure.type))
+       if(CLOSURE_IS_BSDF_DIFFUSE(sd->closure.type))
                return sd->closure.weight*ao_factor;
        else if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type))
                return sd->closure.weight;
index 1875fd6..1f9630d 100644 (file)
@@ -48,6 +48,9 @@ struct Main;
 
 #define IMA_MAX_SPACE       64
 
+void   BKE_images_init(void);
+void   BKE_images_exit(void);
+
 /* call from library */
 void    BKE_image_free(struct Image *me);
 
@@ -133,14 +136,13 @@ enum {
 #define IMA_CHAN_FLAG_RGB   2
 #define IMA_CHAN_FLAG_ALPHA 4
 
-/* depending Image type, and (optional) ImageUser setting it returns ibuf */
-/* always call to make signals work */
-struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser);
+/* checks whether there's an image buffer for given image and user */
+int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
 
 /* same as above, but can be used to retrieve images being rendered in
  * a thread safe way, always call both acquire and release */
 struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r);
-void BKE_image_release_ibuf(struct Image *ima, void *lock);
+void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
 
 /* returns a new image or NULL if it can't load */
 struct Image *BKE_image_load(const char *filepath);
index e1e868b..40cd5b3 100644 (file)
@@ -70,6 +70,7 @@
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_idprop.h"
+#include "BKE_image.h"
 #include "BKE_ipo.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
@@ -113,6 +114,7 @@ void free_blender(void)
        BKE_spacetypes_free();      /* after free main, it uses space callbacks */
        
        IMB_exit();
+       BKE_images_exit();
 
        BLI_callback_global_finalize();
 
index 98b2067..f310895 100644 (file)
@@ -1287,8 +1287,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
 
                texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
 
-               BKE_image_get_ibuf(mtex->tex->ima, NULL);
-               
                /*do normalized cannonical view coords for texture*/
                for (y = -1.0, iy = 0; iy < side; iy++, y += step) {
                        for (x = -1.0, ix = 0; ix < side; ix++, x += step) {
index 55d37c9..993d72a 100644 (file)
 
 #include "WM_api.h"
 
+static SpinLock image_spin;
+
 /* max int, to indicate we don't store sequences in ibuf */
 #define IMA_NO_INDEX    0x7FEFEFEF
 
 #define IMA_INDEX_FRAME(index)          (index >> 10)
 #define IMA_INDEX_PASS(index)           (index & ~1023)
 
+void BKE_images_init(void)
+{
+       BLI_spin_init(&image_spin);
+}
+
+void BKE_images_exit(void)
+{
+       BLI_spin_end(&image_spin);
+}
+
 /* ******** IMAGE PROCESSING ************* */
 
 static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */
@@ -168,13 +180,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */
 
 void BKE_image_de_interlace(Image *ima, int odd)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        if (ibuf) {
                if (odd)
                        de_interlace_st(ibuf);
                else
                        de_interlace_ng(ibuf);
        }
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 /* ***************** ALLOC & FREE, DATA MANAGING *************** */
@@ -260,8 +273,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame)
        /* this function is intended to be thread safe. with IMA_NO_INDEX this
         * should be OK, but when iterating over the list this is more tricky
         * */
-       if (index == IMA_NO_INDEX)
+       if (index == IMA_NO_INDEX) {
                return ima->ibufs.first;
+       }
        else {
                ImBuf *ibuf;
 
@@ -269,9 +283,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame)
                for (ibuf = ima->ibufs.first; ibuf; ibuf = ibuf->next)
                        if (ibuf->index == index)
                                return ibuf;
-
-               return NULL;
        }
+
+       return NULL;
 }
 
 /* no ima->ibuf anymore, but listbase */
@@ -534,7 +548,7 @@ int BKE_image_scale(Image *image, int width, int height)
                ibuf->userflags |= IB_BITMAPDIRTY;
        }
 
-       BKE_image_release_ibuf(image, lock);
+       BKE_image_release_ibuf(image, ibuf, lock);
 
        return (ibuf != NULL);
 }
@@ -2081,6 +2095,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
        if (ima == NULL)
                return;
 
+       BLI_spin_lock(&image_spin);
+
        switch (signal) {
                case IMA_SIGNAL_FREE:
                        image_free_buffers(ima);
@@ -2167,6 +2183,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
                        }
                }
        }
+
+       BLI_spin_unlock(&image_spin);
 }
 
 /* if layer or pass changes, we need an index for the imbufs list */
@@ -2320,7 +2338,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
 
        if (ibuf) {
 #ifdef WITH_OPENEXR
-               /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */
+               /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
                if (ibuf->ftype == OPENEXR && ibuf->userdata) {
                        image_create_multilayer(ima, ibuf, frame);
                        ima->type = IMA_TYPE_MULTILAYER;
@@ -2482,7 +2500,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
        }
 
        if (ibuf) {
-               /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */
+               /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */
                if (ibuf->ftype == OPENEXR && ibuf->userdata) {
                        image_create_multilayer(ima, ibuf, cfra);
                        ima->type = IMA_TYPE_MULTILAYER;
@@ -2751,38 +2769,32 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame
                 * a big bottleneck */
        }
 
-       *frame_r = frame;
-       *index_r = index;
+       if (frame_r)
+               *frame_r = frame;
+
+       if (index_r)
+               *index_r = index;
 
        return ibuf;
 }
 
-/* Checks optional ImageUser and verifies/creates ImBuf. */
-/* use this one if you want to get a render result in progress,
- * if not, use BKE_image_get_ibuf which doesn't require a release */
-ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
+/* Checks optional ImageUser and verifies/creates ImBuf.
+ *
+ * not thread-safe, so callee should worry about thread locks
+ */
+static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
 {
        ImBuf *ibuf = NULL;
        float color[] = {0, 0, 0, 1};
        int frame = 0, index = 0;
 
-       /* This function is intended to be thread-safe. It postpones the mutex lock
-        * until it needs to load the image, if the image is already there it
-        * should just get the pointer and return. The reason is that a lot of mutex
-        * locks appears to be very slow on certain multicore macs, causing a render
-        * with image textures to actually slow down as more threads are used.
-        *
-        * Note that all the image loading functions should also make sure they do
-        * things in a threadsafe way for image_get_ibuf_threadsafe to work correct.
-        * That means, the last two steps must be, 1) add the ibuf to the list and
-        * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */
-
        if (lock_r)
                *lock_r = NULL;
 
        /* quick reject tests */
        if (ima == NULL)
                return NULL;
+
        if (iuser) {
                if (iuser->ok == 0)
                        return NULL;
@@ -2790,95 +2802,71 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
        else if (ima->ok == 0)
                return NULL;
 
-       /* try to get the ibuf without locking */
        ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index);
 
        if (ibuf == NULL) {
-               /* couldn't get ibuf and image is not ok, so let's lock and try to
-                * load the image */
-               BLI_lock_thread(LOCK_IMAGE);
-
-               /* need to check ok flag and loading ibuf again, because the situation
-                * might have changed in the meantime */
-               if (iuser) {
-                       if (iuser->ok == 0) {
-                               BLI_unlock_thread(LOCK_IMAGE);
-                               return NULL;
+               /* we are sure we have to load the ibuf, using source and type */
+               if (ima->source == IMA_SRC_MOVIE) {
+                       /* source is from single file, use flipbook to store ibuf */
+                       ibuf = image_load_movie_file(ima, iuser, frame);
+               }
+               else if (ima->source == IMA_SRC_SEQUENCE) {
+                       if (ima->type == IMA_TYPE_IMAGE) {
+                               /* regular files, ibufs in flipbook, allows saving */
+                               ibuf = image_load_sequence_file(ima, iuser, frame);
                        }
-               }
-               else if (ima->ok == 0) {
-                       BLI_unlock_thread(LOCK_IMAGE);
-                       return NULL;
-               }
-
-               ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index);
-
-               if (ibuf == NULL) {
-                       /* we are sure we have to load the ibuf, using source and type */
-                       if (ima->source == IMA_SRC_MOVIE) {
-                               /* source is from single file, use flipbook to store ibuf */
-                               ibuf = image_load_movie_file(ima, iuser, frame);
-                       }
-                       else if (ima->source == IMA_SRC_SEQUENCE) {
-                               if (ima->type == IMA_TYPE_IMAGE) {
-                                       /* regular files, ibufs in flipbook, allows saving */
-                                       ibuf = image_load_sequence_file(ima, iuser, frame);
-                               }
-                               /* no else; on load the ima type can change */
-                               if (ima->type == IMA_TYPE_MULTILAYER) {
-                                       /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
-                                       ibuf = image_load_sequence_multilayer(ima, iuser, frame);
-                               }
-                       }
-                       else if (ima->source == IMA_SRC_FILE) {
-
-                               if (ima->type == IMA_TYPE_IMAGE)
-                                       ibuf = image_load_image_file(ima, iuser, frame);  /* cfra only for '#', this global is OK */
-                               /* no else; on load the ima type can change */
-                               if (ima->type == IMA_TYPE_MULTILAYER)
-                                       /* keeps render result, stores ibufs in listbase, allows saving */
-                                       ibuf = image_get_ibuf_multilayer(ima, iuser);
-
+                       /* no else; on load the ima type can change */
+                       if (ima->type == IMA_TYPE_MULTILAYER) {
+                               /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
+                               ibuf = image_load_sequence_multilayer(ima, iuser, frame);
                        }
-                       else if (ima->source == IMA_SRC_GENERATED) {
-                               /* generated is: ibuf is allocated dynamically */
-                               /* UV testgrid or black or solid etc */
-                               if (ima->gen_x == 0) ima->gen_x = 1024;
-                               if (ima->gen_y == 0) ima->gen_y = 1024;
-                               ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type,
-                                                    color, &ima->colorspace_settings);
-                               image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
-                               ima->ok = IMA_OK_LOADED;
+               }
+               else if (ima->source == IMA_SRC_FILE) {
+
+                       if (ima->type == IMA_TYPE_IMAGE)
+                               ibuf = image_load_image_file(ima, iuser, frame);  /* cfra only for '#', this global is OK */
+                       /* no else; on load the ima type can change */
+                       if (ima->type == IMA_TYPE_MULTILAYER)
+                               /* keeps render result, stores ibufs in listbase, allows saving */
+                               ibuf = image_get_ibuf_multilayer(ima, iuser);
+
+               }
+               else if (ima->source == IMA_SRC_GENERATED) {
+                       /* generated is: ibuf is allocated dynamically */
+                       /* UV testgrid or black or solid etc */
+                       if (ima->gen_x == 0) ima->gen_x = 1024;
+                       if (ima->gen_y == 0) ima->gen_y = 1024;
+                       ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type,
+                                            color, &ima->colorspace_settings);
+                       image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+                       ima->ok = IMA_OK_LOADED;
+               }
+               else if (ima->source == IMA_SRC_VIEWER) {
+                       if (ima->type == IMA_TYPE_R_RESULT) {
+                               /* always verify entirely, and potentially
+                                * returns pointer to release later */
+                               ibuf = image_get_render_result(ima, iuser, lock_r);
                        }
-                       else if (ima->source == IMA_SRC_VIEWER) {
-                               if (ima->type == IMA_TYPE_R_RESULT) {
-                                       /* always verify entirely, and potentially
-                                        * returns pointer to release later */
-                                       ibuf = image_get_render_result(ima, iuser, lock_r);
-                               }
-                               else if (ima->type == IMA_TYPE_COMPOSITE) {
-                                       /* requires lock/unlock, otherwise don't return image */
-                                       if (lock_r) {
-                                               /* unlock in BKE_image_release_ibuf */
-                                               BLI_lock_thread(LOCK_VIEWER);
-                                               *lock_r = ima;
-
-                                               /* XXX anim play for viewer nodes not yet supported */
-                                               frame = 0; // XXX iuser?iuser->framenr:0;
-                                               ibuf = image_get_ibuf(ima, 0, frame);
-
-                                               if (!ibuf) {
-                                                       /* Composite Viewer, all handled in compositor */
-                                                       /* fake ibuf, will be filled in compositor */
-                                                       ibuf = IMB_allocImBuf(256, 256, 32, IB_rect);
-                                                       image_assign_ibuf(ima, ibuf, 0, frame);
-                                               }
+                       else if (ima->type == IMA_TYPE_COMPOSITE) {
+                               /* requires lock/unlock, otherwise don't return image */
+                               if (lock_r) {
+                                       /* unlock in BKE_image_release_ibuf */
+                                       BLI_lock_thread(LOCK_VIEWER);
+                                       *lock_r = ima;
+
+                                       /* XXX anim play for viewer nodes not yet supported */
+                                       frame = 0; // XXX iuser?iuser->framenr:0;
+                                       ibuf = image_get_ibuf(ima, 0, frame);
+
+                                       if (!ibuf) {
+                                               /* Composite Viewer, all handled in compositor */
+                                               /* fake ibuf, will be filled in compositor */
+                                               ibuf = IMB_allocImBuf(256, 256, 32, IB_rect);
+                                               image_assign_ibuf(ima, ibuf, 0, frame);
                                        }
                                }
                        }
                }
-
-               BLI_unlock_thread(LOCK_IMAGE);
        }
 
        BKE_image_tag_time(ima);
@@ -2886,23 +2874,66 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
        return ibuf;
 }
 
-void BKE_image_release_ibuf(Image *ima, void *lock)
+/* return image buffer for given image and user
+ *
+ * - will lock render result if image type is render result and lock is not NULL
+ * - will return NULL if image type if render or composite result and lock is NULL
+ *
+ * references the result, BKE_image_release_ibuf should be used to de-reference
+ */
+ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
 {
-       /* for getting image during threaded render / compositing, need to release */
-       if (lock == ima) {
-               BLI_unlock_thread(LOCK_VIEWER); /* viewer image */
+       ImBuf *ibuf;
+
+       BLI_spin_lock(&image_spin);
+
+       ibuf = image_acquire_ibuf(ima, iuser, lock_r);
+
+       if (ibuf)
+               IMB_refImBuf(ibuf);
+
+       BLI_spin_unlock(&image_spin);
+
+       return ibuf;
+}
+
+void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
+{
+       if (lock) {
+               /* for getting image during threaded render / compositing, need to release */
+               if (lock == ima) {
+                       BLI_unlock_thread(LOCK_VIEWER); /* viewer image */
+               }
+               else if (lock) {
+                       RE_ReleaseResultImage(lock); /* render result */
+                       BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */
+               }
        }
-       else if (lock) {
-               RE_ReleaseResultImage(lock); /* render result */
-               BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */
+
+       if (ibuf) {
+               BLI_spin_lock(&image_spin);
+               IMB_freeImBuf(ibuf);
+               BLI_spin_unlock(&image_spin);
        }
 }
 
-/* warning, this can allocate generated images */
-ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser)
+/* checks whether there's an image buffer for given image and user */
+int BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
 {
-       /* here (+fie_ima/2-1) makes sure that division happens correctly */
-       return BKE_image_acquire_ibuf(ima, iuser, NULL);
+       ImBuf *ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL);
+
+       if (!ibuf) {
+               BLI_spin_lock(&image_spin);
+
+               ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL);
+
+               if (!ibuf)
+                       ibuf = image_acquire_ibuf(ima, iuser, NULL);
+
+               BLI_spin_unlock(&image_spin);
+       }
+
+       return ibuf != NULL;
 }
 
 int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range)
@@ -3020,7 +3051,7 @@ int BKE_image_has_alpha(struct Image *image)
 
        ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
        planes = (ibuf ? ibuf->planes : 0);
-       BKE_image_release_ibuf(image, lock);
+       BKE_image_release_ibuf(image, ibuf, lock);
 
        if (planes == 32)
                return 1;
@@ -3044,7 +3075,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height)
                *height = IMG_SIZE_FALLBACK;
        }
 
-       BKE_image_release_ibuf(image, lock);
+       BKE_image_release_ibuf(image, ibuf, lock);
 }
 
 void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2])
index 9cd801f..ec8e567 100644 (file)
@@ -37,6 +37,10 @@ extern "C" {
 
 #include <pthread.h>
 
+#ifdef __APPLE__
+#include <libkern/OSAtomic.h>
+#endif
+
 /* for tables, button in UI, etc */
 #define BLENDER_MAX_THREADS     64
 
@@ -92,6 +96,19 @@ void BLI_mutex_lock(ThreadMutex *mutex);
 void BLI_mutex_unlock(ThreadMutex *mutex);
 void BLI_mutex_end(ThreadMutex *mutex);
 
+/* Spin Lock */
+
+#ifdef __APPLE__
+typedef OSSpinLock SpinLock;
+#else
+typedef pthread_spinlock_t SpinLock;
+#endif
+
+void BLI_spin_init(SpinLock *spin);
+void BLI_spin_lock(SpinLock *spin);
+void BLI_spin_unlock(SpinLock *spin);
+void BLI_spin_end(SpinLock *spin);
+
 /* Read/Write Mutex Lock */
 
 #define THREAD_LOCK_READ    1
index 66527b9..146e1d5 100644 (file)
@@ -400,6 +400,42 @@ void BLI_mutex_end(ThreadMutex *mutex)
        pthread_mutex_destroy(mutex);
 }
 
+/* Spin Locks */
+
+void BLI_spin_init(SpinLock *spin)
+{
+#ifdef __APPLE__
+       *spin = OS_SPINLOCK_INIT;
+#else
+       pthread_spin_init(spin, 0);
+#endif
+}
+
+void BLI_spin_lock(SpinLock *spin)
+{
+#ifdef __APPLE__
+       OSSpinLockLock(spin);
+#else
+       pthread_spin_lock(spin);
+#endif
+}
+
+void BLI_spin_unlock(SpinLock *spin)
+{
+#ifdef __APPLE__
+       OSSpinLockUnlock(spin);
+#else
+       pthread_spin_unlock(spin);
+#endif
+}
+
+void BLI_spin_end(SpinLock *spin)
+{
+#ifndef __APPLE__
+       pthread_spin_destroy(spin);
+#endif
+}
+
 /* Read/Write Mutex Lock */
 
 void BLI_rw_mutex_init(ThreadRWMutex *mutex)
index 3033171..03e5a1d 100644 (file)
@@ -3043,7 +3043,7 @@ static void direct_link_image(FileData *fd, Image *ima)
                link_ibuf_list(fd, &ima->ibufs);
        else
                ima->ibufs.first = ima->ibufs.last = NULL;
-       
+
        /* if not restored, we keep the binded opengl index */
        if (ima->ibufs.first == NULL) {
                ima->bindcode = 0;
index 2e0c0f1..aba290f 100644 (file)
@@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
 
        if (not_yet_exported) {
 
-               ImBuf *imbuf       = BKE_image_get_ibuf(image, NULL);
+               ImBuf *imbuf       = BKE_image_acquire_ibuf(image, NULL, NULL);
                if (!imbuf) {
                        fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name);
                        return;
@@ -147,6 +147,8 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
                img.add(mSW);
                fprintf(stdout, "Collada export: Added image: %s\n", export_file);
                mImages.push_back(translated_name);
+
+               BKE_image_release_ibuf(image, imbuf, NULL);
        }
 }
 
index 4ebd28d..729cb1b 100644 (file)
@@ -73,7 +73,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
        /* force a load, we assume iuser index will be set OK anyway */
        if (image && image->type == IMA_TYPE_MULTILAYER) {
                bool is_multilayer_ok = false;
-               BKE_image_get_ibuf(image, imageuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL);
                if (image->rr) {
                        RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
                        if (rl) {
@@ -118,6 +118,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
                                }
                        }
                }
+               BKE_image_release_ibuf(image, ibuf, NULL);
 
                /* without this, multilayer that fail to load will crash blender [#32490] */
                if (is_multilayer_ok == false) {
index fb3efbb..a7743cd 100644 (file)
@@ -65,7 +65,7 @@ ImBuf *BaseImageOperation::getImBuf()
 {
        ImBuf *ibuf;
        
-       ibuf = BKE_image_get_ibuf(this->m_image, this->m_imageUser);
+       ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL);
        if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) {
                return NULL;
        }
@@ -93,6 +93,7 @@ void BaseImageOperation::initExecution()
 void BaseImageOperation::deinitExecution()
 {
        this->m_imageBuffer = NULL;
+       IMB_freeImBuf(this->m_buffer);
 }
 
 void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
@@ -106,6 +107,8 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne
                resolution[0] = stackbuf->x;
                resolution[1] = stackbuf->y;
        }
+
+       IMB_freeImBuf(stackbuf);
 }
 
 void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
index 4d4c119..cc31351 100644 (file)
@@ -87,20 +87,16 @@ void ViewerBaseOperation::initImage()
        /* now we combine the input with ibuf */
        this->m_outputBuffer = ibuf->rect_float;
 
-       /* needed for display buffer update
-        *
-        * no need to lock / reference the image buffer because it's seems
-        * to be the single place which changes buffers of viewer image
-        * which is this node
-        */
+       /* needed for display buffer update */
        this->m_ibuf = ibuf;
 
        if (m_doDepthBuffer) {
                this->m_depthBuffer = ibuf->zbuf_float;
        }
 
-       BKE_image_release_ibuf(this->m_image, this->m_lock);
+       BKE_image_release_ibuf(this->m_image, this->m_ibuf, this->m_lock);
 }
+
 void ViewerBaseOperation:: updateImage(rcti *rect)
 {
        IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0,
index a50b339..9b726ce 100644 (file)
@@ -49,7 +49,7 @@ void          ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sim
 
 int ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]);
 struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r);
-void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock);
+void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
 int ED_space_image_has_buffer(struct SpaceImage *sima);
 
 void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height);
index 032314d..e144c38 100644 (file)
@@ -114,7 +114,7 @@ typedef struct {
 } MultiresBakeRender;
 
 typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
-                               const int face_index, const int lvl, const float st[2],
+                               ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                float tangmat[3][3], const int x, const int y);
 
 typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
@@ -133,6 +133,7 @@ typedef struct {
        DerivedMesh *lores_dm, *hires_dm;
        int lvl;
        void *bake_data;
+       ImBuf *ibuf;
        MPassKnownData pass_data;
 } MResolvePixelData;
 
@@ -257,7 +258,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
        /* sequence end */
 
        data->pass_data(data->lores_dm, data->hires_dm, data->bake_data,
-                       data->face_index, data->lvl, st, to_tang, x, y);
+                       data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
 }
 
 static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
@@ -368,7 +369,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData
                              MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
 {
        DerivedMesh *dm = bkr->lores_dm;
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        const int lvl = bkr->lvl;
        const int tot_face = dm->getNumTessFaces(dm);
        MVert *mvert = dm->getVertArray(dm);
@@ -414,6 +415,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData
                                continue;
 
                        data.face_index = f;
+                       data.ibuf = ibuf;
 
                        /* might support other forms of diagonal splits later on such as
                         * split by shortest diagonal.*/
@@ -449,6 +451,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData
                if (freeBakeData)
                        freeBakeData(data.bake_data);
        }
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 /* mode = 0: interpolate normals,
@@ -579,7 +583,7 @@ static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float
 static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
 {
        MHeightBakeData *height_data;
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        DerivedMesh *lodm = bkr->lores_dm;
 
        height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
@@ -609,6 +613,8 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
        height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
        height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
 
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return (void *)height_data;
 }
 
@@ -635,7 +641,7 @@ static void free_normal_data(void *bake_data)
 static void apply_heights_data(void *bake_data)
 {
        MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
-       ImBuf *ibuf = BKE_image_get_ibuf(height_data->ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL);
        int x, y, i;
        float height, *heights = height_data->heights;
        float min = height_data->height_min, max = height_data->height_max;
@@ -667,6 +673,8 @@ static void apply_heights_data(void *bake_data)
        }
 
        ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID;
+
+       BKE_image_release_ibuf(height_data->ima, ibuf, NULL);
 }
 
 static void free_heights_data(void *bake_data)
@@ -687,13 +695,11 @@ static void free_heights_data(void *bake_data)
  *     mesh to make texture smoother) let's call this point p0 and n.
  *   - height wound be dot(n, p1-p0) */
 static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
-                                   const int face_index, const int lvl, const float st[2],
+                                   ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                    float UNUSED(tangmat[3][3]), const int x, const int y)
 {
        MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
        MFace mface;
-       Image *ima = mtface[face_index].tpage;
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
        MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
        float uv[2], *st0, *st1, *st2, *st3;
        int pixel = ibuf->x * y + x;
@@ -764,13 +770,11 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
  *   - multiply it by tangmat
  *   - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
 static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
-                                   const int face_index, const int lvl, const float st[2],
+                                   ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
                                    float tangmat[3][3], const int x, const int y)
 {
        MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
        MFace mface;
-       Image *ima = mtface[face_index].tpage;
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
        MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
        float uv[2], *st0, *st1, *st2, *st3;
        int pixel = ibuf->x * y + x;
@@ -853,7 +857,7 @@ static void bake_images(MultiresBakeRender *bkr)
 
        for (link = bkr->image.first; link; link = link->next) {
                Image *ima = (Image *)link->data;
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                if (ibuf->x > 0 && ibuf->y > 0) {
                        ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
@@ -869,6 +873,8 @@ static void bake_images(MultiresBakeRender *bkr)
                        }
                }
 
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+
                ima->id.flag |= LIB_DOIT;
        }
 }
@@ -879,7 +885,7 @@ static void finish_images(MultiresBakeRender *bkr)
 
        for (link = bkr->image.first; link; link = link->next) {
                Image *ima = (Image *)link->data;
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                if (ibuf->x <= 0 || ibuf->y <= 0)
                        continue;
@@ -900,6 +906,8 @@ static void finish_images(MultiresBakeRender *bkr)
                        MEM_freeN(ibuf->userdata);
                        ibuf->userdata = NULL;
                }
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 }
 
@@ -974,7 +982,7 @@ static int multiresbake_check(bContext *C, wmOperator *op)
                                        ok = 0;
                                }
                                else {
-                                       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                                        if (!ibuf) {
                                                BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
@@ -991,6 +999,8 @@ static int multiresbake_check(bContext *C, wmOperator *op)
                                                if (!ok)
                                                        BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
                                        }
+
+                                       BKE_image_release_ibuf(ima, ibuf, NULL);
                                }
                        }
                }
@@ -1061,10 +1071,12 @@ static void clear_images(MTFace *mtface, int totface)
                Image *ima = mtface[a].tpage;
 
                if ((ima->id.flag & LIB_DOIT) == 0) {
-                       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                        IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
                        ima->id.flag |= LIB_DOIT;
+
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                }
        }
 
@@ -1358,7 +1370,7 @@ static void finish_bake_internal(BakeRender *bkr)
 
        /* force OpenGL reload and mipmap recalc */
        for (ima = G.main->image.first; ima; ima = ima->id.next) {
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                /* some of the images could have been changed during bake,
                 * so recreate mipmaps regardless bake result status
@@ -1383,6 +1395,8 @@ static void finish_bake_internal(BakeRender *bkr)
                                ibuf->userdata = NULL;
                        }
                }
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 }
 
index c0c2195..4d6b9ed 100644 (file)
@@ -1380,7 +1380,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d)
                                                if (ma->mtex[b] && ma->mtex[b]->tex) {
                                                        tex = ma->mtex[b]->tex;
                                                        if (tex->type == TEX_IMAGE && tex->ima) {
-                                                               ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, NULL);
+                                                               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, NULL, NULL);
                                                                
                                                                /* texturespace */
                                                                space = 1.0;
@@ -1402,6 +1402,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d)
                                                                
                                                                done = TRUE;
                                                                DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+
+                                                               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
                                                        }
                                                }
                                                if (done) break;
index 4b17762..7b67f63 100644 (file)
@@ -375,7 +375,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
                /* make jobs timer to send notifier */
                *(rj->do_update) = TRUE;
        }
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 }
 
 static void render_startjob(void *rjv, short *stop, short *do_update, float *progress)
index e4592a4..effb984 100644 (file)
@@ -288,7 +288,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                }
        }
        
-       BKE_image_release_ibuf(oglrender->ima, lock);
+       BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
 }
 
 static int screen_opengl_render_init(bContext *C, wmOperator *op)
@@ -613,7 +613,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
                IMB_freeImBuf(ibuf);
        }
 
-       BKE_image_release_ibuf(oglrender->ima, lock);
+       BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
 
        /* movie stats prints have no line break */
        printf("\n");
index b119165..a864fe3 100644 (file)
@@ -934,13 +934,15 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
                /* elubie: this needs to be changed: here image is always loaded if not
                 * already there. Very expensive for large images. Need to find a way to 
                 * only get existing ibuf */
-               ibuf = BKE_image_get_ibuf(ima, &iuser);
+               ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
                if (ibuf == NULL || ibuf->rect == NULL)
                        return;
                
                icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect);
 
                *do_update = TRUE;
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
        else if (idtype == ID_BR) {
                Brush *br = (Brush *)id;
index 4b40062..192ad35 100644 (file)
@@ -500,7 +500,7 @@ static void image_undo_restore(bContext *C, ListBase *lb)
                        ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name));
                }
 
-               ibuf = BKE_image_get_ibuf(ima, NULL);
+               ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) {
                        /* current ImBuf filename was changed, probably current frame
@@ -508,19 +508,27 @@ static void image_undo_restore(bContext *C, ListBase *lb)
                         * full image user (which isn't so obvious, btw) try to find ImBuf with
                         * matched file name in list of already loaded images */
 
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+
                        ibuf = BLI_findstring(&ima->ibufs, tile->ibufname, offsetof(ImBuf, name));
                }
 
-               if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
+               if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        continue;
+               }
 
-               if (ima->gen_type != tile->gen_type || ima->source != tile->source)
+               if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        continue;
+               }
 
                use_float = ibuf->rect_float ? 1 : 0;
 
-               if (use_float != tile->use_float)
+               if (use_float != tile->use_float) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        continue;
+               }
 
                undo_copy_tile(tile, tmpibuf, ibuf, 1);
 
@@ -530,6 +538,8 @@ static void image_undo_restore(bContext *C, ListBase *lb)
                if (ibuf->mipmap[0])
                        ibuf->userflags |= IB_MIPMAP_INVALID;  /* force mipmap recreatiom */
                ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 
        IMB_freeImBuf(tmpibuf);
@@ -1398,8 +1408,8 @@ static float project_paint_uvpixel_mask(
                Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index);
                const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
                
-               if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) {
-                       /* BKE_image_get_ibuf - TODO - this may be slow */
+               if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+                       /* BKE_image_acquire_ibuf - TODO - this may be slow */
                        unsigned char rgba_ub[4];
                        float rgba_f[4];
                        
@@ -1411,7 +1421,9 @@ static float project_paint_uvpixel_mask(
                        else { /* from char to float */
                                mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f);
                        }
-                       
+
+                       BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
+
                        if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */
                                mask = (1.0f - mask);
 
@@ -1579,8 +1591,8 @@ static ProjPixel *project_paint_uvpixel_init(
                        Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index);
                        const MTFace *tf_other = ps->dm_mtface_clone + face_index;
                        
-                       if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) {
-                               /* BKE_image_get_ibuf - TODO - this may be slow */
+                       if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+                               /* BKE_image_acquire_ibuf - TODO - this may be slow */
                                
                                if (ibuf->rect_float) {
                                        if (ibuf_other->rect_float) { /* from float to float */
@@ -1602,6 +1614,8 @@ static ProjPixel *project_paint_uvpixel_init(
                                                project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
                                        }
                                }
+
+                               BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
                        }
                        else {
                                if (ibuf->rect_float) {
@@ -3408,7 +3422,7 @@ static void project_paint_begin(ProjPaintState *ps)
                                
                                image_index = BLI_linklist_index(image_LinkList, tpage);
                                
-                               if (image_index == -1 && BKE_image_get_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
+                               if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
                                        BLI_linklist_append(&image_LinkList, tpage);
                                        image_index = ps->image_tot;
                                        ps->image_tot++;
@@ -3431,7 +3445,7 @@ static void project_paint_begin(ProjPaintState *ps)
        for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
                projIma->ima = node->link;
                projIma->touch = 0;
-               projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
+               projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
                projIma->partRedrawRect =  BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
                memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
        }
@@ -3458,6 +3472,7 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2])
 static void project_paint_end(ProjPaintState *ps)
 {
        int a;
+       ProjPaintImage *projIma;
        
        /* build undo data from original pixel colors */
        if (U.uiflag & USER_GLOBALUNDO) {
@@ -3545,7 +3560,14 @@ static void project_paint_end(ProjPaintState *ps)
                if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
        }
        /* done calculating undo data */
-       
+
+       /* dereference used image buffers */
+       for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+               BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
+       }
+
+       BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
+
        MEM_freeN(ps->screenCoords);
        MEM_freeN(ps->bucketRect);
        MEM_freeN(ps->bucketFaces);
@@ -4672,7 +4694,7 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float
 
 static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
        
        /* verify that we can paint and set canvas */
        if (ima == NULL) {
@@ -4695,10 +4717,12 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
        /* set clone canvas */
        if (s->tool == PAINT_TOOL_CLONE) {
                ima = s->brush->clone.image;
-               ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL);
+               ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
                
-               if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
+               if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        return 0;
+               }
 
                s->clonecanvas = ibuf;
 
@@ -4713,13 +4737,15 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
        return 1;
 }
 
-static void imapaint_canvas_free(ImagePaintState *UNUSED(s))
+static void imapaint_canvas_free(ImagePaintState *s)
 {
+       BKE_image_release_ibuf(s->image, s->canvas, NULL);
+       BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
 }
 
 static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL);
        float pos[2];
        int is_data;
 
@@ -4739,9 +4765,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
        if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) {
                if (update)
                        imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint);
+               BKE_image_release_ibuf(image, ibuf, NULL);
                return 1;
        }
-       else return 0;
+       else {
+               BKE_image_release_ibuf(image, ibuf, NULL);
+               return 0;
+       }
 }
 
 static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure)
@@ -4759,7 +4789,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
                        ImBuf *ibuf;
                        
                        newimage = imapaint_face_image(s, newfaceindex);
-                       ibuf = BKE_image_get_ibuf(newimage, s->sima ? &s->sima->iuser : NULL);
+                       ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL);
 
                        if (ibuf && ibuf->rect)
                                imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv);
@@ -4767,6 +4797,8 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint
                                newimage = NULL;
                                newuv[0] = newuv[1] = 0.0f;
                        }
+
+                       BKE_image_release_ibuf(newimage, ibuf, NULL);
                }
                else
                        newuv[0] = newuv[1] = 0.0f;
@@ -5890,7 +5922,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
        }
 
        ps.reproject_image = image;
-       ps.reproject_ibuf = BKE_image_get_ibuf(image, NULL);
+       ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
 
        if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) {
                BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
index ae7a718..0a3db59 100644 (file)
@@ -593,7 +593,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
                if (ima->source == IMA_SRC_VIEWER) {
                        ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
                        image_info(scene, iuser, ima, ibuf, str);
-                       BKE_image_release_ibuf(ima, lock);
+                       BKE_image_release_ibuf(ima, ibuf, lock);
 
                        uiItemL(layout, ima->id.name + 2, ICON_NONE);
                        uiItemL(layout, str, ICON_NONE);
@@ -663,7 +663,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
                                if (compact == 0) {
                                        ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
                                        image_info(scene, iuser, ima, ibuf, str);
-                                       BKE_image_release_ibuf(ima, lock);
+                                       BKE_image_release_ibuf(ima, ibuf, lock);
                                        uiItemL(layout, str, ICON_NONE);
                                }
                        }
@@ -722,7 +722,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
                                split = uiLayoutSplit(layout, 0.0f, FALSE);
 
                                col = uiLayoutColumn(split, TRUE);
-                               uiLayoutSetEnabled(col, 0);
                                uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
                                uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
                                
index 9fc2b98..d565e6f 100644 (file)
@@ -652,7 +652,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int
        if (!brush || !brush->clone.image)
                return NULL;
        
-       ibuf = BKE_image_get_ibuf(brush->clone.image, NULL);
+       ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
 
        if (!ibuf)
                return NULL;
@@ -660,6 +660,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int
        display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
 
        if (!display_buffer) {
+               BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
                IMB_display_buffer_release(cache_handle);
 
                return NULL;
@@ -669,8 +670,10 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int
 
        IMB_display_buffer_release(cache_handle);
 
-       if (!rect)
+       if (!rect) {
+               BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
                return NULL;
+       }
 
        *width = ibuf->x;
        *height = ibuf->y;
@@ -684,6 +687,8 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int
                cp += 4;
        }
 
+       BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+
        return rect;
 }
 
@@ -799,7 +804,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
        }
 #endif
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 
        if (show_viewer) {
                BLI_unlock_thread(LOCK_DRAW_IMAGE);
index 4ca2f88..c4e2230 100644 (file)
@@ -117,8 +117,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
 #endif
                ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r);
 
-               if (ibuf && (ibuf->rect || ibuf->rect_float))
-                       return ibuf;
+               if (ibuf) {
+                       if (ibuf->rect || ibuf->rect_float)
+                               return ibuf;
+
+                       BKE_image_release_ibuf(sima->image, ibuf, NULL);
+               }
        }
        else
                *lock_r = NULL;
@@ -126,10 +130,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r)
        return NULL;
 }
 
-void ED_space_image_release_buffer(SpaceImage *sima, void *lock)
+void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock)
 {
        if (sima && sima->image)
-               BKE_image_release_ibuf(sima->image, lock);
+               BKE_image_release_ibuf(sima->image, ibuf, lock);
 }
 
 int ED_space_image_has_buffer(SpaceImage *sima)
@@ -140,7 +144,7 @@ int ED_space_image_has_buffer(SpaceImage *sima)
 
        ibuf = ED_space_image_acquire_buffer(sima, &lock);
        has_buffer = (ibuf != NULL);
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 
        return has_buffer;
 }
@@ -175,7 +179,7 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
                *height = IMG_SIZE_FALLBACK;
        }
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 }
 
 void ED_space_image_get_size_fl(SpaceImage *sima, float size[2])
index ce3c6e1..d4f24ba 100644 (file)
@@ -167,7 +167,7 @@ static int space_image_file_exists_poll(bContext *C)
                                ret = TRUE;
                        }
                }
-               ED_space_image_release_buffer(sima, lock);
+               ED_space_image_release_buffer(sima, ibuf, lock);
 
                return ret;
        }
@@ -1188,7 +1188,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
                BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
        }
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 
        return (ibuf != NULL);
 }
@@ -1328,7 +1328,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
                        IMB_freeImBuf(colormanaged_ibuf);
        }
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 }
 
 static void image_save_as_free(wmOperator *op)
@@ -1743,17 +1743,14 @@ void IMAGE_OT_new(wmOperatorType *ot)
 static int image_invert_poll(bContext *C)
 {
        Image *ima = CTX_data_edit_image(C);
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
-       
-       if (ibuf != NULL)
-               return 1;
-       return 0;
+
+       return BKE_image_has_ibuf(ima, NULL);
 }
 
 static int image_invert_exec(bContext *C, wmOperator *op)
 {
        Image *ima = CTX_data_edit_image(C);
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
 
        /* flags indicate if this channel should be inverted */
        const short r = RNA_boolean_get(op->ptr, "invert_r");
@@ -1792,6 +1789,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
                }
        }
        else {
+               BKE_image_release_ibuf(ima, ibuf, NULL);
                return OPERATOR_CANCELLED;
        }
 
@@ -1800,6 +1798,9 @@ static int image_invert_exec(bContext *C, wmOperator *op)
                ibuf->userflags |= IB_MIPMAP_INVALID;
 
        WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return OPERATOR_FINISHED;
 }
 
@@ -1848,7 +1849,7 @@ static int image_pack_exec(bContext *C, wmOperator *op)
 {
        struct Main *bmain = CTX_data_main(C);
        Image *ima = CTX_data_edit_image(C);
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        int as_png = RNA_boolean_get(op->ptr, "as_png");
 
        if (!image_pack_test(C, op))
@@ -1865,30 +1866,38 @@ static int image_pack_exec(bContext *C, wmOperator *op)
                ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
 
        WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
-       
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return OPERATOR_FINISHED;
 }
 
 static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 {
        Image *ima = CTX_data_edit_image(C);
-       ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf;
        uiPopupMenu *pup;
        uiLayout *layout;
        int as_png = RNA_boolean_get(op->ptr, "as_png");
 
        if (!image_pack_test(C, op))
                return OPERATOR_CANCELLED;
-       
+
+       ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
        if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
                pup = uiPupMenuBegin(C, "OK", ICON_QUESTION);
                layout = uiPupMenuLayout(pup);
                uiItemBooleanO(layout, "Can't pack edited image from disk. Pack as internal PNG?", ICON_NONE, op->idname, "as_png", 1);
                uiPupMenuEnd(C, pup);
 
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+
                return OPERATOR_CANCELLED;
        }
 
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return image_pack_exec(C, op);
 }
 
@@ -2032,7 +2041,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa
        int ret = FALSE;
 
        if (ibuf == NULL) {
-               ED_space_image_release_buffer(sima, lock);
+               ED_space_image_release_buffer(sima, ibuf, lock);
                return FALSE;
        }
 
@@ -2058,7 +2067,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa
                }
        }
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
        return ret;
 }
 
@@ -2074,7 +2083,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
        CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
 
        if (ibuf == NULL) {
-               ED_space_image_release_buffer(sima, lock);
+               ED_space_image_release_buffer(sima, ibuf, lock);
                info->draw = 0;
                return;
        }
@@ -2175,7 +2184,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
                info->draw = 0;
        }
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
        ED_area_tag_redraw(CTX_wm_area(C));
 }
 
@@ -2266,12 +2275,12 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
        float x1f, y1f, x2f, y2f;
        
        if (ibuf == NULL) {
-               ED_space_image_release_buffer(sima, lock);
+               ED_space_image_release_buffer(sima, ibuf, lock);
                return OPERATOR_CANCELLED;
        }
        /* hmmmm */
        if (ibuf->channels < 3) {
-               ED_space_image_release_buffer(sima, lock);
+               ED_space_image_release_buffer(sima, ibuf, lock);
                return OPERATOR_CANCELLED;
        }
        
@@ -2288,7 +2297,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
        /* reset y zoom */
        hist->ymax = 1.0f;
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
        
        ED_area_tag_redraw(CTX_wm_area(C));
        
@@ -2383,11 +2392,13 @@ static int image_record_composite_apply(bContext *C, wmOperator *op)
 
        ED_area_tag_redraw(CTX_wm_area(C));
        
-       ibuf = BKE_image_get_ibuf(sima->image, &sima->iuser);
+       ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL);
        /* save memory in flipbooks */
        if (ibuf)
                imb_freerectfloatImBuf(ibuf);
-       
+
+       BKE_image_release_ibuf(sima->image, ibuf, NULL);
+
        scene->r.cfra++;
 
        return (scene->r.cfra <= rcd->efra);
index 4131cbf..ea69677 100644 (file)
@@ -780,7 +780,7 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar)
                }
                scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
        }
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
        
        ED_region_panels(C, ar, 1, NULL, -1);
 }
index 131908b..48b5eaf 100644 (file)
@@ -87,10 +87,14 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
        // first check for dirty images
        for (ima = bmain->image.first; ima; ima = ima->id.next) {
                if (ima->ibufs.first) { /* XXX FIX */
-                       ibuf = BKE_image_get_ibuf(ima, NULL);
+                       ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
                        
-                       if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+                       if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
+                               BKE_image_release_ibuf(ima, ibuf, NULL);
                                break;
+                       }
+
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                }
        }
 
index f808a08..e842bb5 100644 (file)
@@ -3313,7 +3313,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
                        glPopMatrix();
                }
 
-               BKE_image_release_ibuf(ima, lock);
+               BKE_image_release_ibuf(ima, ibuf, lock);
        }
 }
 
@@ -3326,7 +3326,7 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
        
        if (snode->flag & SNODE_BACKDRAW) {
                Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
                if (ibuf) {
                        int x, y;
                        float zoom = 1.0;
@@ -3362,6 +3362,8 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
                        glPopMatrix();
                        glMatrixMode(GL_MODELVIEW);
                        glPopMatrix();
+
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                }
        }
 }
index a4ea2e3..f386657 100644 (file)
@@ -241,7 +241,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
        ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
 
        if (ibuf == NULL) {
-               BKE_image_release_ibuf(ima, lock);
+               BKE_image_release_ibuf(ima, ibuf, lock);
                return OPERATOR_CANCELLED;
        }
 
@@ -255,7 +255,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
        nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad;
        nvm->ymax =  (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad;
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 
        /* add modal handler */
        WM_event_add_modal_handler(C, op);
@@ -403,7 +403,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
                }
        }
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 
        return ret;
 }
@@ -493,7 +493,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
                ED_node_sample_set(NULL);
        }
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 
        ED_area_tag_redraw(CTX_wm_area(C));
 }
index cb55563..f35a844 100644 (file)
@@ -728,7 +728,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
                        BKE_bproperty_set_valstr(prop, string);
                        characters = strlen(string);
                        
-                       if (!BKE_image_get_ibuf(mtpoly->tpage, NULL))
+                       if (!BKE_image_has_ibuf(mtpoly->tpage, NULL))
                                characters = 0;
 
                        if (!mf_smooth) {
index 729f810..08ba4fb 100644 (file)
@@ -530,7 +530,7 @@ void drawaxes(float size, char drawtype)
 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
 {
        Image *ima = (Image *)ob->data;
-       ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL;
+       ImBuf *ibuf = ima ? BKE_image_acquire_ibuf(ima, NULL, NULL) : NULL;
 
        float scale, ofs_x, ofs_y, sca_x, sca_y;
        int ima_x, ima_y;
@@ -615,6 +615,8 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
        /* Reset GL settings */
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4])
index 24fc6ad..a9b3823 100644 (file)
@@ -1561,7 +1561,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
                                        ibuf = NULL; /* frame is out of range, dont show */
                                }
                                else {
-                                       ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser);
+                                       ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL);
+                                       freeibuf = ibuf;
                                }
 
                                image_aspect[0] = ima->aspx;
index 7bd7243..e3ba4cb 100644 (file)
@@ -318,7 +318,7 @@ static void gpu_make_repbind(Image *ima)
 {
        ImBuf *ibuf;
        
-       ibuf = BKE_image_get_ibuf(ima, NULL);
+       ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        if (ibuf==NULL)
                return;
 
@@ -333,6 +333,8 @@ static void gpu_make_repbind(Image *ima)
 
        if (ima->totbind>1)
                ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 static void gpu_clear_tpage(void)
@@ -479,7 +481,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
                return 0;
 
        /* check if we have a valid image buffer */
-       ibuf= BKE_image_get_ibuf(ima, iuser);
+       ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL);
 
        if (ibuf==NULL)
                return 0;
@@ -574,6 +576,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
        if (*bind != 0) {
                /* enable opengl drawing with textures */
                glBindTexture(GL_TEXTURE_2D, *bind);
+               BKE_image_release_ibuf(ima, ibuf, NULL);
                return *bind;
        }
 
@@ -635,6 +638,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
        if (srgb_frect)
                MEM_freeN(srgb_frect);
 
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return *bind;
 }
 
@@ -896,7 +901,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
 {
        ImBuf *ibuf;
        
-       ibuf = BKE_image_get_ibuf(ima, NULL);
+       ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
        
        if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
            (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) ||
@@ -935,6 +940,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
                                ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
                        }
 
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                        return;
                }
                
@@ -959,6 +965,8 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
                        ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
                }
        }
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 void GPU_update_images_framechange(void)
index ef73764..497105d 100644 (file)
@@ -1165,13 +1165,14 @@ static void do_material_tex(GPUShadeInput *shi)
 
                                                // resolve texture resolution
                                                if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
-                                                       ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser);
+                                                       ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
                                                        ima_x= 512.0f; ima_y= 512.f;            // prevent calling textureSize, glsl 1.3 only
                                                        if (ibuf) {
                                                                ima_x= ibuf->x;
                                                                ima_y= ibuf->y;
                                                                aspect = ((float) ima_y) / ima_x;
                                                        }
+                                                       BKE_image_release_ibuf(tex->ima, ibuf, NULL);
                                                }
 
                                                // The negate on norfac is done because the
index f8af242..9fedbee 100644 (file)
@@ -113,7 +113,7 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
                        BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
        }
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 }
 
 static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -187,8 +187,12 @@ static EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), PointerRNA
 static int rna_Image_file_format_get(PointerRNA *ptr)
 {
        Image *image = (Image *)ptr->data;
-       ImBuf *ibuf = BKE_image_get_ibuf(image, NULL);
-       return BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+       int imtype = BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0);
+
+       BKE_image_release_ibuf(image, ibuf, NULL);
+
+       return imtype;
 }
 
 static void rna_Image_file_format_set(PointerRNA *ptr, int value)
@@ -199,12 +203,13 @@ static void rna_Image_file_format_set(PointerRNA *ptr, int value)
                int ftype = BKE_imtype_to_ftype(value);
 
 #if 0
-               ibuf = BKE_image_get_ibuf(image, NULL);
+               ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
                if (ibuf)
                        ibuf->ftype = ftype;
 #endif
 
                /* to be safe change all buffer file types */
+               /* TODO: this is never threadsafe */
                for (ibuf = image->ibufs.first; ibuf; ibuf = ibuf->next) {
                        ibuf->ftype = ftype;
                }
@@ -237,7 +242,7 @@ static void rna_Image_size_get(PointerRNA *ptr, int *values)
                values[1] = 0;
        }
 
-       BKE_image_release_ibuf(im, lock);
+       BKE_image_release_ibuf(im, ibuf, lock);
 }
 
 static void rna_Image_resolution_get(PointerRNA *ptr, float *values)
@@ -256,7 +261,7 @@ static void rna_Image_resolution_get(PointerRNA *ptr, float *values)
                values[1] = 0;
        }
 
-       BKE_image_release_ibuf(im, lock);
+       BKE_image_release_ibuf(im, ibuf, lock);
 }
 
 static void rna_Image_resolution_set(PointerRNA *ptr, const float *values)
@@ -271,7 +276,7 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values)
                ibuf->ppm[1] = values[1];
        }
 
-       BKE_image_release_ibuf(im, lock);
+       BKE_image_release_ibuf(im, ibuf, lock);
 }
 
 static int rna_Image_depth_get(PointerRNA *ptr)
@@ -290,7 +295,7 @@ static int rna_Image_depth_get(PointerRNA *ptr)
        else
                planes = ibuf->planes;
 
-       BKE_image_release_ibuf(im, lock);
+       BKE_image_release_ibuf(im, ibuf, lock);
 
        return planes;
 }
@@ -317,7 +322,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY
        else
                length[0] = 0;
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 
        return length[0];
 }
@@ -343,7 +348,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values)
                }
        }
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 }
 
 static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
@@ -369,7 +374,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
                ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
        }
 
-       BKE_image_release_ibuf(ima, lock);
+       BKE_image_release_ibuf(ima, ibuf, lock);
 }
 
 #else
index cb5c515..686e6c8 100644 (file)
@@ -99,7 +99,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
                                IMB_freeImBuf(write_ibuf);
                }
 
-               BKE_image_release_ibuf(image, lock);
+               BKE_image_release_ibuf(image, ibuf, lock);
        }
        else {
                BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters");
@@ -108,7 +108,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
 
 static void rna_Image_save(Image *image, ReportList *reports)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(image, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
        if (ibuf) {
                char filename[FILE_MAX];
                BLI_strncpy(filename, image->name, sizeof(filename));
@@ -136,11 +136,13 @@ static void rna_Image_save(Image *image, ReportList *reports)
        else {
                BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
        }
+
+       BKE_image_release_ibuf(image, ibuf, NULL);
 }
 
 static void rna_Image_pack(Image *image, ReportList *reports, int as_png)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(image, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
 
        if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
                BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG");
@@ -153,6 +155,8 @@ static void rna_Image_pack(Image *image, ReportList *reports, int as_png)
                        image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(G.main, &image->id));
                }
        }
+
+       BKE_image_release_ibuf(image, ibuf, NULL);
 }
 
 static void rna_Image_unpack(Image *image, ReportList *reports, int method)
@@ -177,7 +181,7 @@ static void rna_Image_reload(Image *image)
 
 static void rna_Image_update(Image *image, ReportList *reports)
 {
-       ImBuf *ibuf = BKE_image_get_ibuf(image, NULL);
+       ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
 
        if (ibuf == NULL) {
                BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
@@ -188,6 +192,8 @@ static void rna_Image_update(Image *image, ReportList *reports)
                IMB_rect_from_float(ibuf);
 
        ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+       BKE_image_release_ibuf(image, ibuf, NULL);
 }
 
 static void rna_Image_scale(Image *image, ReportList *reports, int width, int height)
@@ -206,10 +212,11 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int
        if (*bind)
                return error;
 
-       ibuf = BKE_image_get_ibuf(image, NULL);
+       ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
 
        if (ibuf == NULL || ibuf->rect == NULL) {
                BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
+               BKE_image_release_ibuf(image, ibuf, NULL);
                return (int)GL_INVALID_OPERATION;
        }
 
@@ -238,6 +245,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int
                image->bindcode = 0;
        }
 
+       BKE_image_release_ibuf(image, ibuf, NULL);
+
        return error;
 }
 
index 962a922..caa81da 100644 (file)
@@ -598,7 +598,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS
        alpha = ibuf && (ibuf->channels == 4);
        zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1));
 
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 
        if (alpha && zbuf)
                return draw_channels_items;
@@ -678,7 +678,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
                scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
                WM_main_add_notifier(NC_IMAGE, sima->image);
        }
-       ED_space_image_release_buffer(sima, lock);
+       ED_space_image_release_buffer(sima, ibuf, lock);
 }
 
 /* Space Text Editor */
index 150382c..88d78df 100644 (file)
@@ -173,9 +173,10 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
        Image *ima= (Image *)node->id;
        if (ima) {
                ImageUser *iuser= node->storage;
+               ImBuf *ibuf;
                
                /* make sure ima->type is correct */
-               BKE_image_get_ibuf(ima, iuser);
+               ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
                
                if (ima->rr) {
                        RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
@@ -191,6 +192,8 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
                }
                else
                        cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z);
+               
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
        else
                cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
@@ -312,7 +315,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
 }
 
 /* note: this function is used for multilayer too, to ensure uniform 
- * handling with BKE_image_get_ibuf() */
+ * handling with BKE_image_acquire_ibuf() */
 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
 {
        ImBuf *ibuf;
@@ -322,7 +325,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
        float *rect;
        int alloc= FALSE;
 
-       ibuf= BKE_image_get_ibuf(ima, iuser);
+       ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL);
        if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
                return NULL;
        }
@@ -374,12 +377,15 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
                }
        }
 #endif
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        return stackbuf;
 }
 
 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
 {
-       ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
+       ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL);
        CompBuf *zbuf= NULL;
        
        if (ibuf && ibuf->zbuf_float) {
@@ -391,6 +397,9 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
                        zbuf->rect= ibuf->zbuf_float;
                }
        }
+
+       BKE_image_release_ibuf((Image *)node->id, ibuf, NULL);
+
        return zbuf;
 }
 
@@ -418,13 +427,14 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE
                RenderData *rd= data;
                Image *ima= (Image *)node->id;
                ImageUser *iuser= (ImageUser *)node->storage;
+               ImBuf *ibuf = NULL;
                
                /* first set the right frame number in iuser */
                BKE_image_user_frame_calc(iuser, rd->cfra, 0);
                
                /* force a load, we assume iuser index will be set OK anyway */
                if (ima->type==IMA_TYPE_MULTILAYER)
-                       BKE_image_get_ibuf(ima, iuser);
+                       ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
                
                if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
                        RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
@@ -505,6 +515,8 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE
                                generate_preview(data, node, stackbuf);
                        }
                }
+
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 }
 
index 73cf039..81f2f9b 100644 (file)
@@ -128,7 +128,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack *
                
                composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL);
                
-               BKE_image_release_ibuf(ima, lock);
+               BKE_image_release_ibuf(ima, ibuf, lock);
                
                generate_preview(data, node, cbuf);
                free_compbuf(cbuf);
index 938f75c..b186a9a 100644 (file)
@@ -112,7 +112,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in,
                        free_compbuf(zbuf);
                }
 
-               BKE_image_release_ibuf(ima, lock);
+               BKE_image_release_ibuf(ima, ibuf, lock);
 
                generate_preview(data, node, cbuf);
                free_compbuf(cbuf);
index abe8e01..d2d0870 100644 (file)
@@ -75,12 +75,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod
        ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata));
 
        if (ret) {
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
                if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
                    GPU_material_do_color_management(mat))
                {
                        GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
                }
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 
        return ret;
index 9b17f76..49b3843 100644 (file)
@@ -75,12 +75,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack
        ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
 
        if (ret) {
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
                if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
                    GPU_material_do_color_management(mat))
                {
                        GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
                }
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
 
        return ret;
index 6d1b3ff..b77c7d0 100644 (file)
@@ -128,12 +128,13 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
                int ret = GPU_stack_link(mat, "texture_image", in, out, texlink);
 
                if (ret) {
-                       ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser);
+                       ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
                        if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) ==0 &&
                            GPU_material_do_color_management(mat))
                        {
                                GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link);
                        }
+                       BKE_image_release_ibuf(tex->ima, ibuf, NULL);
                }
 
                return ret;
index f3fdaf0..2ef1669 100644 (file)
@@ -46,7 +46,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i
        ImageUser *iuser= (ImageUser *)node->storage;
        
        if ( ima ) {
-               ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
                if ( ibuf ) {
                        float xsize, ysize;
                        float xoff, yoff;
@@ -77,6 +77,8 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i
                        
                        result = ibuf->rect_float + py*ibuf->x*4 + px*4;
                        copy_v4_v4(out, result);
+
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                }
        }
 }
index 28f7021..c3126e5 100644 (file)
@@ -687,11 +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_get_ibuf(env->ima, NULL);
+                               ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL);
                                if (ibuf_ima)
                                        envmap_split_ima(env, ibuf_ima);
                                else
                                        env->ok = 0;
+                               BKE_image_release_ibuf(env->ima, ibuf_ima, NULL);
                        }
                }
        }
index db1454f..cd06839 100644 (file)
@@ -124,13 +124,16 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                /* hack for icon render */
                if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
                        return retval;
-               
-               ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
+
+               ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
 
                ima->flag|= IMA_USED_FOR_RENDER;
        }
-       if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
+       if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
+               if (ima)
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                return retval;
+       }
        
        /* setup mapping */
        if (tex->imaflag & TEX_IMAROT) {
@@ -155,11 +158,17 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                                /* pass */
                        }
                        else {
+                               if (ima)
+                                       BKE_image_release_ibuf(ima, ibuf, NULL);
                                return retval;
                        }
                }
                if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
-                       if ((xs+ys) & 1) return retval;
+                       if ((xs+ys) & 1) {
+                               if (ima)
+                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                               return retval;
+                       }
                }
                /* scale around center, (0.5, 0.5) */
                if (tex->checkerdist<1.0f) {
@@ -173,11 +182,15 @@ 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);
                        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);
                        return retval;
                }
        }
@@ -287,6 +300,9 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
                texres->tb*= fx;
        }
        
+       if (ima)
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+       
        BRICONTRGB;
        
        return retval;
@@ -1056,10 +1072,14 @@ 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_get_ibuf(ima, &tex->iuser); 
+               ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
        }
 
-       if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval;
+       if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
+               if (ima)
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+               return retval;
+       }
 
        if (ima) {
                ima->flag |= IMA_USED_FOR_RENDER;
@@ -1172,8 +1192,16 @@ 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) return retval;
-                               if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval;
+                               if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
+                                       if (ima)
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       return retval;
+                               }
+                               if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
+                                       if (ima)
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       return retval;
+                               }
                                fx -= xs;
                                fy -= ys;
                        }
@@ -1189,10 +1217,18 @@ 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) return retval;
+               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);
+                       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) return retval;
+               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);
+                       return retval;
+               }
        }
        else {
                if (tex->extend == TEX_EXTEND) {
@@ -1413,6 +1449,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
                texres->tb *= fx;
        }
 
+       if (ima)
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+
        BRICONTRGB;
        
        return retval;
@@ -1449,12 +1488,15 @@ 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_get_ibuf(ima, &tex->iuser); 
+               ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
 
                ima->flag|= IMA_USED_FOR_RENDER;
        }
-       if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
+       if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
+               if (ima)
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                return retval;
+       }
        
        /* mipmap test */
        image_mipmap_test(tex, ibuf);
@@ -1565,11 +1607,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
                                                /* pass */
                                        }
                                        else {
+                                               if (ima)
+                                                       BKE_image_release_ibuf(ima, ibuf, NULL);
                                                return retval;
                                        }
                                }
                                if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
                                        if ((xs + ys) & 1) {
+                                               if (ima)
+                                                       BKE_image_release_ibuf(ima, ibuf, NULL);
                                                return retval;
                                        }
                                }
@@ -1605,11 +1651,15 @@ 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);
                        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);
                        return retval;
                }
        }
@@ -1804,6 +1854,9 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
                mul_v3_fl(&texres->tr, 1.0f / texres->ta);
        }
 
+       if (ima)
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+
        BRICONTRGB;
        
        return retval;
@@ -1812,7 +1865,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4])
 {
        TexResult texres;
-       ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+       ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
        
        if (UNLIKELY(ibuf == NULL)) {
                zero_v4(result);
@@ -1830,6 +1883,8 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu
                ibuf->rect-= (ibuf->x*ibuf->y);
 
        ima->flag|= IMA_USED_FOR_RENDER;
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
 }
 
 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
index f2549f0..1b237d6 100644 (file)
@@ -63,6 +63,7 @@
 #include "BLI_string.h"
 #include "BLI_path_util.h"
 #include "BLI_fileops.h"
+#include "BLI_threads.h"
 #include "BLI_rand.h"
 #include "BLI_callbacks.h"
 
index c507d65..e6daa5f 100644 (file)
@@ -1233,11 +1233,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
                        rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
 
                        if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
-                               ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser);
+                               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
                                
                                /* 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);
                        }
                }
                else {
@@ -1264,11 +1266,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
                        rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output);
 
                        {
-                               ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser);
+                               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
 
                                /* 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);
                        }
                }
 
@@ -1723,11 +1727,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_get_ibuf(tex->ima, &tex->iuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
                if (ibuf) {
                        du = 1.f/(float)ibuf->x;
                        dv = 1.f/(float)ibuf->y;
                }
+               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
        }
        else if (shi->osatex) {
                /* we have derivatives, can compute proper du/dv */
@@ -1900,12 +1905,13 @@ 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_get_ibuf(tex->ima, &tex->iuser);
+               ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
                if (ibuf) {
                        dimx = ibuf->x;
                        dimy = ibuf->y;
                        aspect = ((float) dimy) / dimx;
                }
+               BKE_image_release_ibuf(tex->ima, ibuf, NULL);
        }
        
        if (found_deriv_map) {
@@ -2396,11 +2402,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_get_ibuf(ima, &tex->iuser);
+                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
                                        
                                        /* 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);
                                }
                                
                                if (mtex->mapto & MAP_COL) {
@@ -2928,11 +2936,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_get_ibuf(ima, &mtex->tex->iuser);
+                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL);
                        
                        /* 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);
                }
 
                fact= texres.tin*mtex->colfac;
@@ -3147,11 +3157,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_get_ibuf(ima, &tex->iuser);
+                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
                                        
                                        /* 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);
                                }
 
                                if (mtex->mapto & WOMAP_HORIZ) {
@@ -3361,11 +3373,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_get_ibuf(ima, &tex->iuser);
+                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
                                        
                                        /* 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);
                                }
 
                                /* lamp colors were premultiplied with this */
index 9fe2620..3431c3f 100644 (file)
@@ -2506,21 +2506,26 @@ static int get_next_bake_face(BakeShade *bs)
 
                                if (tface && tface->tpage) {
                                        Image *ima= tface->tpage;
-                                       ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+                                       ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
                                        const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
                                        const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
                                        
                                        if (ibuf==NULL)
                                                continue;
                                        
-                                       if (ibuf->rect==NULL && ibuf->rect_float==NULL)
+                                       if (ibuf->rect==NULL && ibuf->rect_float==NULL) {
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
                                                continue;
+                                       }
                                        
-                                       if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
+                                       if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) {
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
                                                continue;
+                                       }
                                        
                                        if (ima->flag & IMA_USED_FOR_RENDER) {
                                                ima->id.flag &= ~LIB_DOIT;
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
                                                continue;
                                        }
                                        
@@ -2548,6 +2553,9 @@ static int get_next_bake_face(BakeShade *bs)
                                        v++;
                                        
                                        BLI_unlock_thread(LOCK_CUSTOM1);
+
+                                       BKE_image_release_ibuf(ima, ibuf, NULL);
+
                                        return 1;
                                }
                        }
@@ -2571,8 +2579,10 @@ static void shade_tface(BakeShade *bs)
        
        /* check valid zspan */
        if (ima!=bs->ima) {
+               BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
                bs->ima= ima;
-               bs->ibuf= BKE_image_get_ibuf(ima, NULL);
+               bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
                /* note, these calls only free/fill contents of zspan struct, not zspan itself */
                zbuf_free_span(bs->zspan);
                zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
@@ -2638,7 +2648,9 @@ static void *do_bake_thread(void *bs_v)
                        *bs->do_update= TRUE;
        }
        bs->ready= 1;
-       
+
+       BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
        return NULL;
 }
 
@@ -2689,12 +2701,13 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        
        /* baker uses this flag to detect if image was initialized */
        for (ima= G.main->image.first; ima; ima= ima->id.next) {
-               ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+               ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
                ima->id.flag |= LIB_DOIT;
                ima->flag&= ~IMA_USED_FOR_RENDER;
                if (ibuf) {
                        ibuf->userdata = NULL; /* use for masking if needed */
                }
+               BKE_image_release_ibuf(ima, ibuf, NULL);
        }
        
        BLI_init_threads(&threads, do_bake_thread, re->r.threads);
@@ -2747,7 +2760,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        /* filter and refresh images */
        for (ima= G.main->image.first; ima; ima= ima->id.next) {
                if ((ima->id.flag & LIB_DOIT)==0) {
-                       ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
+                       ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
 
                        if (ima->flag & IMA_USED_FOR_RENDER)
                                result= BAKE_RESULT_FEEDBACK_LOOP;
@@ -2758,6 +2771,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
                        RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
 
                        ibuf->userflags |= IB_BITMAPDIRTY;
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
                }
        }
        
index 42849a0..77d6644 100644 (file)
@@ -157,10 +157,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
 
        /* find the first valid ibuf and use it to initialize the resolution of the data set */
        /* need to do this in advance so we know how much memory to allocate */
-       ibuf = BKE_image_get_ibuf(ima, &iuser);
+       ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
        while (!ibuf && (iuser.framenr < iuser.frames)) {
                iuser.framenr++;
-               ibuf = BKE_image_get_ibuf(ima, &iuser);
+               ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
        }
        if (!ibuf) return;
        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
@@ -175,7 +175,8 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
                /* get a new ibuf for each frame */
                if (z > 0) {
                        iuser.framenr++;
-                       ibuf = BKE_image_get_ibuf(ima, &iuser);
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
                        if (!ibuf) break;
                        if (!ibuf->rect_float) IMB_float_from_rect(ibuf);
                }
@@ -191,7 +192,9 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
                
                BKE_image_free_anim_ibufs(ima, iuser.framenr);
        }
-       
+
+       BKE_image_release_ibuf(ima, ibuf, NULL);
+
        vd->ok = 1;
        return;
 }
index 96bbedf..fba4506 100644 (file)
@@ -61,6 +61,7 @@
 
 #include "BKE_blender.h"
 #include "BKE_global.h"
+#include "BKE_image.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
@@ -1082,6 +1083,7 @@ void WM_main_playanim(int argc, const char **argv)
        /* we still miss freeing a lot!,
         * but many areas could skip initialization too for anim play */
        IMB_exit();
+       BKE_images_exit();
        BLF_exit();
 #endif
        GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
index ca3deaf..fc2f555 100644 (file)
@@ -1270,6 +1270,7 @@ int main(int argc, const char **argv)
        initglobals();  /* blender.c */
 
        IMB_init();
+       BKE_images_init();
 
 #ifdef WITH_FFMPEG
        IMB_ffmpeg_init();
index 3e8755c..4451c78 100644 (file)
@@ -60,6 +60,7 @@ extern "C"
 #include "BKE_blender.h"
 #include "BKE_global.h"
 #include "BKE_icons.h"
+#include "BKE_image.h"
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_library.h"
@@ -446,6 +447,7 @@ int main(int argc, char** argv)
        G.main = NULL;
 
        IMB_init();
+       BKE_images_init();
 
        // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
        BLF_init(11, U.dpi);
@@ -1067,6 +1069,7 @@ int main(int argc, char** argv)
 #endif
 
        IMB_exit();
+       BKE_images_exit();
        free_nodesystem();
 
        SYS_DeleteSystem(syshandle);
index 26523df..66423ed 100644 (file)
@@ -109,7 +109,7 @@ bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
                return mOk;
        }
 
-       ibuf= BKE_image_get_ibuf(img, NULL);
+       ibuf= BKE_image_acquire_ibuf(img, NULL, NULL);
        if (ibuf==NULL)
        {
                img->ok = 0;
@@ -128,6 +128,7 @@ bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
        if (mTexture != 0) {
                glBindTexture(GL_TEXTURE_2D, mTexture );
                Validate();
+               BKE_image_release_ibuf(img, ibuf, NULL);
                return mOk;
        }
 
@@ -140,6 +141,7 @@ bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
                        mTexture = mapLook->second.gl_texture;
                        glBindTexture(GL_TEXTURE_2D, mTexture);
                        mOk = IsValid();
+                       BKE_image_release_ibuf(img, ibuf, NULL);
                        return mOk;
                }
        }
@@ -166,6 +168,9 @@ bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
        glDisable(GL_TEXTURE_2D);
        ActivateUnit(0);
        Validate();
+
+       BKE_image_release_ibuf(img, ibuf, NULL);
+
        return mOk;
 }
 
@@ -251,7 +256,7 @@ bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
                return mOk;
        }
 
-       ImBuf *ibuf= BKE_image_get_ibuf(cubemap->ima, NULL);
+       ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL);
        if (ibuf==0)
        {
                cubemap->ima->ok = 0;
@@ -274,6 +279,7 @@ bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
                        mTexture = mapLook->second.gl_texture;
                        glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture);
                        mOk = IsValid();
+                       BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
                        return mOk;
                }
        }
@@ -307,6 +313,7 @@ bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
 
                my_free_envmapdata(cubemap);
                mOk = false;
+               BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
                return mOk;
        }
 
@@ -341,6 +348,9 @@ bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
        ActivateUnit(0);
 
        mOk = IsValid();
+
+       BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
+
        return mOk;
 }
 
@@ -646,9 +656,11 @@ int BL_Texture::GetPow2(int n)
 void BL_Texture::SplitEnvMap(EnvMap *map)
 {
        if (!map || !map->ima || (map->ima && !map->ima->ok)) return;
-       ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL);
-       if (ibuf)
+       ImBuf *ibuf= BKE_image_acquire_ibuf(map->ima, NULL, NULL);
+       if (ibuf) {
                my_envmap_split_ima(map, ibuf);
+               BKE_image_release_ibuf(map->ima, ibuf, NULL);
+       }
 }
 
 unsigned int BL_Texture::mDisableState = 0;