Bugfix #22040
authorTon Roosendaal <ton@blender.org>
Tue, 14 Dec 2010 18:02:41 +0000 (18:02 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 14 Dec 2010 18:02:41 +0000 (18:02 +0000)
Old bug report:

Image Editor, Painting: crash when texture was visible in
Material or Texture preview. Was caused by paint code
freeing mipmaps. Now replaced with a mipmap tag (to be done
again), and a new mipmap function that doesn't re-allocate.

source/blender/editors/sculpt_paint/paint_image.c
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/IMB_filter.h
source/blender/imbuf/intern/filter.c
source/blender/imbuf/intern/scaling.c
source/blender/render/intern/source/imagetexture.c

index 84816cebc463faf0c861c27bc5f4b469ba2c5aa4..46bcd1f1c0da2cd147b98137fc3f47600fe98b7b 100644 (file)
@@ -4013,8 +4013,9 @@ static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, s
        if(ibuf->rect_float)
                /* TODO - should just update a portion from imapaintpartial! */
                imb_freerectImBuf(ibuf); /* force recreate of char rect */
+       
        if(ibuf->mipmap[0])
-               imb_freemipmapImBuf(ibuf);
+               ibuf->userflags |= IB_MIPMAP_INVALID;
 
        /* todo: should set_tpage create ->rect? */
        if(texpaint || (sima && sima->lock)) {
index a22168e06a30474d3a5550651d477d195b00a75e..2accad35859ba26608adc4bbacb9686e0ee6c3c9 100644 (file)
@@ -244,6 +244,7 @@ void IMB_filter(struct ImBuf *ibuf);
 void IMB_filterN(struct ImBuf *out, struct ImBuf *in);
 void IMB_filter_extend(struct ImBuf *ibuf, char *mask);
 void IMB_makemipmap(struct ImBuf *ibuf, int use_filter);
+void IMB_remakemipmap(struct ImBuf *ibuf, int use_filter);
 struct ImBuf *IMB_getmipmap(struct ImBuf *ibuf, int level);
 
 /**
index a12976fa813999083874817549020504a344046e..f60c6d03547ce3e0a3a25de1ae8660ac891db050 100644 (file)
@@ -131,11 +131,12 @@ typedef struct ImBuf {
 
 /* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */
 /**
- * \brief Flags used internally by blender for imagebuffers
+ * \brief userflags: Flags used internally by blender for imagebuffers
  */
 
 #define IB_BITMAPFONT          (1 << 0)        /* this image is a font */
 #define IB_BITMAPDIRTY         (1 << 1)        /* image needs to be saved is not the same as filename */
+#define IB_MIPMAP_INVALID      (1 << 2)        /* image mipmaps are invalid, need recreate */
 
 /* From iff.h. This was once moved away by Frank, now Nzc moves it
  * back. Such is the way it is... It is a long list of defines, and
index 84ad72c520a2481d4bd65f963e412dfdd7a7c4ce..0d414cb4702aa19869987ff879e695f11fbe15ee 100644 (file)
@@ -44,5 +44,7 @@ void imb_filterx(struct ImBuf *ibuf);
 void IMB_premultiply_rect(unsigned int *rect, int depth, int w, int h);
 void IMB_premultiply_rect_float(float *rect_float, int depth, int w, int h);
 
+void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1);
+
 #endif
 
index 3c2c276b6e4091aa61629dd160ff54b243ee5d3c..13c0e6cf632345f067dd0b704d11d979e6367113 100644 (file)
@@ -371,11 +371,48 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask)
        }
 }
 
+/* threadsafe version, only recreates existing maps */
+void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
+{
+       ImBuf *hbuf = ibuf;
+       int curmap = 0;
+       
+       ibuf->miptot= 1;
+       
+       while(curmap < IB_MIPMAP_LEVELS) {
+               
+               if(ibuf->mipmap[curmap]) {
+                       
+                       if(use_filter) {
+                               ImBuf *nbuf= IMB_allocImBuf(hbuf->x, hbuf->y, 32, IB_rect);
+                               IMB_filterN(nbuf, hbuf);
+                               imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf);
+                               IMB_freeImBuf(nbuf);
+                       }
+                       else
+                               imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf);
+               }
+               
+               ibuf->miptot= curmap+2;
+               hbuf= ibuf->mipmap[curmap];
+               if(hbuf)
+                       hbuf->miplevel= curmap+1;
+               
+               if(!hbuf || (hbuf->x <= 2 && hbuf->y <= 2))
+                       break;
+               
+               curmap++;
+       }
+}
+
+/* frees too (if there) and recreates new data */
 void IMB_makemipmap(ImBuf *ibuf, int use_filter)
 {
        ImBuf *hbuf = ibuf;
        int curmap = 0;
 
+       imb_freemipmapImBuf(ibuf);
+       
        ibuf->miptot= 1;
 
        while(curmap < IB_MIPMAP_LEVELS) {
index 73dcc0c8ea9d528254de1c050aa1de56e9fdbb9a..1f50deaee2a417f1eb141e051da50b17e7496f0a 100644 (file)
@@ -286,26 +286,16 @@ struct ImBuf *IMB_double_y(struct ImBuf *ibuf1)
        return (ibuf2);
 }
 
-
-struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
+/* result in ibuf2, scaling should be done correctly */
+void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
 {
-       struct ImBuf *ibuf2;
        uchar *p1, *p2 = NULL, *dest;
        float *p1f, *destf, *p2f = NULL;
        int x,y;
        int do_rect, do_float;
 
-       if (ibuf1==NULL) return (0);
-       if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (0);
-
        do_rect= (ibuf1->rect != NULL);
-
-       if (ibuf1->x <= 1) return(IMB_half_y(ibuf1));
-       if (ibuf1->y <= 1) return(IMB_half_x(ibuf1));
        
-       ibuf2=IMB_allocImBuf((ibuf1->x)/2, (ibuf1->y)/2, ibuf1->depth, ibuf1->flags);
-       if (ibuf2==NULL) return (0);
-
        p1f = ibuf1->rect_float;
        destf=ibuf2->rect_float;
        p1 = (uchar *) ibuf1->rect;
@@ -343,9 +333,26 @@ struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
                        if (do_float) p1f+=4;
                }
        }
