Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / image.c
index 76cf731..fc6530a 100644 (file)
@@ -82,6 +82,7 @@
 #include "BKE_scene.h"
 #include "BKE_node.h"
 #include "BKE_sequencer.h" /* seq_foreground_frame_get() */
+#include "BKE_workspace.h"
 
 #include "BLF_api.h"
 
@@ -341,19 +342,18 @@ void BKE_image_free_buffers(Image *ima)
 /** Free (or release) any data used by this image (does not free the image itself). */
 void BKE_image_free(Image *ima)
 {
-       int a;
-
        /* Also frees animdata. */
        BKE_image_free_buffers(ima);
 
        image_free_packedfiles(ima);
 
-       for (a = 0; a < IMA_MAX_RENDER_SLOT; a++) {
-               if (ima->renders[a]) {
-                       RE_FreeRenderResult(ima->renders[a]);
-                       ima->renders[a] = NULL;
+       LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots) {
+               if (slot->render) {
+                       RE_FreeRenderResult(slot->render);
+                       slot->render = NULL;
                }
        }
+       BLI_freelistN(&ima->renderslots);
 
        BKE_image_free_views(ima);
        MEM_SAFE_FREE(ima->stereo3d_format);
@@ -369,7 +369,6 @@ static void image_init(Image *ima, short source, short type)
 
        ima->ok = IMA_OK;
 
-       ima->xrep = ima->yrep = 1;
        ima->aspx = ima->aspy = 1.0;
        ima->gen_x = 1024; ima->gen_y = 1024;
        ima->gen_type = IMA_GENTYPE_GRID;
@@ -380,6 +379,12 @@ static void image_init(Image *ima, short source, short type)
        if (source == IMA_SRC_VIEWER)
                ima->flag |= IMA_VIEW_AS_RENDER;
 
+       if (type == IMA_TYPE_R_RESULT) {
+               for (int i = 0; i < 8; i++) {
+                       BKE_image_add_renderslot(ima, NULL);
+               }
+       }
+
        BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
        ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format");
 }
@@ -466,18 +471,17 @@ void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_s
        /* Cleanup stuff that cannot be copied. */
        ima_dst->cache = NULL;
        ima_dst->rr = NULL;
-       for (int i = 0; i < IMA_MAX_RENDER_SLOT; i++) {
-               ima_dst->renders[i] = NULL;
+
+       BLI_duplicatelist(&ima_dst->renderslots, &ima_src->renderslots);
+       LISTBASE_FOREACH(RenderSlot *, slot, &ima_dst->renderslots) {
+               slot->render = NULL;
        }
 
        BLI_listbase_clear(&ima_dst->anims);
 
-       ima_dst->totbind = 0;
        for (int i = 0; i < TEXTARGET_COUNT; i++) {
-               ima_dst->bindcode[i] = 0;
                ima_dst->gputexture[i] = NULL;
        }
-       ima_dst->repbind = NULL;
 
        if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
                BKE_previewimg_id_copy(&ima_dst->id, &ima_src->id);
@@ -540,16 +544,14 @@ bool BKE_image_scale(Image *image, int width, int height)
        return (ibuf != NULL);
 }
 
-bool BKE_image_has_bindcode(Image *ima)
+bool BKE_image_has_opengl_texture(Image *ima)
 {
-       bool has_bindcode = false;
        for (int i = 0; i < TEXTARGET_COUNT; i++) {
-               if (ima->bindcode[i]) {
-                       has_bindcode = true;
-                       break;
+               if (ima->gputexture[i]) {
+                       return true;
                }
        }
-       return has_bindcode;
+       return false;
 }
 
 static void image_init_color_management(Image *ima)
@@ -932,21 +934,6 @@ void BKE_image_tag_time(Image *ima)
        ima->lastused = PIL_check_seconds_timer_i();
 }
 
-#if 0
-static void tag_all_images_time(Main *bmain)
-{
-       Image *ima;
-       int ctime = PIL_check_seconds_timer_i();
-
-       ima = bmain->image.first;
-       while (ima) {
-               if (ima->bindcode || ima->repbind || ima->ibufs.first) {
-                       ima->lastused = ctime;
-               }
-       }
-}
-#endif
-
 static uintptr_t image_mem_size(Image *image)
 {
        uintptr_t size = 0;
@@ -1208,7 +1195,6 @@ bool BKE_imtype_is_movie(const char imtype)
                case R_IMF_IMTYPE_H264:
                case R_IMF_IMTYPE_THEORA:
                case R_IMF_IMTYPE_XVID:
-               case R_IMF_IMTYPE_FRAMESERVER:
                        return true;
        }
        return false;
@@ -1349,7 +1335,6 @@ char BKE_imtype_from_arg(const char *imtype_arg)
        else if (STREQ(imtype_arg, "MULTILAYER")) return R_IMF_IMTYPE_MULTILAYER;
 #endif
        else if (STREQ(imtype_arg, "FFMPEG")) return R_IMF_IMTYPE_FFMPEG;
-       else if (STREQ(imtype_arg, "FRAMESERVER")) return R_IMF_IMTYPE_FRAMESERVER;
 #ifdef WITH_CINEON
        else if (STREQ(imtype_arg, "CINEON")) return R_IMF_IMTYPE_CINEON;
        else if (STREQ(imtype_arg, "DPX")) return R_IMF_IMTYPE_DPX;
@@ -2654,19 +2639,19 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
                }
        }
 
