Clean-up and refactor of current OCIO integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 27 Jun 2012 18:10:53 +0000 (18:10 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 27 Jun 2012 18:10:53 +0000 (18:10 +0000)
- Cleaned up some files -- seems there were some wrongly resolved
  conflicts which resulted into duplicated code in space_image.py
  and some build configuration files.
- Store all color space related data (such as display device, view
  transform and so) as strings, so it could easily be ported to new
  OCIO configuration files and it'll be much more portable between
  different configurations.

  This required adding some look-ups to RNA associated with such
  settings, but it's indeed the only way to do this. If it'll be
  figured out such look-ups causes performance issues it's possible
  to optimize this further using hash. So far it's only few elements
  in list to be looked up.
- Added support of display device transformation from OCIO
  configuration files. Display device is setting per-window and
  different windows could have different display devices, so it's
  possible to have one blender window opened on sRGB monitor and
  another one on xyz projector.

  Display device is ignored when using ACES ODT Tonecurve view
  transform due to it's not an OCIO transformation. Probably it'll
  be possible to get rid of this tone curve soon (if it'll be
  proved useless or it'll be implemented as a part of OCIO LUT).
- Movie Cache now supports deleter functions for user keys, so
  such keys could have some allocated data which would be removed
  as soon as element in cache is being removed.
- Movie Cache now support callbacks to check whether current
  cache element could be removed from a cache due to it wouldn't
  be accessed anymore.
- Re-written cache stuff for display buffers of ImBuf. Now it's
  using Movie Cache which is global for all ImBufs.

  Probably it's not implemented in fastest way, would be investigated
  further and probably changed it performance wouldn't be good enough.

30 files changed:
release/scripts/startup/bl_ui/space_image.py
release/scripts/startup/bl_ui/space_info.py
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/seqcache.c
source/blender/blenloader/intern/readfile.c
source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_intern.h
source/blender/editors/space_image/space_image.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/IMB_colormanagement.h
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/IMB_moviecache.h
source/blender/imbuf/SConscript
source/blender/imbuf/intern/IMB_colormanagement_intern.h [new file with mode: 0644]
source/blender/imbuf/intern/IMB_filter.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/colormanagement.c
source/blender/imbuf/intern/divers.c
source/blender/imbuf/intern/filter.c
source/blender/imbuf/intern/moviecache.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_wm.c
source/blender/windowmanager/CMakeLists.txt
source/blender/windowmanager/SConscript
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_window.c

index 6cafaab1ce11211994aa07a809623047b680f586..9fb0d0b4afdf81e83323abdc04444ad18bb54336 100644 (file)
@@ -107,15 +107,6 @@ class IMAGE_MT_select(Menu):
         layout.operator("uv.select_linked")
 
 
-class IMAGE_PT_view_transform(Panel):
-    bl_label = "View Transform"
-
-    def draw(self, context):
-        layout = self.layout
-
-        sima = context.space_data
-
-        layout.prop(sima, "view_transform")
 class IMAGE_MT_image(Menu):
     bl_label = "Image"
 
@@ -436,17 +427,19 @@ class IMAGE_HT_header(Header):
             layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
 
 
-class IMAGE_PT_view_transform(Panel):
+class IMAGE_PT_display_properties(Panel):
     bl_space_type = 'IMAGE_EDITOR'
     bl_region_type = 'UI'
-    bl_label = "View Transform"
+    bl_label = "Display Properties"
 
     def draw(self, context):
         layout = self.layout
 
         sima = context.space_data
+        window = context.window
 
-        layout.prop(sima, "view_transform", text="")
+        layout.prop(window, "display_device", text="Display")
+        layout.prop(sima, "view_transform", text="View")
 
 
 class IMAGE_PT_image_properties(Panel):
index 8ddb2df352a7ce4a5af8ea6c59c852ac44aa7dd8..13ea0a07533217cdd29ab6545c66b4269702490e 100644 (file)
@@ -356,6 +356,8 @@ class INFO_MT_window(Menu):
     def draw(self, context):
         import sys
 
+        window = context.window
+
         layout = self.layout
 
         layout.operator("wm.window_duplicate")
@@ -364,6 +366,9 @@ class INFO_MT_window(Menu):
             layout.separator()
             layout.operator("wm.console_toggle", icon='CONSOLE')
 
+        layout.separator()
+        layout.prop_menu_enum(window, "display_device", text="Display")
+
 
 class INFO_MT_help(Menu):
     bl_label = "Help"
index 54e93f583074ea602f23a93362ebfa0cb6085f3b..55b6d7408c104b2e5451b824f3b8647526bb1e53 100644 (file)
@@ -407,8 +407,8 @@ static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
        if (!clip->cache) {
                clip->cache = MEM_callocN(sizeof(MovieClipCache), "movieClipCache");
 
-               clip->cache->moviecache = IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), moviecache_hashhash,
-                                                               moviecache_hashcmp, moviecache_keydata);
+               clip->cache->moviecache = IMB_moviecache_create(sizeof(MovieClipImBufCacheKey), NULL, moviecache_hashhash,
+                                                               moviecache_hashcmp, moviecache_keydata, NULL);
        }
 
        key.framenr = user->framenr;
index 582034ae6239e70e177efe75870de9f6c487b4c5..6dca3e69f2a827880969c9fd1307c66a6554e982 100644 (file)
@@ -98,8 +98,8 @@ void seq_stripelem_cache_cleanup(void)
 {
        if (moviecache) {
                IMB_moviecache_free(moviecache);
-               moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash,
-                                                  seqcache_hashcmp, NULL);
+               moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), NULL, seqcache_hashhash,
+                                                  seqcache_hashcmp, NULL, NULL);
        }
 }
 
@@ -133,8 +133,8 @@ void seq_stripelem_cache_put(
        }
 
        if (!moviecache) {
-               moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), seqcache_hashhash,
-                                                  seqcache_hashcmp, NULL);
+               moviecache = IMB_moviecache_create(sizeof(SeqCacheKey), NULL, seqcache_hashhash,
+                                                  seqcache_hashcmp, NULL, NULL);
        }
 
        key.seq = seq;
index 47dab0dcc6caa37fc2141a3ba6474e581e976bd9..f323fa721f43609b2548606a9e7b3405ebcd6e23 100644 (file)
 #include "BKE_sound.h"
 
 #include "IMB_imbuf.h"  // for proxy / timecode versioning stuff
+#include "IMB_colormanagement.h"
 
 #include "NOD_socket.h"
 
@@ -8007,7 +8008,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
        fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
        
        link_global(fd, bfd);   /* as last */
-       
+
+       /* OCIO_TODO: is there nicer place for this? */
+       IMB_colormanagement_check_file_config(bfd->main);
+
        return bfd;
 }
 
index 141e8d0eeff871ec5b37521279439b7607ee0786..26cad7d00c1f05cf84fe5bb091b206cfbc0cc95c 100644 (file)
@@ -35,6 +35,7 @@ extern "C" {
        #include "MEM_guardedalloc.h"
        #include "IMB_imbuf.h"
        #include "IMB_imbuf_types.h"
+       #include "IMB_colormanagement.h"
 }
 
 
@@ -72,7 +73,10 @@ void ViewerBaseOperation::initImage()
                anImage->ok = IMA_OK_LOADED;
        }
 
-       imb_freerectviewImBuf_all(ibuf);
+       /* viewer might have been change size, invalidate cached
+        * display buffers so they'll be used with a proper size
+        */
+       IMB_display_buffer_invalidate(ibuf);
 
        /* now we combine the input with ibuf */
        this->m_outputBuffer = ibuf->rect_float;
@@ -88,7 +92,7 @@ void ViewerBaseOperation:: updateImage(rcti *rect)
 void ViewerBaseOperation::deinitExecution()
 {
        ImBuf *ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, &this->m_lock);
-       imb_freerectviewImBuf_all(ibuf);
+       IMB_display_buffer_invalidate(ibuf);
        BKE_image_release_ibuf(this->m_image, this->m_lock);
 
        this->m_outputBuffer = NULL;
index 0973155a28a0b6b4badd3b0e4f2b6e871937fbc3..552da1bb2f91de79a8b981c5df3fd21103cea5f6 100644 (file)
@@ -50,6 +50,7 @@
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
 
 #include "BKE_context.h"
 #include "BKE_global.h"
@@ -69,6 +70,8 @@
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
+#include "WM_api.h"
+#include "WM_types.h"
 
 #include "RE_pipeline.h"
 
@@ -76,7 +79,7 @@
 
 #define HEADER_HEIGHT 18
 
-static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage, int view_transform)
+static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage)
 {
        /* detect if we need to redo the curve map.
         * ibuf->rect is zero for compositor and render results after change 
@@ -85,9 +88,7 @@ static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage,
         * NOTE: if float buffer changes, we have to manually remove the rect
         */
 
-       unsigned int *rect = imb_getrectviewImBuf(ibuf, view_transform);
-
-       if (ibuf->rect_float && (rect == NULL || (ibuf->userflags & IB_RECT_INVALID)) ) {
+       if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID)) ) {
                if (color_manage) {
                        if (ima && ima->source == IMA_SRC_VIEWER)
                                ibuf->profile = IB_PROFILE_LINEAR_RGB;
@@ -95,7 +96,7 @@ static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage,
                else
                        ibuf->profile = IB_PROFILE_NONE;
 
-               IMB_rect_from_float_with_view_transform(ibuf, view_transform);
+               IMB_rect_from_float(ibuf);
        }
 }
 
@@ -419,7 +420,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
        MEM_freeN(rectf);
 }
 
-static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
+static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
 {
        int x, y;
        int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
@@ -432,10 +433,8 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
 
        /* this part is generic image display */
        if (sima->flag & SI_SHOW_ALPHA) {
-               unsigned int *rect = imb_getrectviewImBuf(ibuf, sima->view_transform);
-
-               if (rect)
-                       sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, rect);
+               if (ibuf->rect)
+                       sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect);
                else if (ibuf->rect_float && ibuf->channels == 4)
                        sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float);
        }
