Three-in-one commit:
[blender-staging.git] / source / blender / render / intern / source / pipeline.c
index 1cbe6273757ddf5ee31e4ef8f86958d5954df92c..5780b780b0f0d4b3bb3dfa30b7f99b8db28fbda8 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
+#include "BLI_threads.h"
 
 #include "PIL_time.h"
 #include "IMB_imbuf.h"
@@ -66,6 +67,7 @@
 #include "zbuf.h"
 
 #include "SDL_thread.h"
+#include "SDL_mutex.h"
 
 /* render flow
 
@@ -104,7 +106,7 @@ Render R;
 /* ********* alloc and free ******** */
 
 
-static SDL_mutex *malloc_lock= NULL;
+SDL_mutex *malloc_lock= NULL;
 
 void *RE_mallocN(int len, char *name)
 {
@@ -153,9 +155,11 @@ static void free_render_result(RenderResult *res)
        }
        
        if(res->rect32)
-               MEM_freeN(res->rect32);
+               RE_freeN(res->rect32);
+       if(res->rectz)
+               RE_freeN(res->rectz);
        if(res->rectf)
-               MEM_freeN(res->rectf);
+               RE_freeN(res->rectf);
        
        RE_freeN(res);
 }
@@ -168,6 +172,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
 {
        RenderResult *rr;
        RenderLayer *rl;
+       SceneRenderLayer *srl;
        int rectx, recty;
        
        rectx= partrct->xmax - partrct->xmin;
@@ -188,64 +193,95 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
        rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
        rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
        
-       /* check renderdata for amount of layers */
-       /* for now just one */
-       rl= RE_callocN(sizeof(RenderLayer), "new render layer");
-       BLI_addtail(&rr->layers, rl);
+       /* copy, so display callbacks can find out too */
+       rr->actlay= re->r.actlay;
        
-       rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
-       rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
+       /* check renderdata for amount of layers */
+       for(srl= re->r.layers.first; srl; srl= srl->next) {
+               rl= RE_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               strcpy(rl->name, srl->name);
+               rl->lay= srl->lay;
+               rl->layflag= srl->layflag;
+               rl->passflag= srl->passflag;
+               
+               rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "layer float rgba");
+               if(srl->passflag  & SCE_PASS_Z)
+                       rl->rectz= RE_callocN(rectx*recty*sizeof(float), "layer float Z");
+               
+       }
+       /* previewrender and envmap don't do layers, so we make a default one */
+       if(rr->layers.first==NULL) {
+               rl= RE_callocN(sizeof(RenderLayer), "new render layer");
+               BLI_addtail(&rr->layers, rl);
+               
+               rl->rectf= RE_callocN(rectx*recty*sizeof(float)*4, "prev/env float rgba");
+               rl->rectz= RE_callocN(rectx*recty*sizeof(float), "prev/env float Z");
+               
+               /* note, this has to be in sync with scene.c */
+               rl->lay= (1<<20) -1;
+               rl->layflag= 0x7FFF;    /* solid ztra halo strand */
+               rl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z;
+               
+       }
        
        return rr;
 }
 
 
 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
