From ef0c02cb4dbd5f74fd0cb7c7ef119e4ca1936249 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 6 May 2016 11:48:07 +0200 Subject: Speedup of regular 2D painting Yet another commit which makes painting aware of multi-threaded systems. --- source/blender/imbuf/IMB_imbuf.h | 17 ++++++- source/blender/imbuf/intern/allocimbuf.c | 81 ++++++++++++++++++-------------- source/blender/imbuf/intern/rectop.c | 63 +++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 36 deletions(-) (limited to 'source/blender/imbuf') diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 383a5f19c4a..93d2b3e0cd0 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -130,7 +130,18 @@ void IMB_freeImBuf(struct ImBuf *ibuf); * \attention Defined in allocimbuf.c */ struct ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, - unsigned char d, unsigned int flags); + unsigned char planes, unsigned int flags); + +/** + * Initialize given ImBuf. + * + * Use in cases when temporary image buffer is allocated on stack. + * + * \attention Defined in allocimbuf.c + */ +bool IMB_initImBuf(struct ImBuf *ibuf, + unsigned int x, unsigned int y, + unsigned char planes, unsigned int flags); /** * Create a copy of a pixel buffer and wrap it to a new ImBuf @@ -213,6 +224,10 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max, int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height, IMB_BlendMode mode, bool accumulate); +void IMB_rectblend_threaded(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf, + unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max, + int destx, int desty, int origx, int origy, int srcx, int srcy, + int width, int height, IMB_BlendMode mode, bool accumulate); /** * diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 988f43ff9fa..ef3743d9c8a 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -446,49 +446,60 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int { ImBuf *ibuf; - ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct"); + ibuf = MEM_mallocN(sizeof(ImBuf), "ImBuf_struct"); if (ibuf) { - ibuf->x = x; - ibuf->y = y; - ibuf->planes = planes; - ibuf->ftype = IMB_FTYPE_PNG; - ibuf->foptions.quality = 15; /* the 15 means, set compression to low ratio but not time consuming */ - ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ - ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */ - - if (flags & IB_rect) { - if (imb_addrectImBuf(ibuf) == false) { - IMB_freeImBuf(ibuf); - return NULL; - } + if (!IMB_initImBuf(ibuf, x, y, planes, flags)) { + IMB_freeImBuf(ibuf); + return NULL; } - - if (flags & IB_rectfloat) { - if (imb_addrectfloatImBuf(ibuf) == false) { - IMB_freeImBuf(ibuf); - return NULL; - } + } + + return (ibuf); +} + +bool IMB_initImBuf(struct ImBuf *ibuf, + unsigned int x, unsigned int y, + unsigned char planes, unsigned int flags) +{ + memset(ibuf, 0, sizeof(ImBuf)); + + ibuf->x = x; + ibuf->y = y; + ibuf->planes = planes; + ibuf->ftype = IMB_FTYPE_PNG; + ibuf->foptions.quality = 15; /* the 15 means, set compression to low ratio but not time consuming */ + ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ + ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */ + + if (flags & IB_rect) { + if (imb_addrectImBuf(ibuf) == false) { + return false; } - - if (flags & IB_zbuf) { - if (addzbufImBuf(ibuf) == false) { - IMB_freeImBuf(ibuf); - return NULL; - } + } + + if (flags & IB_rectfloat) { + if (imb_addrectfloatImBuf(ibuf) == false) { + return false; } - - if (flags & IB_zbuffloat) { - if (addzbuffloatImBuf(ibuf) == false) { - IMB_freeImBuf(ibuf); - return NULL; - } + } + + if (flags & IB_zbuf) { + if (addzbufImBuf(ibuf) == false) { + return false; } + } - /* assign default spaces */ - colormanage_imbuf_set_default_spaces(ibuf); + if (flags & IB_zbuffloat) { + if (addzbuffloatImBuf(ibuf) == false) { + return false; + } } - return (ibuf); + + /* assign default spaces */ + colormanage_imbuf_set_default_spaces(ibuf); + + return true; } /* does no zbuffers? */ diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index c7b347cb20c..3360fd7548e 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -693,6 +693,69 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, } } +typedef struct RectBlendThreadData { + ImBuf *dbuf, *obuf, *sbuf; + unsigned short *dmask, *curvemask, *texmask; + float mask_max; + int destx, desty, origx, origy; + int srcx, srcy, width; + IMB_BlendMode mode; + bool accumulate; +} RectBlendThreadData; + +static void rectblend_thread_do(void *data_v, + int start_scanline, + int num_scanlines) +{ + RectBlendThreadData *data = (RectBlendThreadData *)data_v; + IMB_rectblend(data->dbuf, data->obuf, data->sbuf, + data->dmask, data->curvemask, data->texmask, + data->mask_max, + data->destx, + data->desty + start_scanline, + data->origx, + data->origy + start_scanline, + data->srcx, + data->srcy + start_scanline, + data->width, num_scanlines, + data->mode, data->accumulate); +} + +void IMB_rectblend_threaded(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, + unsigned short *dmask, unsigned short *curvemask, + unsigned short *texmask, float mask_max, + int destx, int desty, int origx, int origy, + int srcx, int srcy, int width, int height, + IMB_BlendMode mode, bool accumulate) +{ + if (((size_t)width) * height < 64 * 64) { + IMB_rectblend(dbuf, obuf, sbuf, dmask, curvemask, texmask, + mask_max, destx, desty, origx, origy, + srcx, srcy, width, height, mode, accumulate); + } + else { + RectBlendThreadData data; + data.dbuf = dbuf; + data.obuf = obuf; + data.sbuf = sbuf; + data.dmask = dmask; + data.curvemask = curvemask; + data.texmask = texmask; + data.mask_max = mask_max; + data.destx = destx; + data.desty = desty; + data.origx = origx; + data.origy = origy; + data.srcx = srcx; + data.srcy = srcy; + data.width = width; + data.mode = mode; + data.accumulate = accumulate; + IMB_processor_apply_threaded_scanlines( + height, rectblend_thread_do, &data); + } +} + /* fill */ void IMB_rectfill(ImBuf *drect, const float col[4]) -- cgit v1.2.3