+       for (Camera *cam = mainp->camera.first; cam; cam = cam->id.next) {
+               for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+                       callback(bgpic->ima, &bgpic->iuser, customdata);
+               }
+       }
+
        /* image window, compo node users */
        for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
                for (win = wm->windows.first; win; win = win->next) {
-                       ScrArea *sa;
-                       for (sa = win->screen->areabase.first; sa; sa = sa->next) {
-                               if (sa->spacetype == SPACE_VIEW3D) {
-                                       View3D *v3d = sa->spacedata.first;
-                                       BGpic *bgpic;
-                                       for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
-                                               callback(bgpic->ima, &bgpic->iuser, customdata);
-                                       }
-                               }
-                               else if (sa->spacetype == SPACE_IMAGE) {
+                       const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+                       for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+                               if (sa->spacetype == SPACE_IMAGE) {
                                        SpaceImage *sima = sa->spacedata.first;
                                        callback(sima->image, &sima->iuser, customdata);
                                }
@@ -3019,7 +3004,7 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
                if (ima->render_slot == ima->last_render_slot)
                        rr = RE_AcquireResultRead(RE_GetSceneRender(scene));
                else
-                       rr = ima->renders[ima->render_slot];
+                       rr = BKE_image_get_renderslot(ima, ima->render_slot)->render;
 
                /* set proper views */
                image_init_multilayer_multiview(ima, rr);
@@ -3053,22 +3038,23 @@ bool BKE_image_is_openexr(struct Image *ima)
 
 void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
 {
-       /* called right before rendering, ima->renders contains render
+       /* called right before rendering, ima->renderslots contains render
         * result pointers for everything but the current render */
        Render *re = RE_GetSceneRender(scene);
        int slot = ima->render_slot, last = ima->last_render_slot;
 
        if (slot != last) {
-               ima->renders[last] = NULL;
-               RE_SwapResult(re, &ima->renders[last]);
+               RenderSlot *last_slot = BKE_image_get_renderslot(ima, last);
+               last_slot->render = NULL;
+               RE_SwapResult(re, &last_slot->render);
 
-               if (ima->renders[slot]) {
+               RenderSlot *cur_slot = BKE_image_get_renderslot(ima, slot);
+               if (cur_slot->render) {
                        if (free_current_slot) {
-                               RE_FreeRenderResult(ima->renders[slot]);
-                               ima->renders[slot] = NULL;
+                               BKE_image_clear_renderslot(ima, NULL, slot);
                        }
                        else {
-                               RE_SwapResult(re, &ima->renders[slot]);
+                               RE_SwapResult(re, &cur_slot->render);
                        }
                }
        }
@@ -3691,11 +3677,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
        if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO))
                actview = iuser->multiview_eye;
 
+       RenderSlot *slot;
        if (from_render) {
                RE_AcquireResultImage(re, &rres, actview);
        }
-       else if (ima->renders[ima->render_slot]) {
-               rres = *(ima->renders[ima->render_slot]);
+       else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
+               rres = *(slot->render);
                rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL;
        }
        else
@@ -4725,3 +4712,96 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
                }
        }
 }