-/* no test happens here if it fits... */
+/* no test happens here if it fits... we also assume layers are in sync */
 /* is used within threads */
 static void merge_render_result(RenderResult *rr, RenderResult *rrpart)
 {
-       RenderLayer *rl= rr->layers.first;
-       RenderLayer *rlp= rrpart->layers.first;
+       RenderLayer *rl, *rlp;
        float *rf, *rfp;
-       int *rz=NULL, *rzp;
+       float *rz, *rzp;
        int y, height, len, copylen;
        
-       if(rlp->rectf==NULL) return;
-       if(rl->rectf==NULL) return;
-       
-       rzp= NULL; //rlp->rectz;
-       rfp= rlp->rectf;
-       
-       copylen=len= rrpart->rectx;
-       height= rrpart->recty;
-       
-       if(rrpart->crop) {      /* filters add pixel extra */
-               
-               if(rzp) rzp+= rrpart->crop + rrpart->crop*len;
-               if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len);
+       for(rl= rr->layers.first, rlp= rrpart->layers.first; rl && rlp; rl= rl->next, rlp= rlp->next) {
                
-               copylen= len-2*rrpart->crop;
-               height -= 2*rrpart->crop;
-               
-               //              rz= re->rectz+ (pa->miny + rrpart->crop)*rr->rectx+ (pa->minx+rrpart->crop);
-               rf= rl->rectf+ ( (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop) )*4;
-       }
-       else {
-               //              rz= re->rectz +  (pa->disprect.ymin*rr->rectx + pa->disprect.xmin);
-               rf= rl->rectf+ (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin)*4;
-       }
+               /* first combined and z pass */
+               if(rl->rectf && rlp->rectf) {
+                       int ofs;
+                       
+                       rzp= rlp->rectz;
+                       rfp= rlp->rectf;
+                       
+                       copylen=len= rrpart->rectx;
+                       height= rrpart->recty;
+                       
+                       if(rrpart->crop) {      /* filters add pixel extra */
+                               
+                               if(rzp) rzp+= rrpart->crop + rrpart->crop*len;
+                               if(rfp) rfp+= 4*(rrpart->crop + rrpart->crop*len);
+                               
+                               copylen= len-2*rrpart->crop;
+                               height -= 2*rrpart->crop;
+                               
+                               ofs= (rrpart->tilerect.ymin + rrpart->crop)*rr->rectx + (rrpart->tilerect.xmin+rrpart->crop);
+                               rz= rl->rectz+ ofs;
+                               rf= rl->rectf+ 4*ofs;
+                       }
+                       else {
+                               ofs= (rrpart->tilerect.ymin*rr->rectx + rrpart->tilerect.xmin);
+                               rz= rl->rectz+ ofs;
+                               rf= rl->rectf+ 4*ofs;
+                       }
 
-       for(y=0; y<height; y++) {
-               if(rzp) {
-                       memcpy(rz, rzp, 4*copylen);
-                       rz+= rr->rectx;
-                       rzp+= len;
-               }
-               if(rfp) {
-                       memcpy(rf, rfp, 16*copylen);
-                       rf+= 4*rr->rectx;
-                       rfp+= 4*len;
+                       for(y=0; y<height; y++) {
+                               if(rzp) {
+                                       memcpy(rz, rzp, 4*copylen);
+                                       rz+= rr->rectx;
+                                       rzp+= len;
+                               }
+                               if(rfp) {
+                                       memcpy(rf, rfp, 16*copylen);
+                                       rf+= 4*rr->rectx;
+                                       rfp+= 4*len;
+                               }
+                       }
                }
        }
 }
@@ -278,22 +314,25 @@ RenderResult *RE_GetResult(Render *re)
 void RE_GetResultImage(Render *re, RenderResult *rr)
 {
        memset(rr, sizeof(RenderResult), 0);
-       
+
        if(re && re->result) {
                RenderLayer *rl;
                
                rr->rectx= re->result->rectx;
                rr->recty= re->result->recty;
+               
                rr->rectf= re->result->rectf;
                rr->rectz= re->result->rectz;
                rr->rect32= re->result->rect32;
                
-               /* will become 'active' call */
-               rl= re->result->layers.first;
-               if(rr->rectf==NULL)
-                       rr->rectf= rl->rectf;
-               if(rr->rectz==NULL)
-                       rr->rectz= rl->rectz;   
+               /* active layer */
+               rl= BLI_findlink(&re->result->layers, re->r.actlay);
+               if(rl) {
+                       if(rr->rectf==NULL)
+                               rr->rectf= rl->rectf;
+                       if(rr->rectz==NULL)
+                               rr->rectz= rl->rectz;   
+               }
        }
 }
 
@@ -519,67 +558,7 @@ void RE_AddObject(Render *re, Object *ob)
        
 }
 