@@ -448,7 +447,8 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
                        sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
        }
        else {
-               unsigned int *rect;
+               unsigned char *display_buffer;
+               void *cache_handle;
 
                if (sima->flag & SI_USE_ALPHA) {
                        fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
@@ -459,17 +459,19 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
 
                /* we don't draw floats buffers directly but
                 * convert them, and optionally apply curves */
-               image_verify_buffer_float(ima, ibuf, color_manage, sima->view_transform);
+               image_verify_buffer_float(ima, ibuf, color_manage);
 
-               rect = imb_getrectviewImBuf(ibuf, sima->view_transform);
+               display_buffer = IMB_display_buffer_acquire(ibuf, sima->view_transform, win->display_device, &cache_handle);
 
-               if (rect)
-                       glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+               if (display_buffer)
+                       glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
 #if 0
                else
                        glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
 #endif
-               
+
+               IMB_display_buffer_release(cache_handle);
+
                if (sima->flag & SI_USE_ALPHA)
                        glDisable(GL_BLEND);
        }
@@ -478,15 +480,14 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
        glPixelZoom(1.0f, 1.0f);
 }
 
-static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy, int view_transform)
+static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy)
 {
        unsigned int *rt, *rp, *rectmain;
        short y, heigth, len;
-       unsigned int *rect = imb_getrectviewImBuf(ibuf, view_transform);
 
        /* the right offset in rectot */
 
-       rt = rect + (starty * ibuf->x + startx);
+       rt = ibuf->rect + (starty * ibuf->x + startx);
 
        len = (endx - startx);
        heigth = (endy - starty);
@@ -517,14 +518,14 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
                sima->curtile = ima->xrep * ima->yrep - 1;
        
        /* create char buffer from float if needed */
-       image_verify_buffer_float(ima, ibuf, color_manage, sima->view_transform);
+       image_verify_buffer_float(ima, ibuf, color_manage);
 
        /* retrieve part of image buffer */
        dx = ibuf->x / ima->xrep;
        dy = ibuf->y / ima->yrep;
        sx = (sima->curtile % ima->xrep) * dx;
        sy = (sima->curtile / ima->xrep) * dy;
-       rect = get_part_from_ibuf(ibuf, sx, sy, sx + dx, sy + dy, sima->view_transform);
+       rect = get_part_from_ibuf(ibuf, sx, sy, sx + dx, sy + dy);
        
        /* draw repeated */
        for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
@@ -540,7 +541,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
        MEM_freeN(rect);
 }
 
-static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_repeated(wmWindow *win, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
 {
        const double time_current = PIL_check_seconds_timer();
 
@@ -557,7 +558,7 @@ static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *sce
                        if (ima && (ima->tpageflag & IMA_TILES))
                                draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy);
                        else
-                               draw_image_buffer(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy);
+                               draw_image_buffer(win, sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy);
 
                        /* only draw until running out of time */
                        if ((PIL_check_seconds_timer() - time_current) > 0.25)
@@ -646,19 +647,16 @@ static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *heigh
        ImBuf *ibuf;
        unsigned int size, alpha;
        unsigned char *rect, *cp;
-       unsigned int *rect_view;
 
        if (!brush || !brush->clone.image)
                return NULL;
        
        ibuf = BKE_image_get_ibuf(brush->clone.image, NULL);
-       /* XXX: which transform to use here? */
-       rect_view = imb_getrectviewImBuf(ibuf, IMB_VIEW_TRANSFORM_NONE);
 
-       if (!ibuf || !rect_view)
+       if (!ibuf || !ibuf->rect)
                return NULL;
 
-       rect = MEM_dupallocN(rect_view);
+       rect = MEM_dupallocN(ibuf->rect);
        if (!rect)
                return NULL;
 
@@ -709,8 +707,11 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo
 
 /* draw main image area */
 
-void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
+void draw_image_main(const bContext *C, ARegion *ar)
 {
+       SpaceImage *sima = CTX_wm_space_image(C);
+       Scene *scene = CTX_data_scene(C);
+       wmWindow *win = CTX_wm_window(C);
        Image *ima;
        ImBuf *ibuf;
        float zoomx, zoomy;
@@ -749,11 +750,11 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
        if (ibuf == NULL)
                ED_region_grid_draw(ar, zoomx, zoomy);
        else if (sima->flag & SI_DRAW_TILE)
-               draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy);
+               draw_image_buffer_repeated(win, sima, ar, scene, ima, ibuf, zoomx, zoomy);
        else if (ima && (ima->tpageflag & IMA_TILES))
                draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
        else
-               draw_image_buffer(sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+               draw_image_buffer(win, sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy);
 
        /* paint helpers */
        if (sima->flag & SI_DRAWTOOL)
index 0d3a7614f1065a310c58efd499cea8a186d288ac..f86e59c41a81cfbe67aaa6312011bab09ac1a086 100644 (file)
@@ -52,7 +52,7 @@ struct ARegion *image_has_scope_region(struct ScrArea *sa);
 extern const char *image_context_dir[]; /* doc access */
 
 /* image_draw.c */
-void draw_image_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene);
+void draw_image_main(const struct bContext *C, struct ARegion *ar);
 void draw_image_grease_pencil(struct bContext *C, short onlyv2d);
 void draw_image_sample_line(struct SpaceImage *sima);
 
index 59e47363a228af8015f6b53f655ca8681bea34da..97fee2238a02d0aa5c75502af26e37817b0926f6 100644 (file)
@@ -387,6 +387,12 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
        simage->zoom = 1;
        simage->lock = 1;
 
+       /* OCIO_TODO: use default view transform here when OCIO is completely integrated
+       *             and proper versioning stuff is added.
+       *             for now use NONE to be compatible with all current files
+       */
+       BLI_strncpy(simage->view_transform, "NONE", sizeof(simage->view_transform));
+
        simage->iuser.ok = 1;
        simage->iuser.fie_ima = 2;
        simage->iuser.frames = 100;
@@ -449,6 +455,7 @@ static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
 
 static SpaceLink *image_duplicate(SpaceLink *sl)
 {
+       SpaceImage *simage = (SpaceImage *) sl;
        SpaceImage *simagen = MEM_dupallocN(sl);
        
        /* clear or remove stuff from old */
@@ -457,6 +464,8 @@ static SpaceLink *image_duplicate(SpaceLink *sl)
 
        scopes_new(&simagen->scopes);
 
+       BLI_strncpy(simagen->view_transform, simage->view_transform, sizeof(simage->view_transform));
+
        return (SpaceLink *)simagen;
 }
 
@@ -817,7 +826,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
        image_main_area_set_view2d(sima, ar);
        
        /* we draw image in pixelspace */
-       draw_image_main(sima, ar, scene);
+       draw_image_main(C, ar);
 
        /* and uvs in 0.0-1.0 space */
        UI_view2d_view_ortho(v2d);
index 3618ce6b66318ea7248648411b7268e609280734..9c707a459f2c97985f42188f01e6480a01429a62 100644 (file)
@@ -30,6 +30,7 @@ set(INC
        ../blenlib
        ../blenloader
        ../makesdna
+       ../makesrna
        ../../../intern/guardedalloc
        ../../../intern/memutil
 )
@@ -45,6 +46,7 @@ set(SRC
        intern/anim_movie.c
        intern/bmp.c
        intern/cache.c
+       intern/colormanagement.c
        intern/divers.c
        intern/filetype.c
        intern/filter.c
@@ -67,6 +69,7 @@ set(SRC
        intern/util.c
        intern/writeimage.c
 
+       IMB_colormanagement.h
        IMB_imbuf.h
        IMB_imbuf_types.h
        IMB_moviecache.h
@@ -182,17 +185,6 @@ endif()
 
 if(WITH_OPENCOLORIO)
        list(APPEND SRC
-               intern/colormanagement.c
-       )
-       list(APPEND INC
-               ../../../intern/opencolorio
-       )
-       add_definitions(-DWITH_OCIO)
-endif()
-
-if(WITH_OPENCOLORIO)
-       list(APPEND SRC
-               intern/colormanagement.c
        )
        list(APPEND INC
                ../../../intern/opencolorio
index 1fab281ea7b8f9ec5a7312ef93ed224bdbd12174..e8d3e56bbff99d395feaca0d65c91e3483931697 100644 (file)
 
 #define BCM_CONFIG_FILE "config.ocio"
 
+struct EnumPropertyItem;
+struct ImBuf;
+struct Main;
+
+/* ** Initialization / De-initialization ** */
+
 void IMB_colormanagement_init(void);
 void IMB_colormanagement_exit(void);
 
+/* ** Public display buffers interfaces ** */
+
+unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const char *view_transform, const char *display,
+                                          void **cache_handle);
+void IMB_display_buffer_release(void *cache_handle);
+
+void IMB_display_buffer_invalidate(struct ImBuf *ibuf);
+
+void IMB_colormanagement_check_file_config(struct Main *bmain);
+
+/* ** Display funcrions ** */
+int IMB_colormanagement_display_get_named_index(const char *name);
+const char *IMB_colormanagement_display_get_indexed_name(int index);
+
+/* ** View funcrions ** */
+int IMB_colormanagement_view_get_named_index(const char *name);
+const char *IMB_colormanagement_view_get_indexed_name(int index);
+
+/* ** RNA helper functions ** */
+void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem);
+void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name);
+
 #endif // IMB_COLORMANAGEMENT_H
index 237fe0d0d0bf0cd46d9fd5113f114a7e1ca526f3..2e02b14723e5510fbed79dce9ab05c0974f6a843 100644 (file)
@@ -364,18 +364,8 @@ int imb_get_anim_type(const char *name);
 void IMB_de_interlace(struct ImBuf *ibuf);
 void IMB_interlace(struct ImBuf *ibuf);
 
-/* currently should match eSpaceImage_ViewTransform */
-typedef enum IMB_ViewTransform {
-       IMB_VIEW_TRANSFORM_NONE = 0,
-       IMB_VIEW_TRANSFORM_ACES_ODT_TONECURVE = 1,
-       IMB_VIEW_TRANSFORM_OCIO_RAW = 2,
-       IMB_VIEW_TRANSFORM_OCIO_RRT = 3,
-       IMB_VIEW_TRANSFORM_OCIO_LOG = 4,
-} IMB_ViewTransform;
-
 /* create char buffer, color corrected if necessary, for ImBufs that lack one */ 
 void IMB_rect_from_float(struct ImBuf *ibuf);
-void IMB_rect_from_float_with_view_transform(struct ImBuf *ibuf, int view_transform);
 /* Create char buffer for part of the image, color corrected if necessary,
  * Changed part will be stored in buffer. This is expected to be used for texture painting updates */
 void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h);
