[Bf-blender-cvs] [ef0c02c] master: Speedup of regular 2D painting

Sergey Sharybin noreply at git.blender.org
Fri May 6 11:59:51 CEST 2016


Commit: ef0c02cb4dbd5f74fd0cb7c7ef119e4ca1936249
Author: Sergey Sharybin
Date:   Fri May 6 11:48:07 2016 +0200
Branches: master
https://developer.blender.org/rBef0c02cb4dbd5f74fd0cb7c7ef119e4ca1936249

Speedup of regular 2D painting

Yet another commit which makes painting aware of multi-threaded systems.

===================================================================

M	source/blender/editors/sculpt_paint/paint_image_2d.c
M	source/blender/imbuf/IMB_imbuf.h
M	source/blender/imbuf/intern/allocimbuf.c
M	source/blender/imbuf/intern/rectop.c

===================================================================

diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 59b50e2..080bd5b 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -42,6 +42,7 @@
 #include "BLI_math_color_blend.h"
 #include "BLI_stack.h"
 #include "BLI_bitmap.h"
+#include "BLI_task.h"
 
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
@@ -1019,6 +1020,64 @@ static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[
 	ipos[1] = (int)floorf((pos[1] - ibufb->y / 2));
 }
 
+static void paint_2d_do_making_brush(ImagePaintState *s,
+                                     ImagePaintRegion *region,
+                                     unsigned short *curveb,
+                                     unsigned short *texmaskb,
+                                     ImBuf *frombuf,
+                                     float mask_max,
+                                     short blend,
+                                     int tilex, int tiley,
+                                     int tilew, int tileh)
+{
+	ImBuf tmpbuf;
+	IMB_initImBuf(&tmpbuf, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
+
+	for (int ty = tiley; ty <= tileh; ty++) {
+		for (int tx = tilex; tx <= tilew; tx++) {
+			/* retrieve original pixels + mask from undo buffer */
+			unsigned short *mask;
+			int origx = region->destx - tx * IMAPAINT_TILE_SIZE;
+			int origy = region->desty - ty * IMAPAINT_TILE_SIZE;
+
+			if (s->canvas->rect_float)
+				tmpbuf.rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
+			else
+				tmpbuf.rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
+
+			IMB_rectblend(s->canvas, &tmpbuf, frombuf, mask,
+			              curveb, texmaskb, mask_max,
+			              region->destx, region->desty,
+			              origx, origy,
+			              region->srcx, region->srcy,
+			              region->width, region->height,
+			              blend, ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
+		}
+	}
+}
+
+typedef struct Paint2DForeachData {
+	ImagePaintState *s;
+	ImagePaintRegion *region;
+	unsigned short *curveb;
+	unsigned short *texmaskb;
+	ImBuf *frombuf;
+	float mask_max;
+	short blend;
+	int tilex;
+	int tilew;
+} Paint2DForeachData;
+
+static void paint_2d_op_foreach_do(void *data_v, const int iter)
+{
+	Paint2DForeachData *data = (Paint2DForeachData *)data_v;
+	paint_2d_do_making_brush(data->s, data->region, data->curveb,
+	                         data->texmaskb, data->frombuf, data->mask_max,
+	                         data->blend,
+	                         data->tilex, iter,
+	                         data->tilew, iter);
+}
+
 static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2])
 {
 	ImagePaintState *s = ((ImagePaintState *)state);
@@ -1072,45 +1131,40 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
 	
 		if (s->do_masking) {
 			/* masking, find original pixels tiles from undo buffer to composite over */
-			int tilex, tiley, tilew, tileh, tx, ty;
-			ImBuf *tmpbuf;
+			int tilex, tiley, tilew, tileh;
 
 			imapaint_region_tiles(s->canvas, region[a].destx, region[a].desty,
 			                      region[a].width, region[a].height,
 			                      &tilex, &tiley, &tilew, &tileh);
 
-			tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
-
-			for (ty = tiley; ty <= tileh; ty++) {
-				for (tx = tilex; tx <= tilew; tx++) {
-					/* retrieve original pixels + mask from undo buffer */
-					unsigned short *mask;
-					int origx = region[a].destx - tx * IMAPAINT_TILE_SIZE;
-					int origy = region[a].desty - ty * IMAPAINT_TILE_SIZE;
-
-					if (s->canvas->rect_float)
-						tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
-					else
-						tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
-
-					IMB_rectblend(s->canvas, tmpbuf, frombuf, mask,
-					              curveb, texmaskb, mask_max,
-					              region[a].destx, region[a].desty,
-					              origx, origy,
-					              region[a].srcx, region[a].srcy,
-					              region[a].width, region[a].height, blend, ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
-				}
+			if (tiley == tileh) {
+				paint_2d_do_making_brush(s, &region[a], curveb, texmaskb, frombuf,
+				                         mask_max, blend, tilex, tiley, tilew, tileh);
 			}
+			else {
+				Paint2DForeachData data;
+				data.s = s;
+				data.region = &region[a];
+				data.curveb = curveb;
+				data.texmaskb = texmaskb;
+				data.frombuf = frombuf;
+				data.mask_max = mask_max;
+				data.blend = blend;
+				data.tilex = tilex;
+				data.tilew = tilew;
+				BLI_task_parallel_range(tiley, tileh + 1, &data,
+				                        paint_2d_op_foreach_do,
+				                        true);
 
-			IMB_freeImBuf(tmpbuf);
+			}
 		}
 		else {
 			/* no masking, composite brush directly onto canvas */
-			IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, curveb, texmaskb, mask_max,
-			              region[a].destx, region[a].desty,
-			              region[a].destx, region[a].desty,
-			              region[a].srcx, region[a].srcy,
-			              region[a].width, region[a].height, blend, false);
+			IMB_rectblend_threaded(s->canvas, s->canvas, frombuf, NULL, curveb, texmaskb, mask_max,
+			                       region[a].destx, region[a].desty,
+			                       region[a].destx, region[a].desty,
+			                       region[a].srcx, region[a].srcy,
+			                       region[a].width, region[a].height, blend, false);
 		}
 	}
 
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 383a5f1..93d2b3e 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 988f43f..ef3743d 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 c7b347c..3360fd7 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -693,6 +693,69 @@ void IMB_rectblend(ImBuf *dbuf, ImB

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list