Revision: 17419
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17419
Author:   campbellbarton
Date:     2008-11-12 06:56:37 +0100 (Wed, 12 Nov 2008)

Log Message:
-----------
Option to have painting multi-threaded.
Each thread process the next free bucket the brush is over until they are all 
done.

Modified Paths:
--------------
    branches/projection-paint/source/blender/src/imagepaint.c

Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c   2008-11-11 
23:24:10 UTC (rev 17418)
+++ branches/projection-paint/source/blender/src/imagepaint.c   2008-11-12 
05:56:37 UTC (rev 17419)
@@ -49,6 +49,7 @@
 #include "BLI_linklist.h"
 #include "BLI_memarena.h"
 #include "PIL_time.h"
+#include "BLI_threads.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
@@ -138,6 +139,7 @@
 //#define PROJ_DEBUG_PAINT 1
 #define PROJ_DEBUG_NOSCANLINE 1
 //#define PROJ_DEBUG_NOSEAMBLEED 1
+//#define PROJ_DEBUG_PRINT_THREADS 1
 
 /* projectFaceSeamFlags options */
 //#define PROJ_FACE_IGNORE     1<<0    /* When the face is hidden, backfacing 
or occluded */
@@ -178,6 +180,7 @@
        
        /* projection painting only */
        MemArena *projectArena;                 /* use for alocating many pixel 
structs and link-lists */
+       MemArena *projectArena_mt[BLENDER_MAX_THREADS];         /* Same as 
above but use for multithreading */
        LinkNode **projectBuckets;              /* screen sized 2D array, each 
pixel has a linked list of ProjectPixel's */
        LinkNode **projectFaces;                /* projectBuckets alligned 
array linkList of faces overlapping each bucket */
        char *projectBucketFlags;               /* store if the bucks have been 
initialized  */
@@ -193,7 +196,6 @@
        ImBuf **projectImBufs;                  /* array of imbufs we are 
painting onto while, use so we can get the rect and rect_float quickly */
        
        int projectImageTotal;                  /* size of projectImages array 
*/
-       int imaContextIndex;                    /* current image, use for 
context switching */
        
        float (*projectVertScreenCos)[4];       /* verts projected into 
floating point screen space */
        
@@ -216,6 +218,12 @@
        float viewMax2D[2]; 
        float viewWidth;                        /* Calculated from viewMin2D & 
viewMax2D */
        float viewHeight;
+       
+       /* threads */
+       int thread_tot;
+       int min_bucket[2];
+       int max_bucket[2];
+       int context_bucket_x, context_bucket_y; /* must lock threads while 
accessing these */
 } ProjectPaintState;
 
 #ifndef PROJ_DEBUG_NOSCANLINE
@@ -1201,6 +1209,8 @@
 /* 
  * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits 
are PROJ_FACE_NOSEAM1 to 4
  * 1<<i - where i is (0-3) 
+ * 
+ * If we're multithreadng, make sure threads are locked when this is called
  */
 static void project_face_seams_init(ProjectPaintState *ps, int face_index, int 
is_quad)
 {
@@ -1280,7 +1290,7 @@
 /* Only run this function once for new ProjectPixelClone's */
 #define pixel_size 4
 
-static void project_paint_uvpixel_init(ProjectPaintState *ps, ImBuf *ibuf, int 
x, int y, int bucket_index, int face_index, float pixelScreenCo[4])
+static void project_paint_uvpixel_init(ProjectPaintState *ps, int 
thread_index, ImBuf *ibuf, int x, int y, int bucket_index, int face_index, int 
image_index, float pixelScreenCo[4])
 {
        ProjectPixel *projPixel;
        short size;
@@ -1308,7 +1318,7 @@
                        size = sizeof(ProjectPixel);
                }
                
-               projPixel = (ProjectPixel 
*)BLI_memarena_alloc(ps->projectArena, size);
+               projPixel = (ProjectPixel 
*)BLI_memarena_alloc(ps->projectArena_mt[thread_index], size);
                
                if (ibuf->rect_float) {
                        projPixel->pixel = (void *) ((( float * ) 
ibuf->rect_float) + (( x + y * ibuf->x ) * pixel_size));
@@ -1345,12 +1355,12 @@
                if (ibuf->rect_float)   ((float *)projPixel->pixel)[1] = 0;
                else                                    ((char 
*)projPixel->pixel)[1] = 0;
 #endif
-               projPixel->image_index = ps->imaContextIndex;
+               projPixel->image_index = image_index;
                
                BLI_linklist_prepend_arena(
                        &ps->projectBuckets[ bucket_index ],
                        projPixel,
-                       ps->projectArena
+                       ps->projectArena_mt[thread_index]
                );
        }
 }