@@ -402,6 +392,15 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect
        int width, int height, int stride_to, int stride_from);
 void IMB_buffer_float_clamp(float *buf, int width, int height);
 
+/* converting pixel buffers using tobecurve */
+
+typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]);
+
+void IMB_buffer_byte_from_float_tonecurve(unsigned char *rect_to, const float *rect_from,
+                                          int channels_from, float dither, int profile_to, int profile_from, int predivide,
+                                          int width, int height, int stride_to, int stride_from,
+                                          imb_tonecurveCb tonecurve_func);
+
 /**
  * Change the ordering of the color bytes pointed to by rect from
  * rgba to abgr. size * 4 color bytes are reordered.
@@ -508,10 +507,4 @@ void imb_freemipmapImBuf(struct ImBuf *ibuf);
 short imb_addtilesImBuf(struct ImBuf *ibuf);
 void imb_freetilesImBuf(struct ImBuf *ibuf);
 
-short imb_addrectviewImBuf(struct ImBuf *ibuf, int view_transform);
-void imb_freerectviewImBuf(struct ImBuf *ibuf, int view_transform);
-void imb_freerectviewImBuf_all(struct ImBuf *ibuf);
-
-unsigned int *imb_getrectviewImBuf(struct ImBuf *ibuf, int view_transform);
-
 #endif
index 013e2cc892eb95decb821dd03b338993734f0dab..aa95bf5f2ddfa715b6779082d5501a55742d5c92 100644 (file)
@@ -76,8 +76,6 @@ typedef struct ImBuf {
 
        /* pixels */
        unsigned int *rect;             /* pixel values stored here */
-       unsigned int *rect_view[5];     /* cached view rects which were converted from float buffer */
-                                       /* using different view transforms */
        float *rect_float;              /* floating point Rect equivalent
                                 * Linear RGB color space - may need gamma correction to
                                 * sRGB when generating 8bit representations */
@@ -121,6 +119,12 @@ typedef struct ImBuf {
        unsigned char *encodedbuffer;     /* Compressed image only used with png currently */
        unsigned int   encodedsize;       /* Size of data written to encodedbuffer */
        unsigned int   encodedbuffersize; /* Size of encodedbuffer */
+
+       /* color management */
+       int colormanage_refcounter;
+       unsigned int colormanage_flags;
+       unsigned int display_buffer_flags[16];  /* array of per-display display buffers dirty flags */
+                                               /* currently supports 16 display spaces and 32 view-transform */
 } ImBuf;
 
 /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */
@@ -222,4 +226,7 @@ extern const char *imb_ext_image_qt[];
 extern const char *imb_ext_movie[];
 extern const char *imb_ext_audio[];
 
+/* colormanage flags */
+#define IMB_COLORMANAGED               (1 << 0)
+
 #endif
index f6927d4f31d6942aa99fef20d9fcea1df3abdf78..663d662785dcd0fe43c536b4cf5fe84a0795422b 100644 (file)
@@ -43,11 +43,16 @@ struct ImBuf;
 struct MovieCache;
 
 typedef void (*MovieCacheGetKeyDataFP) (void *userkey, int *framenr, int *proxy, int *render_flags);
+typedef void (*MoviKeyDeleterFP) (void *userkey);
+typedef int (*MovieCacheCheckKeyUnusedFP) (void *userkey);
 
 void IMB_moviecache_init(void);
 void IMB_moviecache_destruct(void);
 
-struct MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp, MovieCacheGetKeyDataFP getdatafp);
+struct MovieCache *IMB_moviecache_create(int keysize, MoviKeyDeleterFP keydeleterfp,
+                                         GHashHashFP hashfp, GHashCmpFP cmpfp,
+                                         MovieCacheGetKeyDataFP getdatafp,
+                                         MovieCacheCheckKeyUnusedFP checkkeyunusedfp);
 void IMB_moviecache_put(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
 struct ImBuf* IMB_moviecache_get(struct MovieCache *cache, void *userkey);
 void IMB_moviecache_free(struct MovieCache *cache);
index 3e812aecb69082af827ba328d92ab79d0a23e5fb..61cc5684356c33add3347dcaa9ab748499b49104 100644 (file)
@@ -4,7 +4,7 @@ Import ('env')
 
 sources = env.Glob('intern/*.c')
 
-incs = '. ../makesdna #/intern/guardedalloc #/intern/memutil ../blenlib'
+incs = '. ../makesdna ../makesrna #/intern/guardedalloc #/intern/memutil ../blenlib'
 incs += ' ../avi ../blenkernel ../blenloader'
 incs += ' #/intern/ffmpeg'
 
@@ -61,7 +61,5 @@ if env['WITH_BF_QUICKTIME']:
 if env['WITH_BF_OCIO']:
     defs.append('WITH_OCIO')
     incs += ' #intern/opencolorio'
-else:
-    sources.remove(os.path.join('intern', 'colormanagement.c'))
 
 env.BlenderLib ( libname = 'bf_imbuf', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [185,115] )
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
new file mode 100644 (file)
index 0000000..5030aca
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Xavier Thomas,
+ *                 Lukas Toenne,
+ *                 Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef IMB_COLORMANAGEMENT_INTERN_H
+#define IMB_COLORMANAGEMENT_INTERN_H
+
+#include "DNA_listBase.h"
+
+#define BCM_CONFIG_FILE "config.ocio"
+
+typedef struct ColorSpace {
+       struct ColorSpace *next, *prev;
+       int index;
+       char name[64];
+} ColorSpace;
+
+typedef struct ColorManagedDisplay {
+       struct ColorManagedDisplay *next, *prev;
+       int index;
+       char name[64];
+       ListBase views;
+} ColorManagedDisplay;
+
+typedef struct ColorManagedView {
+       struct ColorManagedView *next, *prev;
+       int index;
+       char name[64];
+} ColorManagedView;
+
+struct ColorManagedDisplay *colormanage_display_get_default(void);
+struct ColorManagedDisplay *colormanage_display_add(const char *name);
+struct ColorManagedDisplay *colormanage_display_get_named(const char *name);
+struct ColorManagedDisplay *colormanage_display_get_indexed(int index);
+
+struct ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display);
+struct ColorManagedView *colormanage_view_add(const char *name);
+struct ColorManagedView *colormanage_view_get_indexed(int index);
+struct ColorManagedView *colormanage_view_get_named(const char *name);
+
+#endif // IMB_COLORMANAGEMENT_INTERN_H
index c3857c1f537aaff38914c8c13158d398cc4b6ba4..20e1e1207053c9d8a5ca3ec75624a56d53968c57 100644 (file)
@@ -44,8 +44,7 @@ void IMB_premultiply_rect_float(float *rect_float, char planes, int w, int h);
 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1);
 
 /* tonecurves corrections */
-void IMB_ratio_preserving_odt_tonecurve_v3(const float rgbIn[3], float rgbOut[3]);
-void IMB_ratio_preserving_odt_tonecurve_v4(const float rgbIn[4], float rgbOut[4]);
+void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3]);
 
 #endif
 
index 8f269c9999469767e4f50e0545e4b4ab181a8314..0ecd5cf33199cf42889d7cbbf20f5f5694e33ed5 100644 (file)
@@ -41,6 +41,7 @@
 #include "IMB_allocimbuf.h"
 #include "IMB_filetype.h"
 #include "IMB_metadata.h"
+#include "IMB_colormanagement.h"
 
 #include "imbuf.h"
 
@@ -156,7 +157,6 @@ void IMB_freeImBuf(ImBuf *ibuf)
                }
                else {
                        imb_freerectImBuf(ibuf);
-                       imb_freerectviewImBuf_all(ibuf);
                        imb_freerectfloatImBuf(ibuf);
                        imb_freetilesImBuf(ibuf);
                        IMB_freezbufImBuf(ibuf);
@@ -440,10 +440,11 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
        // for now don't duplicate metadata
        tbuf.metadata = NULL;
 
-       memset(tbuf.rect_view, 0, sizeof(tbuf.rect_view));
-
        *ibuf2 = tbuf;
-       
+
+       IMB_display_buffer_invalidate(ibuf2);
+       ibuf2->colormanage_flags &= ~ IMB_COLORMANAGED;
+
        return(ibuf2);
 }
 
@@ -474,63 +475,3 @@ static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
        return &c;
 }
 #endif
-
-/* question; why also add zbuf? */
-short imb_addrectviewImBuf(ImBuf *ibuf, int view_transform)
-{
-       int size;
-
-       if (view_transform == IMB_VIEW_TRANSFORM_NONE)
-               return imb_addrectImBuf(ibuf);
-
-       if (ibuf == NULL) return FALSE;
-
-       /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
-       if (ibuf->rect_view[view_transform])
-               MEM_freeN(ibuf->rect_view[view_transform]);
-       ibuf->rect_view[view_transform] = NULL;
-
-       size = ibuf->x * ibuf->y;
-       size = size * sizeof(unsigned int);
-
-       if ((ibuf->rect_view[view_transform] = MEM_mapallocN(size, "imb_addrectImBuf"))) {
-               if (ibuf->planes > 32) return (addzbufImBuf(ibuf));
-               else return TRUE;
-       }
-
-       return FALSE;
-}
-
-/* any free rect frees mipmaps to be sure, creation is in render on first request */
-void imb_freerectviewImBuf(ImBuf *ibuf, int view_transform)
-{
-       if (view_transform == IMB_VIEW_TRANSFORM_NONE) {
-               imb_freerectImBuf(ibuf);
-
-               return;
-       }
-
-       if (ibuf == NULL) return;
-
-       if (ibuf->rect_view[view_transform])
-               MEM_freeN(ibuf->rect_view[view_transform]);
-
-       ibuf->rect_view[view_transform] = NULL;
-}
-
-void imb_freerectviewImBuf_all(ImBuf *ibuf)
-{
-       imb_freerectviewImBuf(ibuf, IMB_VIEW_TRANSFORM_ACES_ODT_TONECURVE);
-       imb_freerectviewImBuf(ibuf, IMB_VIEW_TRANSFORM_OCIO_RAW);
-       imb_freerectviewImBuf(ibuf, IMB_VIEW_TRANSFORM_OCIO_RRT);
-       imb_freerectviewImBuf(ibuf, IMB_VIEW_TRANSFORM_OCIO_LOG);
-}
-
-unsigned int *imb_getrectviewImBuf(ImBuf *ibuf, int view_transform)
-{
-       if (view_transform == IMB_VIEW_TRANSFORM_NONE) {
-               return ibuf->rect;
-       }
-
-       return ibuf->rect_view[view_transform];
-}
index a7a949f23d7389374eeb181c914e4642c5eb85c3..a9acd92e5ee682f163a9c6d223a05bdb780fbaac 100644 (file)
  */
 
 #include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
 
 #include <string.h>
 #include <math.h>
 