+
+RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name)
+{
+       RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image new Render Slot");
+       if (name && name[0]) {
+               BLI_strncpy(slot->name, name, sizeof(slot->name));
+       }
+       else {
+               int n = BLI_listbase_count(&ima->renderslots) + 1;
+               BLI_snprintf(slot->name, sizeof(slot->name), "Slot %d", n);
+       }
+       BLI_addtail(&ima->renderslots, slot);
+       return slot;
+}
+
+bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index)
+{
+       int num_slots = BLI_listbase_count(&ima->renderslots);
+       if (index >= num_slots || num_slots == 1) {
+               return false;
+       }
+
+       RenderSlot *remove_slot = BLI_findlink(&ima->renderslots, index);
+       RenderSlot *current_slot = BLI_findlink(&ima->renderslots, ima->render_slot);
+       RenderSlot *current_last_slot = BLI_findlink(&ima->renderslots, ima->last_render_slot);
+
+       RenderSlot *next_slot;
+       if (current_slot == remove_slot) {
+               next_slot = BLI_findlink(&ima->renderslots, (index == num_slots - 1) ? index - 1 : index + 1);
+       }
+       else {
+               next_slot = current_slot;
+       }
+
+       /* If the slot to be removed is the slot with the last render, make another slot the last render slot. */
+       if (remove_slot == current_last_slot) {
+               /* Choose the currently selected slot unless that one is being removed, in that case take the next one. */
+               RenderSlot *next_last_slot;
+               if (current_slot == remove_slot)
+                       next_last_slot = next_slot;
+               else
+                       next_last_slot = current_slot;
+
+               if (!iuser) return false;
+               Render *re = RE_GetSceneRender(iuser->scene);
+               if (!re) return false;
+               RE_SwapResult(re, &current_last_slot->render);
+               RE_SwapResult(re, &next_last_slot->render);
+               current_last_slot = next_last_slot;
+       }
+
+       current_slot = next_slot;
+
+       BLI_remlink(&ima->renderslots, remove_slot);
+
+       ima->render_slot = BLI_findindex(&ima->renderslots, current_slot);
+       ima->last_render_slot = BLI_findindex(&ima->renderslots, current_last_slot);
+
+       if (remove_slot->render) {
+               RE_FreeRenderResult(remove_slot->render);
+       }
+       MEM_freeN(remove_slot);
+
+       return true;
+}
+
+bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index)
+{
+       if (index == ima->last_render_slot) {
+               if (!iuser) return false;
+               if (G.is_rendering) return false;
+               Render *re = RE_GetSceneRender(iuser->scene);
+               if (!re) return false;
+               RE_ClearResult(re);
+               return true;
+       }
+       else {
+               RenderSlot *slot = BLI_findlink(&ima->renderslots, index);
+               if (!slot) return false;
+               if (slot->render) {
+                       RE_FreeRenderResult(slot->render);
+                       slot->render = NULL;
+               }
+               return true;
+       }
+}
+
+RenderSlot *BKE_image_get_renderslot(Image *ima, int index)
+{
+       RenderSlot *slot = BLI_findlink(&ima->renderslots, index);
+       BLI_assert(slot);
+       return slot;
+}