@@ -1493,9 +1503,51 @@
        VecAddf(insetCos[2], insetCos[2], cent);
 }
 
-/**/
-static void project_paint_face_init(ProjectPaintState *ps, int bucket_index, 
int face_index, float bucket_bounds[4], ImBuf *ibuf)
+static void rect_to_uvspace(
+               ProjectPaintState *ps, float bucket_bounds[4],
+               float *v1coSS, float *v2coSS, float *v3coSS,
+               float *uv1co, float *uv2co, float *uv3co,
+               float bucket_bounds_uv[4][2]
+       )
 {
+       float uv[2];
+       float w[3];
+       
+       /* get the UV space bounding box */
+       uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT];
+       uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
+       if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, 
uv, w);    
+       else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);       
+       bucket_bounds_uv[0][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
+       bucket_bounds_uv[0][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
+       
+       //uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT]; // set above
+       uv[1] = bucket_bounds[PROJ_BUCKET_TOP];
+       if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, 
uv, w);
+       else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
+       bucket_bounds_uv[1][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
+       bucket_bounds_uv[1][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
+       
+       
+       uv[0] = bucket_bounds[PROJ_BUCKET_LEFT];
+       //uv[1] = bucket_bounds[PROJ_BUCKET_TOP]; // set above
+       if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, 
uv, w);
+       else                    BarycentricWeightsPersp2f(v1coSS, v2coSS, 
v3coSS, uv, w);
+       bucket_bounds_uv[2][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
+       bucket_bounds_uv[2][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2];
+       
+       //uv[0] = bucket_bounds[PROJ_BUCKET_LEFT]; // set above
+       uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
+       if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, v3coSS, 
uv, w);
+       else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
+       bucket_bounds_uv[3][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + uv3co[0]*w[2];
+       bucket_bounds_uv[3][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + uv3co[1]*w[2]; 
+}
+
+
+/* initialize pixels from this face where it intersects with the bucket_index, 
initialize pixels for removing seams */
+static void project_paint_face_init(ProjectPaintState *ps, int thread_index, 
int bucket_index, int face_index, int image_index, float bucket_bounds[4], 
ImBuf *ibuf)
+{
        /* Projection vars, to get the 3D locations into screen space  */
        
        MFace *mf = ps->dm_mface + face_index;
@@ -1508,7 +1560,7 @@
        
        int min_px[2], max_px[2]; /* UV Bounds converted to int's for pixel */
        int min_px_tf[2], max_px_tf[2]; /* UV Bounds converted to int's for 
pixel */
-       int min_px_bucket[2][2], max_px_bucket[2][2]; /* Bucket Bounds 
converted to int's for pixel */
+       int min_px_bucket[2], max_px_bucket[2]; /* Bucket Bounds converted to 
int's for pixel */
        float *v1coSS, *v2coSS, *v3coSS, *v4coSS; /* vert co screen-space, 
these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
        float *v1co, *v2co, *v3co; /* vert co */
        float *vCo[4]; /* vertex screenspace coords */
@@ -1551,43 +1603,15 @@
                v2coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i2)) ];
                v3coSS = ps->projectVertScreenCos[ (*(&mf->v1 + i3)) ];
                
-               /* get the UV space bounding box */
-               uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT];
-               uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
-               if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, 
v3coSS, uv, w);    
-               else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);       
-               bucket_bounds_uv[0][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + 
uv3co[0]*w[2];
-               bucket_bounds_uv[0][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + 
uv3co[1]*w[2];
+               rect_to_uvspace(ps, bucket_bounds, v1coSS, v2coSS, v3coSS, 
uv1co, uv2co, uv3co, bucket_bounds_uv);
                
-               //uv[0] = bucket_bounds[PROJ_BUCKET_RIGHT]; // set above
-               uv[1] = bucket_bounds[PROJ_BUCKET_TOP];
-               if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, 
v3coSS, uv, w);
-               else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
-               bucket_bounds_uv[1][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + 
uv3co[0]*w[2];
-               bucket_bounds_uv[1][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + 
uv3co[1]*w[2];
-               
-               
-               uv[0] = bucket_bounds[PROJ_BUCKET_LEFT];
-               //uv[1] = bucket_bounds[PROJ_BUCKET_TOP]; // set above
-               if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, 
v3coSS, uv, w);
-               else                    BarycentricWeightsPersp2f(v1coSS, 
v2coSS, v3coSS, uv, w);
-               bucket_bounds_uv[2][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + 
uv3co[0]*w[2];
-               bucket_bounds_uv[2][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + 
uv3co[1]*w[2];
-               
-               //uv[0] = bucket_bounds[PROJ_BUCKET_LEFT]; // set above
-               uv[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
-               if (ps->projectIsOrtho) BarycentricWeights2f(v1coSS, v2coSS, 
v3coSS, uv, w);
-               else                                    
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
-               bucket_bounds_uv[3][0] = uv1co[0]*w[0] + uv2co[0]*w[1] + 
uv3co[0]*w[2];
-               bucket_bounds_uv[3][1] = uv1co[1]*w[0] + uv2co[1]*w[1] + 
uv3co[1]*w[2];
-               
                //printf("Bounds: %f | %f | %f | %f\n", bucket_bounds[0], 
bucket_bounds[1], bucket_bounds[2], bucket_bounds[3]);
 
                if (    uv_image_rect(uv1co, uv2co, uv3co, NULL, min_px_tf, 
max_px_tf, ibuf->x, ibuf->y, 0) && 
-                               uv_image_rect(bucket_bounds_uv[0], 
bucket_bounds_uv[1], bucket_bounds_uv[2], bucket_bounds_uv[3], 
min_px_bucket[i], max_px_bucket[i], ibuf->x, ibuf->y, 1) )
+                               uv_image_rect(bucket_bounds_uv[0], 
bucket_bounds_uv[1], bucket_bounds_uv[2], bucket_bounds_uv[3], min_px_bucket, 
max_px_bucket, ibuf->x, ibuf->y, 1) )
                {
                        
-                       uvpixel_rect_intersect(min_px, max_px, 
min_px_bucket[i], max_px_bucket[i], min_px_tf, max_px_tf);
+                       uvpixel_rect_intersect(min_px, max_px, min_px_bucket, 
max_px_bucket, min_px_tf, max_px_tf);
                        
                        /* clip face and */
 
@@ -1607,7 +1631,7 @@
                                                        
screen_px_from_persp(ps, uv, vCo[i1],vCo[i2],vCo[i3], uv1co,uv2co,uv3co, 
pixelScreenCo);
                                                }
                                                
-                                               project_paint_uvpixel_init(ps, 
ibuf, x,y, bucket_index, face_index, pixelScreenCo);
+                                               project_paint_uvpixel_init(ps, 
thread_index, ibuf, x,y, bucket_index, face_index, image_index, pixelScreenCo);
                                        }
                                }
                        }
@@ -1615,21 +1639,30 @@
        } while(i--);
 #ifndef PROJ_DEBUG_NOSEAMBLEED
        if (ps->projectSeamBleed > 0.0) {
+               int face_seam_flag;
                
-               int flag = ps->projectFaceSeamFlags[face_index];
+               if (ps->thread_tot > 1)
+                       BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could 
be modifying these vars */
                
+               face_seam_flag = ps->projectFaceSeamFlags[face_index];
+               
                /* are any of our edges un-initialized? */
-               if ((flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 || 
-                       (flag & (PROJ_FACE_SEAM2|PROJ_FACE_NOSEAM2))==0 || 
-                       (flag & (PROJ_FACE_SEAM3|PROJ_FACE_NOSEAM3))==0 || 
-                       (flag & (PROJ_FACE_SEAM4|PROJ_FACE_NOSEAM4))==0
+               if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 
|| 

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to