+#include "DNA_windowmanager_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+
+#include "IMB_filter.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_moviecache.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_path_util.h"
+#include "BLI_string.h"
 
 #include "BKE_utildefines.h"
+#include "BKE_main.h"
+
+#include "RNA_define.h"
+
+#ifdef WITH_OCIO
+#  include <ocio_capi.h>
+#endif
+
+/*********************** Global declarations *************************/
+
+/* ** list of all supported color spaces, displays and views */
+#ifdef WITH_OCIO
+static ListBase global_colorspaces = {NULL};
+#endif
+
+static ListBase global_displays = {NULL};
+static ListBase global_views = {NULL};
+
+/*********************** Color managed cache *************************/
+
+/* Currently it's original ImBuf pointer is used to distinguish which
+ * datablock, frame number, possible postprocessing display buffer was
+ * created for.
+ *
+ * This makes it's possible to easy define key for color managed cache
+ * which would work for Images, Movie Clips, Sequencer Strips and so.
+ *
+ * This also allows to easily control memory usage -- all color managed
+ * buffers are concentrated in single cache and it's really easy to
+ * control maximal memory usage for all color management related stuff
+ * (currently supports only maximal memory usage, but it could be
+ * improved further to support removing buffers when they are not needed
+ * anymore but memory usage didn't exceed it's limit).
+ *
+ * This ImBuf is being referenced by cache key, so it could accessed
+ * anytime on runtime while cache element is valid. This is needed to
+ * support removing display buffers from cache when ImBuf they were
+ * created for is being freed.
+ *
+ * Technically it works in the following way:
+ * - ImBuf is being referenced first time when display buffer is
+ *   creating for it and being put into the cache
+ * - On any further display buffer created for this ImBuf user
+ *   reference counter is not being incremented
+ * - There's count of color management users in ImBuf which is
+ *   being incremented every time display buffer is creating for
+ *   giver ImBuf.
+ * - Hence, we always know how many display buffers is created
+ *   for the ImBuf and if there's any display buffers created
+ *   this ImBuf would be referenced by color management stuff and
+ *   actual data for it wouldn't be freed even when this ImBuf is
+ *   being freed by user, who created it.
+ * - When all external users finished working with this ImBuf it's
+ *   reference counter would be 0.
+ * - On every new display buffer adding to the cache review of
+ *   the cache happens and all cached display buffers who's ImBuf's
+ *   user counter is zero are being removed from the cache.
+ * - On every display buffer removed from the cache ImBuf's color
+ *   management user counter is being decremented. As soon as it's
+ *   becoming zero, original ImBuf is being freed completely.
+ */
+
+typedef struct ColormanageCacheKey {
+       ImBuf *ibuf;         /* image buffer for which display buffer was created */
+       int view_transform;  /* view transformation used for display buffer */
+       int display;         /* display device name */
+} ColormanageCacheKey;
+
+static struct MovieCache *colormanage_cache = NULL;
+
+static unsigned int colormanage_hashhash(const void *key_v)
+{
+       ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+
+       unsigned int rval = *(unsigned int *) key->ibuf;
+
+       return rval;
+}
+
+static int colormanage_hashcmp(const void *av, const void *bv)
+{
+       const ColormanageCacheKey *a = (ColormanageCacheKey *) av;
+       const ColormanageCacheKey *b = (ColormanageCacheKey *) bv;
+
+       if (a->ibuf < b->ibuf)
+               return -1;
+       else if (a->ibuf > b->ibuf)
+               return 1;
+
+       if (a->view_transform < b->view_transform)
+               return -1;
+       else if (a->view_transform > b->view_transform)
+               return 1;
+
+       if (a->display < b->display)
+               return -1;
+       else if (a->display > b->display)
+               return 1;
+
+       return 0;
+}
+
+static int colormanage_checkkeyunused(void *key_v)
+{
+       ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+
+       return key->ibuf->refcounter == 0;
+}
+
+static void colormanage_keydeleter(void *key_v)
+{
+       ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+       ImBuf *cache_ibuf = key->ibuf;
+
+       cache_ibuf->colormanage_refcounter--;
+
+       if (cache_ibuf->colormanage_refcounter == 0) {
+               IMB_freeImBuf(key->ibuf);
+       }
+}
+
+static void colormanage_cache_init(void)
+{
+       colormanage_cache = IMB_moviecache_create(sizeof(ColormanageCacheKey), colormanage_keydeleter,
+                                                 colormanage_hashhash, colormanage_hashcmp,
+                                                 NULL, colormanage_checkkeyunused);
+}
+
+static void colormanage_cache_exit(void)
+{
+       IMB_moviecache_free(colormanage_cache);
+}
+
+#ifdef WITH_OCIO
+static unsigned char *colormanage_cache_get(ImBuf *ibuf, int view_transform, int display, void **cache_handle)
+{
+       ImBuf *cache_ibuf;
+       ColormanageCacheKey key;
+
+       *cache_handle = NULL;
+
+       key.ibuf = ibuf;
+       key.view_transform = view_transform;
+       key.display = display;
+
+       cache_ibuf = IMB_moviecache_get(colormanage_cache, &key);
+
+       if (cache_ibuf) {
+               *cache_handle = cache_ibuf;
+
+               return (unsigned char *) cache_ibuf->rect;
+       }
+
+       return NULL;
+}
+
+static void colormanage_cache_put(ImBuf *ibuf, int view_transform, int display,
+                                  unsigned char *display_buffer, void **cache_handle)
+{
+       ColormanageCacheKey key;
+       ImBuf *cache_ibuf;
+
+       key.ibuf = ibuf;
+       key.view_transform = view_transform;
+       key.display = display;
+
+       cache_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
+       cache_ibuf->rect = (unsigned int *) display_buffer;
+
+       cache_ibuf->mall |= IB_rect;
+       cache_ibuf->flags |= IB_rect;
+
+       *cache_handle = cache_ibuf;
+
+       if ((ibuf->colormanage_flags & IMB_COLORMANAGED) == 0) {
+               ibuf->colormanage_flags |= IMB_COLORMANAGED;
+
+               IMB_refImBuf(ibuf);
+       }
+
+       ibuf->colormanage_refcounter++;
+
+       IMB_moviecache_put(colormanage_cache, &key, cache_ibuf);
+}
+
+static void colormanage_cache_update(ImBuf *ibuf, unsigned char *display_buffer, void *cache_handle)
+{
+       ImBuf *cache_ibuf = cache_handle;
+
+       /* remove old display buffer */
+       MEM_freeN(cache_ibuf->rect);
+
+       /* resolution could have been changed for generated images */
+       cache_ibuf->x = ibuf->x;
+       cache_ibuf->y = ibuf->y;
+
+       /* use new display buffer */
+       cache_ibuf->rect = (unsigned int *) display_buffer;
+}
+#endif
+
+static void colormanage_cache_handle_release(void *cache_handle)
+{
+       ImBuf *cache_ibuf = cache_handle;
+
+       IMB_freeImBuf(cache_ibuf);
+}
 
-#include <ocio_capi.h>
+/*********************** Initialization / De-initialization *************************/
 
-static void colormgmt_load_config(ConstConfigRcPtr* config)
+#ifdef WITH_OCIO
+static void colormanage_load_config(ConstConfigRcPtr* config)
 {
-       OCIO_setCurrentConfig(config);
+       ConstColorSpaceRcPtr *ociocs;
+       int tot_colorspace, tot_display, tot_display_view, index, viewindex, viewindex2;
+       const char *name;
+
+       /* load colorspaces */
+       tot_colorspace = OCIO_configGetNumColorSpaces(config);
+       for (index = 0 ; index < tot_colorspace; index++) {
+               ColorSpace *colorspace;
+
+               name = OCIO_configGetColorSpaceNameByIndex(config, index);
+               ociocs = OCIO_configGetColorSpace(config, name);
+
+               colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace");
+               colorspace->index = index + 1;
+
+               BLI_strncpy(colorspace->name, name, sizeof(colorspace->name));
+
+               BLI_addtail(&global_colorspaces, colorspace);
+
+               OCIO_colorSpaceRelease(ociocs);
+       }
+
+       /* load displays */
+       viewindex2 = 0;
+       tot_display = OCIO_configGetNumDisplays(config);
+
+       for (index = 0 ; index < tot_display; index++) {
+               const char *displayname;
+               ColorManagedDisplay *display;
+
+               displayname = OCIO_configGetDisplay(config, index);
+
+               display = colormanage_display_add(displayname);
+
+               /* load views */
+               tot_display_view = OCIO_configGetNumViews(config, displayname);
+               for (viewindex = 0 ; viewindex < tot_display_view; viewindex++, viewindex2++) {
+                       const char *viewname;
+                       ColorManagedView *view;
+                       LinkData *display_view;
+
+                       viewname = OCIO_configGetView(config, displayname, viewindex);
+
+                       /* first check if view transform with given name was already loaded */
+                       view = colormanage_view_get_named(viewname);
+
+                       if (!view) {
+                               view = colormanage_view_add(viewname);
+                       }
+
+                       display_view = BLI_genericNodeN(view);
+
+                       BLI_addtail(&display->views, display_view);
+               }
+       }
 }
 
