diff options
author | Ton Roosendaal <ton@blender.org> | 2010-12-14 21:02:41 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2010-12-14 21:02:41 +0300 |
commit | 9ac68ad4abf2f4bb4fc92c292170a7cf6c29b319 (patch) | |
tree | 128b666894274882e649418e8af2a81d25ce133f /source/blender | |
parent | 73ea636abb6f9d4d25155f630ac606973e9bf335 (diff) |
Bugfix #22040
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 3 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf.h | 1 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf_types.h | 3 | ||||
-rw-r--r-- | source/blender/imbuf/intern/IMB_filter.h | 2 | ||||
-rw-r--r-- | source/blender/imbuf/intern/filter.c | 37 | ||||
-rw-r--r-- | source/blender/imbuf/intern/scaling.c | 33 | ||||
-rw-r--r-- | source/blender/render/intern/source/imagetexture.c | 48 |
7 files changed, 92 insertions, 35 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 84816cebc46..46bcd1f1c0d 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -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)) { diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a22168e06a3..2accad35859 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -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); /** diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index a12976fa813..f60c6d03547 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -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 diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h index 84ad72c520a..0d414cb4702 100644 --- a/source/blender/imbuf/intern/IMB_filter.h +++ b/source/blender/imbuf/intern/IMB_filter.h @@ -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 diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 3c2c276b6e4..13c0e6cf632 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -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) { diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 73dcc0c8ea9..1f50deaee2a 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -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 */ diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 9376c798c39..5a2ce5a6b89 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -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); |