[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60883] branches/soc-2013-paint/source/ blender/editors/sculpt_paint/paint_image_proj.c: Simplify undo pushing for projection painting.
Antony Riakiotakis
kalast at gmail.com
Mon Oct 21 18:32:17 CEST 2013
Revision: 60883
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60883
Author: psy-fi
Date: 2013-10-21 16:32:16 +0000 (Mon, 21 Oct 2013)
Log Message:
-----------
Simplify undo pushing for projection painting.
* Do not compare image pixels at end of stroke, it causes a great
stutter at the end of painting on large images (4096x4096 in my test
case). In any case tiles have been pushed already for such images.
* Only add tile if pixel passes the mask test. Previous approach could
add tiles even for clipped pixels.
Modified Paths:
--------------
branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c
Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c 2013-10-21 15:44:09 UTC (rev 60882)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_image_proj.c 2013-10-21 16:32:16 UTC (rev 60883)
@@ -330,6 +330,16 @@
PixelStore clonepx;
} ProjPixelClone;
+/* undo tile pushing */
+typedef struct {
+ bool threaded;
+ bool masked;
+ unsigned short tile_width;
+ ImBuf **tmpibuf;
+ ProjPaintImage *pjima;
+} TileInfo;
+
+
/* Finish projection painting structs */
static Image *project_paint_face_image(const ProjPaintState *ps, int face_index)
@@ -1380,26 +1390,53 @@
}
}
+static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
+{
+ unsigned short *maskrect;
+ ProjPaintImage *pjIma = tinf->pjima;
+ int tileindex = tx + ty * tinf->tile_width;
+
+ if (tinf->threaded)
+ BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ if (UNLIKELY(!pjIma->undoRect[tileindex])) {
+ if (tinf->masked) {
+ pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &maskrect);
+ pjIma->maskRect[tileindex] = maskrect;
+ }
+ else
+ pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL);
+
+ pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+
+ if (tinf->threaded)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
+ return tileindex;
+}
+
/* run this function when we know a bucket's, face's pixel can be initialized,
* return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
static ProjPixel *project_paint_uvpixel_init(
const ProjPaintState *ps,
MemArena *arena,
- const ProjPaintImage *projima,
+ const TileInfo *tinf,
int x_px, int y_px,
const float mask,
const int face_index,
const float pixelScreenCo[4],
const float world_spaceCo[3],
const int side,
- const float w[3], unsigned int tile_width)
+ const float w[3])
{
ProjPixel *projPixel;
int x_tile, y_tile;
int x_round, y_round;
int tile_offset, tile_index;
+ ProjPaintImage *projima = tinf->pjima;
ImBuf *ibuf = projima->ibuf;
/* wrap pixel location */
@@ -1415,11 +1452,10 @@
y_round = y_tile * IMAPAINT_TILE_SIZE;
tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
- tile_index = x_tile + y_tile * tile_width;
+ tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
- BLI_assert(projima->undoRect[tile_index] != NULL);
BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
@@ -2232,112 +2268,6 @@
return 1;
}
-static void project_paint_undo_subtiles(rcti *bounds_px, ProjPaintImage *pjIma, ImBuf **tmpibuf, unsigned short tile_width, bool threaded, bool do_masking)
-{
- int tilex, tiley, tilew, tileh, tx, ty;
- unsigned short *maskrect;
- /* find the tiles covered by this face and make sure they are initialized */
- imapaint_region_tiles(pjIma->ibuf, bounds_px->xmin, bounds_px->ymin,
- bounds_px->xmax - bounds_px->xmin, bounds_px->ymax - bounds_px->ymin,
- &tilex, &tiley, &tilew, &tileh);
-
- if (threaded)
- BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
-
- for (ty = tiley; ty <= tileh; ty++) {
- for (tx = tilex; tx <= tilew; tx++) {
- int tileindex = tx + tile_width * ty;
-
- if (!pjIma->undoRect[tileindex]) {
- if (do_masking) {
- pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tmpibuf, tx, ty, &maskrect);
- pjIma->maskRect[tileindex] = maskrect;
- }
- else
- pjIma->undoRect[tileindex] = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tmpibuf, tx, ty, NULL);
-
- pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
- }
- else {
-
- }
- }
- }
-
- if (threaded)
- BLI_unlock_thread(LOCK_CUSTOM1);
-
-}
-
-/* check if boundary rectangle of face in uv space exceeds the image boundaries and if it does, create subrectangles to properly initialize the tiles */
-static void project_paint_undo_tiles_init(rcti *bounds_px, ProjPaintImage *pjIma, ImBuf **tmpibuf, unsigned short tile_width, bool threaded, bool do_masking)
-{
- rcti rect;
- ImBuf *ibuf = pjIma->ibuf;
- /* first determine if bounds rectangle exceeds the ibuf bounds, and if it does, create
- * extra rectangles to initialize the tiles from. The rectangles get clipped so it shouldn't
- * generate any unneeded tiles */
- if (bounds_px->xmin < 0) {
- rect.xmin = ibuf->x + bounds_px->xmin;
- rect.xmax = ibuf->x;
- rect.ymin = bounds_px->ymin;
- rect.ymax = bounds_px->ymax;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->xmax >= ibuf->x) {
- rect.xmin = 0;
- rect.xmax = bounds_px->xmax - ibuf->x + 1;
- rect.ymin = bounds_px->ymin;
- rect.ymax = bounds_px->ymax;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->ymin < 0) {
- rect.xmax = bounds_px->xmax;
- rect.xmin = bounds_px->xmin;
- rect.ymin = ibuf->y + bounds_px->ymin;
- rect.ymax = ibuf->y;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->ymax >= ibuf->y) {
- rect.xmax = bounds_px->xmax;
- rect.xmin = bounds_px->xmin;
- rect.ymin = 0;
- rect.ymax = bounds_px->ymax - ibuf->y + 1;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- /* finally check the diagonals */
- if (bounds_px->xmin < 0 && bounds_px->ymin < 0) {
- rect.xmin = ibuf->x + bounds_px->xmin;
- rect.xmax = ibuf->x;
- rect.ymin = ibuf->y + bounds_px->ymin;
- rect.ymax = ibuf->y;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->xmax >= ibuf->x && bounds_px->ymax >= ibuf->y) {
- rect.xmin = 0;
- rect.xmax = bounds_px->xmax - ibuf->x + 1;
- rect.ymin = 0;
- rect.ymax = bounds_px->ymax - ibuf->y + 1;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->xmin < 0 && bounds_px->ymax >= ibuf->y) {
- rect.xmin = ibuf->x + bounds_px->xmin;
- rect.xmax = ibuf->x;
- rect.ymin = 0;
- rect.ymax = bounds_px->ymax - ibuf->y + 1;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- if (bounds_px->xmax >= ibuf->x && bounds_px->ymin < 0) {
- rect.xmin = 0;
- rect.xmax = bounds_px->xmax - ibuf->x + 1;
- rect.ymin = ibuf->y + bounds_px->ymin;
- rect.ymax = ibuf->y;
- project_paint_undo_subtiles(&rect, pjIma, tmpibuf, tile_width, threaded, do_masking);
- }
- /* finally do the rectangle itself */
- project_paint_undo_subtiles(bounds_px, pjIma, tmpibuf, tile_width, threaded, do_masking);
-}
-
/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
* initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
@@ -2347,6 +2277,13 @@
LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+ TileInfo tinf = {
+ (ps->thread_tot > 1),
+ ps->do_masking,
+ IMAPAINT_TILE_NUMBER(ibuf->x),
+ tmpibuf,
+ ps->projImages + image_index
+ };
const MFace *mf = ps->dm_mface + face_index;
const MTFace *tf = ps->dm_mtface + face_index;
@@ -2355,7 +2292,6 @@
int y; /* Image Y-Pixel */
float mask;
float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
- unsigned short tile_width;
int side;
float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
@@ -2427,8 +2363,6 @@
side = 0;
}
- tile_width = IMAPAINT_TILE_NUMBER(ibuf->x);
-
do {
if (side == 1) {
i1 = 0; i2 = 2; i3 = 3;
@@ -2471,9 +2405,10 @@
CLAMP(bounds_px.ymax, 0, ibuf->y);
}
+ /*
project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
tile_width, threaded, ps->do_masking);
-
+ */
/* clip face and */
has_isect = 0;
@@ -2517,8 +2452,8 @@
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ps->projImages + image_index, x, y, mask, face_index,
- pixelScreenCo, wco, side, w, tile_width),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
}
@@ -2648,9 +2583,6 @@
if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, true)) {
/* bounds between the seam rect and the uvspace bucket pixels */
- project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
- tile_width, threaded, ps->do_masking);
-
has_isect = 0;
for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
// uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
@@ -2740,8 +2672,8 @@
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ps->projImages + image_index, x, y, mask, face_index,
- pixelScreenCo, wco, side, w, tile_width),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list