-void colormgmt_free_config(void)
+void colormanage_free_config(void)
 {
+       ColorSpace *colorspace;
+       ColorManagedDisplay *display;
+       ColorManagedView *view;
+
+       colorspace = global_colorspaces.first;
+       while (colorspace) {
+               ColorSpace *colorspace_next = colorspace->next;
+
+               MEM_freeN(colorspace);
+               colorspace = colorspace_next;
+       }
+
+       display = global_displays.first;
+       while (display) {
+               ColorManagedDisplay *display_next = display->next;
+               LinkData *display_view = display->views.first;
+
+               while (display_view) {
+                       LinkData *display_view_next = display_view->next;
+
+                       MEM_freeN(display_view);
+                       display_view = display_view_next;
+               }
+
+               MEM_freeN(display);
+               display = display_next;
+       }
+
+       view = global_views.first;
+       while (view) {
+               ColorManagedView *view_next = view->next;
+
+               MEM_freeN(view);
+               view = view_next;
+       }
 }
+#endif
 
 void IMB_colormanagement_init(void)
 {
+#ifdef WITH_OCIO
        const char *ocio_env;
        const char *configdir;
        char configfile[FILE_MAXDIR+FILE_MAXFILE];
@@ -74,13 +384,444 @@ void IMB_colormanagement_init(void)
        }
 
        if (config) {
-               colormgmt_load_config(config);
+               OCIO_setCurrentConfig(config);
+
+               colormanage_load_config(config);
        }
 
        OCIO_configRelease(config);
+
+       /* special views, which does not depend on OCIO  */
+       colormanage_view_add("ACES ODT Tonecurve");
+#endif
+
+       colormanage_cache_init();
 }
 
 void IMB_colormanagement_exit(void)
 {
-       colormgmt_free_config();
+#ifdef WITH_OCIO
+       colormanage_free_config();
+#endif
+
+       colormanage_cache_exit();
+}
+
+/*********************** Public display buffers interfaces *************************/
+
+#ifdef WITH_OCIO
+static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer,
+                                         imb_tonecurveCb tonecurve_func)
+{
+       int predivide = ibuf->flags & IB_cm_predivide;
+
+       IMB_buffer_byte_from_float_tonecurve(display_buffer, ibuf->rect_float,
+                                             ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
+                                             predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x, tonecurve_func);
+}
+
+static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer,
+                                      const char *view_transform, const char *display)
+{
+       ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+       DisplayTransformRcPtr *dt = OCIO_createDisplayTransform();
+       ConstProcessorRcPtr *processor;
+       float *rect_float;
+       int predivide = ibuf->flags & IB_cm_predivide;
+       PackedImageDesc *img;
+
+       rect_float = MEM_dupallocN(ibuf->rect_float);
+       img = OCIO_createPackedImageDesc(rect_float, ibuf->x, ibuf->y, ibuf->channels, sizeof(float),
+                                        ibuf->channels * sizeof(float), ibuf->channels * sizeof(float)*ibuf->x);
+
+       /* OCIO_TODO: get rid of hardcoded input and display spaces */
+       OCIO_displayTransformSetInputColorSpaceName(dt, "aces");
+
+       OCIO_displayTransformSetView(dt, view_transform);
+       OCIO_displayTransformSetDisplay(dt, display);
+
+       processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr*)dt);
+
+       if (processor) {
+               OCIO_processorApply(processor, img);
+
+               /* do conversion */
+               IMB_buffer_byte_from_float(display_buffer, rect_float,
+                                          ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+                                                                  predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+       }
+
+       OCIO_packedImageDescRelease(img);
+       OCIO_displayTransformRelease(dt);
+       OCIO_processorRelease(processor);
+       OCIO_configRelease(config);
+
+       MEM_freeN(rect_float);
+}
+#endif
+
+unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transform, const char *display, void **cache_handle)
+{
+       *cache_handle = NULL;
+
+#ifdef WITH_OCIO
+       if (!ibuf->x || !ibuf->y)
+               return NULL;
+
+       /* OCIO_TODO: support colormanaged byte buffers */
+       if (!strcmp(view_transform, "NONE") || !ibuf->rect_float) {
+               /* currently only view-transformation is allowed, input and display
+                * spaces are hard-coded, so if there's no view transform applying
+                * it's safe to suppose standard byte buffer is used for display
+                */
+
+               if (!ibuf->rect)
+                       IMB_rect_from_float(ibuf);
+
+               return (unsigned char *) ibuf->rect;
+       }
+       else {
+               unsigned char *display_buffer;
+               int buffer_size;
+               int view_transform_index = IMB_colormanagement_view_get_named_index(view_transform);
+               int display_index = IMB_colormanagement_display_get_named_index(display);
+               int view_transform_flag = 1 << (view_transform_index - 1);
+
+               display_buffer = colormanage_cache_get(ibuf, view_transform_index, display_index, cache_handle);
+
+               if (display_buffer) {
+                       /* check whether display buffer isn't marked as dirty */
+                       if (ibuf->display_buffer_flags[display_index - 1] & view_transform_flag)
+                               return display_buffer;
+               }
+
+               /* OCIO_TODO: in case when image is being resized it is possible
+                *            to save buffer allocation here
+                */
+
+               buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
+               display_buffer = MEM_callocN(buffer_size, "imbuf display buffer");
+
+               if (!strcmp(view_transform, "ACES ODT Tonecurve")) {
+                       /* special case for Mango team, this does not actually apply
+                        * any input space -> display space conversion and just applies
+                        * a tonecurve for better linear float -> sRGB byte conversion
+                        */
+                       display_buffer_apply_tonemap(ibuf, display_buffer, IMB_ratio_preserving_odt_tonecurve);
+               }
+               else {
+                       display_buffer_apply_ocio(ibuf, display_buffer, view_transform, display);
+               }
+
+               if (*cache_handle) {
+                       colormanage_cache_update(ibuf, display_buffer, *cache_handle);
+               }
+               else {
+                       colormanage_cache_put(ibuf, view_transform_index, display_index, display_buffer, cache_handle);
+               }
+
+               ibuf->display_buffer_flags[display_index - 1] |= view_transform_flag;
+
+               return display_buffer;
+       }
+#else
+       /* no OCIO support, simply return byte buffer which was
+        * generated from float buffer (if any) using standard
+        * profiles without applying any view / display transformation */
+
+       (void) view_transform;
+       (void) display;
+
+       if (!ibuf->rect) {
+               IMB_rect_from_float(ibuf);
+       }
+
+       return (unsigned char*) ibuf->rect;
+#endif
+}
+
+void IMB_display_buffer_release(void *cache_handle)
+{
+       if (cache_handle) {
+               colormanage_cache_handle_release(cache_handle);
+       }
+}
+
+void IMB_display_buffer_invalidate(ImBuf *ibuf)
+{
+       memset(ibuf->display_buffer_flags, 0, sizeof(ibuf->display_buffer_flags));
+}
+
+void IMB_colormanagement_check_file_config(Main *bmain)
+{
+#ifdef WITH_OCIO
+       wmWindowManager *wm = bmain->wm.first;
+       wmWindow *win;
+       bScreen *sc;
+
+       ColorManagedDisplay *default_display = colormanage_display_get_default();
+       ColorManagedView *default_view = colormanage_view_get_default(default_display);
+
+       for (win = wm->windows.first; win; win = win->next) {
+               if (win->display_device[0] == '\0') {
+                       BLI_strncpy(win->display_device, default_display->name, sizeof(win->display_device));
+               }
+               else {
+                       ColorManagedDisplay *display = colormanage_display_get_named(win->display_device);
+
+                       if (!display) {
+                               printf("Blender color management: Window display \"%s\" not found, setting to default (\"%s\").\n",
+                                      win->display_device, default_display->name);
+
+                               BLI_strncpy(win->display_device, default_display->name, sizeof(win->display_device));
+                       }
+               }
+       }
+
+       for(sc = bmain->screen.first; sc; sc= sc->id.next) {
+               ScrArea *sa;
+
+               for (sa = sc->areabase.first; sa; sa = sa->next) {
+                       SpaceLink *sl;
+                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+
+                               if (sl->spacetype == SPACE_IMAGE) {
+                                       SpaceImage *sima = (SpaceImage *) sl;
+
+                                       if (sima->view_transform[0] == '\0') {
+                                               BLI_strncpy(sima->view_transform, "NONE", sizeof(sima->view_transform));
+                                       }
+                                       else if (!strcmp(sima->view_transform, "NONE")) {
+                                               /* pass */
+                                       }
+                                       else {
+                                               ColorManagedView *view = colormanage_view_get_named(sima->view_transform);
+
+                                               if (!view) {
+                                                       printf("Blender color management: image editor view \"%s\" not found, setting default \"%s\".\n",
+                                                              sima->view_transform, default_view->name);
+
+                                                       BLI_strncpy(sima->view_transform, default_view->name, sizeof(sima->view_transform));
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+#else
+       (void) bmain;
+#endif
+}
+
+/*********************** Display functions *************************/
+
+#ifdef WITH_OCIO
+ColorManagedDisplay *colormanage_display_get_default(void)
+{
+       ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+       const char *display = OCIO_configGetDefaultDisplay(config);
+
+       OCIO_configRelease(config);
+
+       if (display[0] == '\0')
+               return NULL;
+
+       return colormanage_display_get_named(display);
+}
+#endif
+
+ColorManagedDisplay *colormanage_display_add(const char *name)
+{
+       ColorManagedDisplay *display;
+       int index = 0;
+
+       if (global_displays.last) {
+               ColorManagedDisplay *last_display = global_displays.last;
+
+               index = last_display->index;
+       }
+
+       display = MEM_callocN(sizeof(ColorManagedDisplay), "ColorManagedDisplay");
+
+       display->index = index + 1;
+
+       BLI_strncpy(display->name, name, sizeof(display->name));
+
+       BLI_addtail(&global_displays, display);
+
+       return display;
+}
+
+ColorManagedDisplay *colormanage_display_get_named(const char *name)
+{
+       ColorManagedDisplay *display;
+
+       for (display = global_displays.first; display; display = display->next) {
+               if (!strcmp(display->name, name))
+                       return display;
+       }
+
+       return NULL;
+}
+
+ColorManagedDisplay *colormanage_display_get_indexed(int index)
+{
+       /* display indices are 1-based */
+       return BLI_findlink(&global_displays, index - 1);
+}
+
+int IMB_colormanagement_display_get_named_index(const char *name)
+{
+       ColorManagedDisplay *display;
+
+       display = colormanage_display_get_named(name);
+
+       if (display) {
+               return display->index;
+       }
+
+       return 0;
+}
+
+const char *IMB_colormanagement_display_get_indexed_name(int index)
+{
+       ColorManagedDisplay *display;
+
+       display = colormanage_display_get_indexed(index);
+
+       if (display) {
+               return display->name;
+       }
+
+       return NULL;
+}
+
+/*********************** View functions *************************/
+
+#ifdef WITH_OCIO
+ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display)
+{
+       ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+       const char *name = OCIO_configGetDefaultView(config, display->name);
+       OCIO_configRelease(config);
+
+       if (name[0] == '\0')
+               return NULL;
+
+       return colormanage_view_get_named(name);
+}
+#endif
+
+ColorManagedView *colormanage_view_add(const char *name)
+{
+       ColorManagedView *view;
+       int index = 0;
+
+       if (global_views.last) {
+               ColorManagedView *last_view = global_views.last;
+
+               index = last_view->index;
+       }
+
+       view = MEM_callocN(sizeof(ColorManagedView), "ColorManagedView");
+       view->index = index + 1;
+       BLI_strncpy(view->name, name, sizeof(view->name));
+
+       BLI_addtail(&global_views, view);
+
+       return view;
+}
+
+ColorManagedView *colormanage_view_get_named(const char *name)
+{
+       ColorManagedView *view;
+
+       for (view = global_views.first; view; view = view->next) {
+               if (!strcmp(view->name, name))
+                       return view;
+       }
+
+       return NULL;
+}
+
+ColorManagedView *colormanage_view_get_indexed(int index)
+{
+       /* view transform indices are 1-based */
+       return BLI_findlink(&global_views, index - 1);
+}
+
+int IMB_colormanagement_view_get_named_index(const char *name)
+{
+       ColorManagedView *view = colormanage_view_get_named(name);
+
+       if (view) {
+               return view->index;
+       }
+
+       return 0;
+}
+
+const char *IMB_colormanagement_view_get_indexed_name(int index)
+{
+       ColorManagedView *view = colormanage_view_get_indexed(index);
+
+       if (view) {
+               return view->name;
+       }
+
+       return "NONE";
+}
+
+/*********************** RNA helper functions *************************/
+
+void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem)
+{
+       ColorManagedDisplay *display;
+
+       for (display = global_displays.first; display; display = display->next) {
+               EnumPropertyItem item;
+
+               item.value = display->index;
+               item.name = display->name;
+               item.identifier = display->name;
+               item.icon = 0;
+               item.description = "";
+
+               RNA_enum_item_add(items, totitem, &item);
+       }
+}
+
+static void colormanagement_view_item_add(EnumPropertyItem **items, int *totitem, ColorManagedView *view)
+{
+       EnumPropertyItem item;
+
+       item.value = view->index;
+       item.name = view->name;
+       item.identifier = view->name;
+       item.icon = 0;
+       item.description = "";
+
+       RNA_enum_item_add(items, totitem, &item);
+}
+
+void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, const char *display_name)
+{
+       ColorManagedDisplay *display = colormanage_display_get_named(display_name);
+       ColorManagedView *view;
+
+       /* OCIO_TODO: try to get rid of such a hackish stuff */
+       view = colormanage_view_get_named("ACES ODT Tonecurve");
+       if (view) {
+               colormanagement_view_item_add(items, totitem, view);
+       }
+
+       if (display) {
+               LinkData *display_view;
+
+               for (display_view = display->views.first; display_view; display_view = display_view->next) {
+                       view = display_view->data;
+
+                       colormanagement_view_item_add(items, totitem, view);
+               }
+       }
 }
index a169d681adba7a8b1d6c1e401fbaf7baca51b9a3..68ecbb58001dc121622c9c41e83db36bd006ef67 100644 (file)
@@ -192,11 +192,13 @@ MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext
 }
 
 /* float to byte pixels, output 4-channel RGBA */
-void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
-                                int channels_from, float dither, int profile_to, int profile_from, int predivide,
-                                int width, int height, int stride_to, int stride_from)
+void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from,
+                                          int channels_from, float dither, int profile_to, int profile_from, int predivide,
+                                          int width, int height, int stride_to, int stride_from,
+                                          imb_tonecurveCb tonecurve_func)
 {
        float tmp[4];
+       float corrected[4];
        int x, y;
        DitherContext *di;
 
@@ -208,6 +210,9 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
        if (dither)
                di = create_dither_context(width, dither);
 
+       if (!tonecurve_func)
+               tonecurve_func = copy_v3_v3;
+
        for (y = 0; y < height; y++) {
                if (channels_from == 1) {
                        /* single channel input */
@@ -232,7 +237,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                        else if (profile_to == IB_PROFILE_SRGB) {
                                /* convert from linear to sRGB */
                                for (x = 0; x < width; x++, from += 3, to += 4) {
-                                       linearrgb_to_srgb_v3_v3(tmp, from);
+                                       tonecurve_func(corrected, from);
+                                       linearrgb_to_srgb_v3_v3(tmp, corrected);
                                        rgb_float_to_uchar(to, tmp);
                                        to[3] = 255;
                                }
@@ -268,25 +274,37 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
 
                                if (dither && predivide) {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4_predivide(us, from);
+                                               tonecurve_func(corrected, from);
+                                               corrected[3] = from[3];
+
+                                               linearrgb_to_srgb_ushort4_predivide(us, corrected);
                                                ushort_to_byte_dither_v4(to, us, di);
                                        }
                                }
                                else if (dither) {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4(us, from);
+                                               tonecurve_func(corrected, from);
+                                               corrected[3] = from[3];
+
+                                               linearrgb_to_srgb_ushort4(us, corrected);
                                                ushort_to_byte_dither_v4(to, us, di);
                                        }
                                }
                                else if (predivide) {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4_predivide(us, from);
+                                               tonecurve_func(corrected, from);
+                                               corrected[3] = from[3];
+
+                                               linearrgb_to_srgb_ushort4_predivide(us, corrected);
                                                ushort_to_byte_v4(to, us);
                                        }
                                }
                                else {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4(us, from);
+                                               tonecurve_func(corrected, from);
+                                               corrected[3] = from[3];
+
+                                               linearrgb_to_srgb_ushort4(us, corrected);
                                                ushort_to_byte_v4(to, us);
                                        }
                                }