-       return (ibuf2);
+       
 }
 
+struct ImBuf *IMB_onehalf(struct ImBuf *ibuf1)
+{
+       struct ImBuf *ibuf2;
+
+       if (ibuf1==NULL) return (0);
+       if (ibuf1->rect==NULL && ibuf1->rect_float==NULL) return (0);
+       
+       if (ibuf1->x <= 1) return(IMB_half_y(ibuf1));
+       if (ibuf1->y <= 1) return(IMB_half_x(ibuf1));
+       
+       ibuf2=IMB_allocImBuf((ibuf1->x)/2, (ibuf1->y)/2, ibuf1->depth, ibuf1->flags);
+       if (ibuf2==NULL) return (0);
+       
+       imb_onehalf_no_alloc(ibuf2, ibuf1);
+       
+       return (ibuf2);
+}
 
 /* q_scale_linear_interpolation helper functions */
 
index 9376c798c391aa63e05f17a08a3c929894c57848..5a2ce5a6b8922d75b04abe932c4e23195cfbb974 100644 (file)
@@ -960,6 +960,30 @@ static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, fl
        }
 }
 
+static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
+{
+       if (tex->imaflag & TEX_MIPMAP) {
+               if ((ibuf->flags & IB_fields) == 0) {
+                       
+                       if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
+                               BLI_lock_thread(LOCK_IMAGE);
+                               if (ibuf->userflags & IB_MIPMAP_INVALID) {
+                                       IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
+                                       ibuf->userflags &= ~IB_MIPMAP_INVALID;
+                               }                               
+                               BLI_unlock_thread(LOCK_IMAGE);
+                       }
+                       if (ibuf->mipmap[0] == NULL) {
+                               BLI_lock_thread(LOCK_IMAGE);
+                               if (ibuf->mipmap[0] == NULL) 
+                                       IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
+                               BLI_unlock_thread(LOCK_IMAGE);
+                       }
+               }
+       }
+       
+}
+
 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, float *dyt, TexResult *texres)
 {
        TexResult texr;
@@ -996,15 +1020,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec,
 
        if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval;
 
-       // mipmap test
-       if (tex->imaflag & TEX_MIPMAP) {
-               if (((ibuf->flags & IB_fields) == 0) && (ibuf->mipmap[0] == NULL)) {
-                       BLI_lock_thread(LOCK_IMAGE);
-                       if (ibuf->mipmap[0] == NULL) IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
-                       BLI_unlock_thread(LOCK_IMAGE);
-               }
-       }
-
+       /* mipmap test */
+       image_mipmap_test(tex, ibuf);
+       
        if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
        texr.talpha = texres->talpha;
 
@@ -1388,17 +1406,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *DXT, f
           return retval;
        
        /* mipmap test */
-       if (tex->imaflag & TEX_MIPMAP) {
-               if(ibuf->flags & IB_fields);
-               else if(ibuf->mipmap[0]==NULL) {
-                       BLI_lock_thread(LOCK_IMAGE);
-                       
-                       if(ibuf->mipmap[0]==NULL)
-                               IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
-
-                       BLI_unlock_thread(LOCK_IMAGE);
-               }
-       }
+       image_mipmap_test(tex, ibuf);
 
        if(tex->imaflag & TEX_USEALPHA) {
                if(tex->imaflag & TEX_CALCALPHA);