-/* ********** basic thread control API ************ */
-
-#define RE_MAX_THREAD 4
-
-typedef struct ThreadSlot {
-       RenderPart *part;
-       int avail;
-} ThreadSlot;
-
-static ThreadSlot threadslots[RE_MAX_THREAD];
-
-static void init_threadslots(int tot)
-{
-       int a;
-       
-       if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
-       else if(tot<1) tot= 1;
-       
-       for(a=0; a< RE_MAX_THREAD; a++) {
-               threadslots[a].part= NULL;
-               if(a<tot)
-                       threadslots[a].avail= 1;
-               else
-                       threadslots[a].avail= 0;
-       }
-}
-
-static int available_threadslots(void)
-{
-       int a, counter=0;
-       for(a=0; a< RE_MAX_THREAD; a++)
-               if(threadslots[a].avail)
-                       counter++;
-       return counter;
-}
-
-static void insert_threadslot(RenderPart *pa)
-{
-       int a;
-       for(a=0; a< RE_MAX_THREAD; a++) {
-               if(threadslots[a].avail) {
-                       threadslots[a].avail= 0;
-                       threadslots[a].part= pa;
-                       pa->thread= a;
-                       break;
-               }
-       }
-}
-
-static void remove_threadslot(RenderPart *pa)
-{
-       int a;
-       for(a=0; a< RE_MAX_THREAD; a++) {
-               if(threadslots[a].part==pa) {
-                       threadslots[a].avail= 1;
-                       threadslots[a].part= NULL;
-               }
-       }
-}
-
-/* ********** basic thread control API ************ */
+/* *************************************** */
 
 static int do_part_thread(void *pa_v)
 {
@@ -600,7 +579,6 @@ static int do_part_thread(void *pa_v)
        }
        
        pa->ready= 1;
-       remove_threadslot(pa);
        
        return 0;
 }
@@ -681,6 +659,7 @@ static RenderPart *find_nicest_part(Render *re)
 
 static void threaded_tile_processor(Render *re)
 {
+       ListBase threads;
        RenderPart *pa;
        int maxthreads=2, rendering=1, counter= 1;
        
@@ -690,7 +669,7 @@ static void threaded_tile_processor(Render *re)
                return;
        
        initparts(re);
-       init_threadslots(maxthreads);
+       BLI_init_threads(&threads, do_part_thread, maxthreads);
        
        /* assuming no new data gets added to dbase... */
        R= *re;
@@ -700,12 +679,12 @@ static void threaded_tile_processor(Render *re)
        while(rendering) {
                
                /* I noted that test_break() in a thread doesn't make ghost send ESC */
-               if(available_threadslots() && !re->test_break()) {
+               if(BLI_available_threads(&threads) && !re->test_break()) {
                        pa= find_nicest_part(re);
                        if(pa) {
-                               insert_threadslot(pa);
-                               pa->nr= counter++;      /* only for stats */
-                               SDL_CreateThread(do_part_thread, pa);
+                               pa->nr= counter++;      /* for nicest part, and for stats */
+                               pa->thread= BLI_available_thread_index(&threads);       /* sample index */
+                               BLI_insert_thread(&threads, pa);
                        }
                }
                else
@@ -716,6 +695,7 @@ static void threaded_tile_processor(Render *re)
                for(pa= re->parts.first; pa; pa= pa->next) {
                        if(pa->ready) {
                                if(pa->result) {
+                                       BLI_remove_thread(&threads, pa);
                                        re->display_draw(pa->result, NULL);
                                        free_render_result(pa->result);
                                        pa->result= NULL;
@@ -726,13 +706,14 @@ static void threaded_tile_processor(Render *re)
                }
                
                /* on break, wait for all slots to get freed */
-               if(re->test_break() && available_threadslots()==maxthreads)
+               if(re->test_break() && BLI_available_threads(&threads)==maxthreads)
                        rendering= 0;
                
        }
        
        if(malloc_lock) SDL_DestroyMutex(malloc_lock); malloc_lock= NULL;
        
+       BLI_end_threads(&threads);
        freeparts(re);
 }
 
@@ -787,7 +768,7 @@ static void do_render_final(Render *re, Scene *scene)
                /* first check if theres nodetree with render result */
                int do_render= ntreeCompositNeedsRender(scene->nodetree);
                /* but.. do we use nodes? */
-               if(scene->use_nodes==NULL) do_render= 1;
+               if(scene->use_nodes==0) do_render= 1;
                
                re->scene= scene;
                
@@ -802,6 +783,10 @@ static void do_render_final(Render *re, Scene *scene)
                        else
                                render_one_frame(re);
                }
+               
+               ntreeCompositTagRender(scene->nodetree);
+               ntreeCompositTagAnimated(scene->nodetree);
+               
                if(re->r.scemode & R_DOCOMP)
                        ntreeCompositExecTree(scene->nodetree, &re->r, 0);
        }