@@ -328,6 +346,15 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                clear_dither_context(di);
 }
 
+void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
+                                int channels_from, float dither, int profile_to, int profile_from, int predivide,
+                                int width, int height, int stride_to, int stride_from)
+{
+       IMB_buffer_byte_from_float_tonecurve(rect_to, rect_from, channels_from, dither, profile_to, profile_from, predivide,
+                                            width, height, stride_to, stride_from, NULL);
+}
+
+
 /* byte to float pixels, input and output 4-channel RGBA  */
 void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
                                 int profile_to, int profile_from, int predivide,
@@ -527,89 +554,6 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
        }
 }
 
-/* float to byte pixels, output 4-channel RGBA */
-void IMB_buffer_srgb_byte_from_linear_float(uchar *rect_to, const float *rect_from,
-                                            int channels_from, float dither, int predivide,
-                                            int width, int height, int stride_to, int stride_from)
-{
-       float tmp[4];
-       int x, y;
-       DitherContext *di;
-       float corrected[4];
-
-       BLI_init_srgb_conversion();
-
-       if (dither)
-               di = create_dither_context(width, dither);
-
-       for (y = 0; y < height; y++) {
-               if (channels_from == 1) {
-                       /* single channel input */
-                       const float *from = rect_from + stride_from * y;
-                       uchar *to = rect_to + stride_to * y * 4;
-
-                       for (x = 0; x < width; x++, from++, to += 4)
-                               to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
-               }
-               else if (channels_from == 3) {
-                       /* RGB input */
-                       const float *from = rect_from + stride_from * y * 3;
-                       uchar *to = rect_to + stride_to * y * 4;
-
-                       /* convert from linear to sRGB */
-                       for (x = 0; x < width; x++, from += 3, to += 4) {
-                               IMB_ratio_preserving_odt_tonecurve_v3(from, corrected);
-                               linearrgb_to_srgb_v3_v3(tmp, corrected);
-                               rgb_float_to_uchar(to, tmp);
-                               to[3] = 255;
-                       }
-               }
-               else if (channels_from == 4) {
-                       /* RGBA input */
-                       const float *from = rect_from + stride_from * y * 4;
-                       uchar *to = rect_to + stride_to * y * 4;
-
-                       /* convert from linear to sRGB */
-                       unsigned short us[4];
-
-                       if (dither && predivide) {
-                               for (x = 0; x < width; x++, from += 4, to += 4) {
-                                       IMB_ratio_preserving_odt_tonecurve_v4(from, corrected);
-                                       linearrgb_to_srgb_ushort4_predivide(us, corrected);
-                                       ushort_to_byte_dither_v4(to, us, di);
-                               }
-                       }
-                       else if (dither) {
-                               for (x = 0; x < width; x++, from += 4, to += 4) {
-                                       IMB_ratio_preserving_odt_tonecurve_v4(from, corrected);
-                                       linearrgb_to_srgb_ushort4(us, corrected);
-                                       ushort_to_byte_dither_v4(to, us, di);
-                               }
-                       }
-                       else if (predivide) {
-                               for (x = 0; x < width; x++, from += 4, to += 4) {
-                                       IMB_ratio_preserving_odt_tonecurve_v4(from, corrected);
-                                       linearrgb_to_srgb_ushort4_predivide(us, corrected);
-                                       ushort_to_byte_v4(to, us);
-                               }
-                       }
-                       else {
-                               for (x = 0; x < width; x++, from += 4, to += 4) {
-                                       IMB_ratio_preserving_odt_tonecurve_v4(from, corrected);
-                                       linearrgb_to_srgb_ushort4(us, corrected);
-                                       ushort_to_byte_v4(to, us);
-                               }
-                       }
-               }
-
-               if (dither)
-                       dither_finish_row(di);
-       }
-
-       if (dither)
-               clear_dither_context(di);
-}
-
 /****************************** ImBuf Conversion *****************************/
 
 void IMB_rect_from_float(ImBuf *ibuf)
@@ -621,10 +565,6 @@ void IMB_rect_from_float(ImBuf *ibuf)
        if (ibuf->rect_float == NULL)
                return;
 
-       if (ibuf->userflags & IB_RECT_INVALID) {
-               imb_freerectviewImBuf_all(ibuf);
-       }
-
        /* create byte rect if it didn't exist yet */
        if (ibuf->rect == NULL)
                imb_addrectImBuf(ibuf);
@@ -650,113 +590,6 @@ void IMB_rect_from_float(ImBuf *ibuf)
        ibuf->userflags &= ~IB_RECT_INVALID;
 }
 
-void IMB_rect_from_float_with_view_transform(ImBuf *ibuf, int view_transform)
-{
-       int predivide = (ibuf->flags & IB_cm_predivide);
-
-       /* verify we have a float buffer */
-       if (ibuf->rect_float == NULL)
-               return;
-
-       if (ibuf->userflags & IB_RECT_INVALID) {
-               imb_freerectviewImBuf_all(ibuf);
-       }
-
-#ifdef WITH_OCIO
-       if (view_transform == IMB_VIEW_TRANSFORM_NONE)
-#else
-       (void)view_transform;
-#endif /* WITH_OCIO */
-       {
-               int profile_from;
-
-               /* create byte rect if it didn't exist yet */
-               if (ibuf->rect == NULL)
-                       imb_addrectImBuf(ibuf);
-
-               /* determine profiles */
-               if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
-                       profile_from = IB_PROFILE_LINEAR_RGB;
-               }
-               else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) {
-                       profile_from = IB_PROFILE_SRGB;
-               }
-               else {
-                       profile_from = IB_PROFILE_SRGB; /* should never happen */
-                       BLI_assert(0);
-               }
-
-               /* do conversion */
-               IMB_buffer_byte_from_float((uchar *)ibuf->rect, ibuf->rect_float,
-                                          ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
-                                          ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-       }
-#ifdef WITH_OCIO
-       else if (view_transform == IMB_VIEW_TRANSFORM_ACES_ODT_TONECURVE) {
-               unsigned int *rect_view;
-
-               /* create byte rect if it didn't exist yet */
-               if (ibuf->rect_view[view_transform] == NULL)
-                       imb_addrectviewImBuf(ibuf, view_transform);
-
-               rect_view = imb_getrectviewImBuf(ibuf, view_transform);
-
-               IMB_buffer_srgb_byte_from_linear_float((uchar *)rect_view, ibuf->rect_float,
-                                                      ibuf->channels, ibuf->dither, predivide,
-                                                      ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-       }
-       else if (ibuf->x && ibuf->y) {
-               ConstConfigRcPtr *config = OCIO_getCurrentConfig();
-               ConstProcessorRcPtr *processor;
-               DisplayTransformRcPtr *dt = OCIO_createDisplayTransform();
-               PackedImageDesc *img;
-               float *rect_float;
-
-               OCIO_displayTransformSetInputColorSpaceName(dt, "aces");
-               OCIO_displayTransformSetDisplay(dt, "sRGB");
-
-               if (view_transform == IMB_VIEW_TRANSFORM_OCIO_RAW)
-                       OCIO_displayTransformSetView(dt, "Raw");
-               else if (view_transform == IMB_VIEW_TRANSFORM_OCIO_RRT)
-                       OCIO_displayTransformSetView(dt, "RRT");
-               else if (view_transform == IMB_VIEW_TRANSFORM_OCIO_LOG)
-                       OCIO_displayTransformSetView(dt, "Log");
-
-               rect_float = MEM_dupallocN(ibuf->rect_float);
-               img = OCIO_createPackedImageDesc(rect_float, ibuf->x, ibuf->y, ibuf->channels, sizeof(float),
-                                                ibuf->channels * sizeof(float), ibuf->channels * sizeof(float)*ibuf->x);
-
-               processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr*)dt);
-               if (processor) {
-                       unsigned int *rect_view;
-
-                       OCIO_processorApply(processor, img);
-
-                       /* create byte rect if it didn't exist yet */
-                       if (ibuf->rect_view[view_transform] == NULL)
-                               imb_addrectviewImBuf(ibuf, view_transform);
-
-                       rect_view = imb_getrectviewImBuf(ibuf, view_transform);
-
-                       /* do conversion */
-                       IMB_buffer_byte_from_float((uchar *)rect_view, rect_float,
-                                                  ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
-                                                  ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-
-               }
-
-               OCIO_packedImageDescRelease(img);
-               OCIO_displayTransformRelease(dt);
-               OCIO_processorRelease(processor);
-               OCIO_configRelease(config);
-
-               MEM_freeN(rect_float);
-       }
-#endif /* WITH_OCIO */
-
-       ibuf->userflags &= ~IB_RECT_INVALID;
-}
-
 /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */
 void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h)
 {
index 3abafaea080a0cdfe1cf79e9efe628e3899b0c46..012c01e6e733970c14a0a9ba789741aa2b541c67 100644 (file)
@@ -755,7 +755,7 @@ static float rdt_shaper_fwd( float x)
     return y;
 }
 
-void IMB_ratio_preserving_odt_tonecurve_v3(const float rgbIn[3], float rgbOut[3])
+void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3])
 {
        //
        // The "ratio preserving tonecurve" is used to avoid hue/chroma shifts.
@@ -783,10 +783,3 @@ void IMB_ratio_preserving_odt_tonecurve_v3(const float rgbIn[3], float rgbOut[3]
                rgbOut[2] = rgbIn[2] * normRGBo / normRGB;
        }
 }
-
-void IMB_ratio_preserving_odt_tonecurve_v4(const float rgbIn[4], float rgbOut[4])
-{
-       IMB_ratio_preserving_odt_tonecurve_v3(rgbIn, rgbOut);
-
-       rgbOut[3] = rgbIn[3];
-}
index 2992e4a0aa7f60684479bba59797649dca8c29e0..281b5df2e88c24894374c9d8544c0b70c42e5a8d 100644 (file)
@@ -48,9 +48,11 @@ static MEM_CacheLimiterC *limitor = NULL;
 
 typedef struct MovieCache {
        GHash *hash;
+       MoviKeyDeleterFP keydeleterfp;
        GHashHashFP hashfp;
        GHashCmpFP cmpfp;
        MovieCacheGetKeyDataFP getdatafp;
+       MovieCacheCheckKeyUnusedFP checkkeyunusedfp;
 
        struct BLI_mempool *keys_pool;
        struct BLI_mempool *items_pool;
@@ -94,6 +96,12 @@ static void moviecache_keyfree(void *val)
 {
        MovieCacheKey *key = (MovieCacheKey *)val;
 
+       if (key->cache_owner->keydeleterfp) {
+               key->cache_owner->keydeleterfp(key->userkey);
+       }
+
+       BLI_mempool_free(key->cache_owner->userkeys_pool, key->userkey);
+
        BLI_mempool_free(key->cache_owner->keys_pool, key);
 }
 
@@ -117,10 +125,16 @@ static void check_unused_keys(MovieCache *cache)
        while (!BLI_ghashIterator_isDone(iter)) {
                MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
                MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
+               int remove = 0;
 
                BLI_ghashIterator_step(iter);
 
-               if (!item->ibuf)
+               remove = !item->ibuf;
+
+               if (!remove && cache->checkkeyunusedfp)
+                       remove = cache->checkkeyunusedfp(key->userkey);
+
+               if (remove)
                        BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree);
        }
 
@@ -198,8 +212,10 @@ void IMB_moviecache_destruct(void)
                delete_MEM_CacheLimiter(limitor);
 }
 
-MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp,
-                                  MovieCacheGetKeyDataFP getdatafp)
+MovieCache *IMB_moviecache_create(int keysize, MoviKeyDeleterFP keydeleterfp,
+                                  GHashHashFP hashfp, GHashCmpFP cmpfp,
+                                  MovieCacheGetKeyDataFP getdatafp,
+                                  MovieCacheCheckKeyUnusedFP checkkeyunusedfp)
 {
        MovieCache *cache;
 
@@ -209,10 +225,12 @@ MovieCache *IMB_moviecache_create(int keysize, GHashHashFP hashfp, GHashCmpFP cm
        cache->userkeys_pool = BLI_mempool_create(keysize, 64, 64, 0);
        cache->hash = BLI_ghash_new(moviecache_hashhash, moviecache_hashcmp, "MovieClip ImBuf cache hash");
 
+       cache->keydeleterfp = keydeleterfp;
        cache->keysize = keysize;
        cache->hashfp = hashfp;
        cache->cmpfp = cmpfp;
        cache->getdatafp = getdatafp;
+       cache->checkkeyunusedfp = checkkeyunusedfp;
        cache->proxy = -1;
 
        return cache;
index 75dc515ef39aecf5a6705d9d0652515a2dcf6a00..e2eaacc5a5548329773abeefab2f2942b15e978a 100644 (file)
@@ -691,7 +691,7 @@ typedef struct SpaceImage {
        char around;
 
        /* color transformation  */
-       int view_transform, pad2;
+       char view_transform[64];
 } SpaceImage;
 
 
@@ -755,15 +755,6 @@ typedef enum eSpaceImage_Flag {
        SI_COLOR_CORRECTION   = (1 << 24),
 } eSpaceImage_Flag;
 
-/* SpaceImage->flag */
-typedef enum eSpaceImage_ViewTransform {
-       SI_VIEW_TRANSFORM_NONE = 0,
-       SI_VIEW_TRANSFORM_ACES_ODT_TONECURVE = 1,
-       SI_VIEW_TRANSFORM_OCIO_RAW = 2,
-       SI_VIEW_TRANSFORM_OCIO_RRT = 3,
-       SI_VIEW_TRANSFORM_OCIO_LOG = 4,
-} eSpaceImage_ViewTransform;
-
 /* Text Editor ============================================ */
 
 /* Text Editor */
index 5a49e45cf5e5026780cce874cca4639886e026b5..44eb1ed46e7f095cd437eef14a508b03dccfa864 100644 (file)
@@ -195,6 +195,8 @@ typedef struct wmWindow {
        
        ListBase subwindows;    /* opengl stuff for sub windows, see notes in wm_subwindow.c */
        ListBase gesture;               /* gesture stuff */
+
+       char display_device[64];        /* color managed display device name */
 } wmWindow;
 
 /* should be something like DNA_EXCLUDE 
index 8ae2500ddc1713f6e5ed06b3f69f76dc0d82d061..b2b87f3df52a43c3639d5cc1cabad8d0b45b5243 100644 (file)
@@ -118,6 +118,11 @@ EnumPropertyItem viewport_shade_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+static EnumPropertyItem view_transform_items[] = {
+       {0, "NONE", 0, "None", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
 #ifdef RNA_RUNTIME
 
 #include "DNA_anim_types.h"
@@ -143,6 +148,7 @@ EnumPropertyItem viewport_shade_items[] = {
 #include "ED_sequencer.h"
 #include "ED_clip.h"
 
+#include "IMB_colormanagement.h"
 #include "IMB_imbuf_types.h"
 
 static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
@@ -665,6 +671,38 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
        ED_space_image_release_buffer(sima, lock);
 }
 
+static int rna_SpaceImageEditor_view_transform_get(PointerRNA *ptr)
+{
+       SpaceImage *sima = (SpaceImage *) ptr->data;
+
+       return IMB_colormanagement_view_get_named_index(sima->view_transform);
+}
+
+static void rna_SpaceImageEditor_view_transform_set(PointerRNA *ptr, int value)
+{
+       SpaceImage *sima = (SpaceImage*) ptr->data;
+
+       const char *name = IMB_colormanagement_view_get_indexed_name(value);
+
+       if (name) {
+               BLI_strncpy(sima->view_transform, name, sizeof(sima->view_transform));
+       }
+}
+
+static EnumPropertyItem* rna_SpaceImageEditor_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+       wmWindow *win = CTX_wm_window(C);
+       EnumPropertyItem *items = NULL;
+       int totitem = 0;
+
+       RNA_enum_item_add(&items, &totitem, &view_transform_items[0]);
+       IMB_colormanagement_view_items_add(&items, &totitem, win->display_device);
+       RNA_enum_item_end(&items, &totitem);
+
+       *free = 1;
+       return items;
+}
+
 /* Space Text Editor */
 
 static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value)
@@ -1922,15 +1960,6 @@ static void rna_def_space_image(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
-       static EnumPropertyItem view_transform_items[] = {
-               {SI_VIEW_TRANSFORM_NONE, "NONE", ICON_NONE, "None", ""},
-               {SI_VIEW_TRANSFORM_ACES_ODT_TONECURVE, "ACES_TOMEMAP", ICON_NONE, "ACES ODT Tonecurve", ""},
-               {SI_VIEW_TRANSFORM_OCIO_RAW, "OCIO_RAW", ICON_NONE, "OCIO RAW", ""},
-               {SI_VIEW_TRANSFORM_OCIO_RRT, "OCIO_RRT", ICON_NONE, "OCIO RRT", ""},
-               {SI_VIEW_TRANSFORM_OCIO_LOG, "OCIO_LOG", ICON_NONE, "OCIO LOG", ""},
-               {0, NULL, 0, NULL, NULL}
-       };
-
        srna = RNA_def_struct(brna, "SpaceImageEditor", "Space");
        RNA_def_struct_sdna(srna, "SpaceImage");
        RNA_def_struct_ui_text(srna, "Space Image Editor", "Image and UV editor space data");
@@ -2035,10 +2064,11 @@ static void rna_def_space_image(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Show UV Editor", "Show UV editing related properties");
 
-       prop = RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_sdna(prop, NULL, "view_transform");
+       prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_items(prop, view_transform_items);
-       RNA_def_property_ui_text(prop, "View Transform", "Transformation used on linear to sRGB conversion");
+       RNA_def_property_enum_funcs(prop, "rna_SpaceImageEditor_view_transform_get", "rna_SpaceImageEditor_view_transform_set",
+                                   "rna_SpaceImageEditor_view_transform_itemf");
+       RNA_def_property_ui_text(prop, "View Transform", "View transform used for this image editor");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
 
        rna_def_space_image_uv(brna);
index 8c6a2809ef892834c8d7c320b1b9f73f7a0e6177..99a56baed953127e22a55ad56e05805d1dcd04f9 100644 (file)
@@ -440,6 +440,8 @@ EnumPropertyItem wm_report_items[] = {
 
 #include "MEM_guardedalloc.h"
 
+#include "IMB_colormanagement.h"
+
 static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr)
 {
        wmWindowManager *wm = ptr->id.data;
@@ -570,6 +572,36 @@ static void rna_Window_screen_update(bContext *C, PointerRNA *ptr)
        }
 }
 
+static int rna_Window_display_device_get(struct PointerRNA *ptr)
+{
+       wmWindow *win = (wmWindow *) ptr->data;
+
+       return IMB_colormanagement_display_get_named_index(win->display_device);
+}
+
+static void rna_Window_display_device_set(struct PointerRNA *ptr, int value)
+{
+       wmWindow *win = (wmWindow *) ptr->data;
+       const char *name = IMB_colormanagement_display_get_indexed_name(value);
+
+       if (name) {
+               BLI_strncpy(win->display_device, name, sizeof(win->display_device));
+       }
+}
+
+static EnumPropertyItem *rna_Window_display_device_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+       EnumPropertyItem *items = NULL;
+       int totitem = 0;
+
+       IMB_colormanagement_display_items_add(&items, &totitem);
+       RNA_enum_item_end(&items, &totitem);
+
+       *free = TRUE;
+
+       return items;
+}
+
 static PointerRNA rna_KeyMapItem_properties_get(PointerRNA *ptr)
 {
        wmKeyMapItem *kmi = ptr->data;
@@ -1577,6 +1609,11 @@ static void rna_def_window(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
+       static EnumPropertyItem display_device_items[] = {
+               {0, "DEFAULT", 0, "Default", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        srna = RNA_def_struct(brna, "Window", NULL);
        RNA_def_struct_ui_text(srna, "Window", "Open window");
        RNA_def_struct_sdna(srna, "wmWindow");
@@ -1589,6 +1626,14 @@ static void rna_def_window(BlenderRNA *brna)
        RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL, NULL);
        RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
        RNA_def_property_update(prop, 0, "rna_Window_screen_update");
+
+       /* Color Management Display */
+       prop= RNA_def_property(srna, "display_device", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, display_device_items);
+       RNA_def_property_enum_funcs(prop, "rna_Window_display_device_get", "rna_Window_display_device_set",
+                                   "rna_Window_display_device_itemf");
+       RNA_def_property_ui_text(prop, "Display Device", "Display device name used for this window");
+       RNA_def_property_update(prop, NC_WINDOW, NULL);
 }
 
 /* curve.splines */
index 001857cbf678858f36429fc20c0721bcab3fc4d6..275aeb3317c3f86caaaedb6931b60eb4e8df64dc 100644 (file)
@@ -143,12 +143,4 @@ if(WIN322)
        )
 endif()
 
-if(WITH_OPENCOLORIO)
-       add_definitions(-DWITH_OCIO)
-endif()
-
-if(WITH_OPENCOLORIO)
-       add_definitions(-DWITH_OCIO)
-endif()
-
 blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}" "${INC_SYS}")
index 1b7db0eb127fb9eb84c6c0c68075d5baefce6fdb..57d632c7d042693c1bd6c422100de16925c514e2 100644 (file)
@@ -43,10 +43,4 @@ if env['BF_BUILDINFO']:
 if env['WITH_BF_INTERNATIONAL']:
     defs.append('WITH_INTERNATIONAL')
 
-if env['WITH_BF_OCIO']:
-    defs.append('WITH_OCIO')
-
-if env['WITH_BF_OCIO']:
-    defs.append('WITH_OCIO')
-
 env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defines=defs, libtype=['core'], priority=[5] )
index 52dfe863ad43fa490796ad821e3b14a115b0250f..cabc51a6e5bb2f03bdd5c0c8d194a69fe41fe50e 100644 (file)
 #include "BKE_depsgraph.h"
 #include "BKE_sound.h"
 
-#ifdef WITH_OCIO
 #include "IMB_colormanagement.h"
-#endif
 
 static void wm_init_reports(bContext *C)
 {
@@ -147,6 +145,10 @@ void WM_init(bContext *C, int argc, const char **argv)
        
        BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
        BLF_lang_init();
+
+       /* initialize color management stuff */
+       IMB_colormanagement_init();
+
        /* get the default database, plus a wm */
        WM_read_homefile(C, NULL, G.factory_startup);
 
@@ -203,10 +205,6 @@ void WM_init(bContext *C, int argc, const char **argv)
 #endif
 
        BLI_strncpy(G.lib, G.main->name, FILE_MAX);
-
-#ifdef WITH_OCIO
-       IMB_colormanagement_init();
-#endif
 }
 
 void WM_init_splash(bContext *C)
@@ -340,6 +338,7 @@ void WM_exit_ext(bContext *C, const short do_python)
 
        sound_exit();
 
+       IMB_colormanagement_exit();
 
        /* first wrap up running stuff, we assume only the active WM is running */
        /* modal handlers are on window level freed, others too? */
@@ -460,10 +459,6 @@ void WM_exit_ext(bContext *C, const short do_python)
                getchar();
        }
 #endif 
-
-#ifdef WITH_OCIO
-       IMB_colormanagement_exit();
-#endif
 }
 
 void WM_exit(bContext *C)
index dd501e6d88057286a07f73aff927bd3d68eff448..2a50bb11bffb8007e90986fbcda8f8d3d722cd12 100644 (file)
@@ -243,7 +243,9 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
 
        win->drawmethod = -1;
        win->drawdata = NULL;
-       
+
+       BLI_strncpy(win->display_device, winorig->display_device, sizeof(win->display_device));
+
        return win;
 }