Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_jobs.c')
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c119
1 files changed, 99 insertions, 20 deletions
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 343b1f68c7f..3ebfac4928c 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -26,6 +26,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include <string.h>
+
#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
@@ -89,12 +91,14 @@ struct wmJob {
/* to prevent cpu overhead, use this one which only gets called when job really starts, not in thread */
void (*initjob)(void *);
/* this runs inside thread, and does full job */
- void (*startjob)(void *, short *stop, short *do_update);
+ void (*startjob)(void *, short *stop, short *do_update, float *progress);
/* update gets called if thread defines so, and max once per timerstep */
/* it runs outside thread, blocking blender, no drawing! */
void (*update)(void *);
/* free entire customdata, doesn't run in thread */
void (*free)(void *);
+ /* gets called when job is stopped, not in thread */
+ void (*endjob)(void *);
/* running jobs each have own timer */
double timestep;
@@ -107,6 +111,10 @@ struct wmJob {
void *owner;
int flag;
short suspended, running, ready, do_update, stop;
+ float progress;
+
+ /* for display in header, identification */
+ char name[128];
/* once running, we store this separately */
void *run_customdata;
@@ -117,18 +125,32 @@ struct wmJob {
};
+/* finds:
+ * 1st priority: job with same owner and name
+ * 2nd priority: job with same owner
+ */
+static wmJob *wm_job_find(wmWindowManager *wm, void *owner, char *name)
+{
+ wmJob *steve, *found=NULL;
+
+ for(steve= wm->jobs.first; steve; steve= steve->next)
+ if(steve->owner==owner) {
+ found= steve;
+ if (name && strcmp(steve->name, name)==0)
+ return steve;
+ }
+
+ return found;
+}
+
/* ******************* public API ***************** */
/* returns current or adds new job, but doesnt run it */
/* every owner only gets a single job, adding a new one will stop running stop and
when stopped it starts the new one */
-wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, int flag)
+wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, char *name, int flag)
{
- wmJob *steve;
-
- for(steve= wm->jobs.first; steve; steve= steve->next)
- if(steve->owner==owner)
- break;
+ wmJob *steve= wm_job_find(wm, owner, name);
if(steve==NULL) {
steve= MEM_callocN(sizeof(wmJob), "new job");
@@ -137,6 +159,7 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, int flag)
steve->win= win;
steve->owner= owner;
steve->flag= flag;
+ BLI_strncpy(steve->name, name, sizeof(steve->name));
}
return steve;
@@ -154,6 +177,26 @@ int WM_jobs_test(wmWindowManager *wm, void *owner)
return 0;
}
+float WM_jobs_progress(wmWindowManager *wm, void *owner)
+{
+ wmJob *steve= wm_job_find(wm, owner, NULL);
+
+ if (steve && steve->flag & WM_JOB_PROGRESS)
+ return steve->progress;
+
+ return 0.0;
+}
+
+char *WM_jobs_name(wmWindowManager *wm, void *owner)
+{
+ wmJob *steve= wm_job_find(wm, owner, NULL);
+
+ if (steve)
+ return steve->name;
+
+ return NULL;
+}
+
void WM_jobs_customdata(wmJob *steve, void *customdata, void (*free)(void *))
{
/* pending job? just free */
@@ -177,20 +220,22 @@ void WM_jobs_timer(wmJob *steve, double timestep, unsigned int note, unsigned in
}
void WM_jobs_callbacks(wmJob *steve,
- void (*startjob)(void *, short *, short *),
+ void (*startjob)(void *, short *, short *, float *),
void (*initjob)(void *),
- void (*update)(void *))
+ void (*update)(void *),
+ void (*endjob)(void *))
{
steve->startjob= startjob;
steve->initjob= initjob;
steve->update= update;
+ steve->endjob= endjob;
}
static void *do_job_thread(void *job_v)
{
wmJob *steve= job_v;
- steve->startjob(steve->run_customdata, &steve->stop, &steve->do_update);
+ steve->startjob(steve->run_customdata, &steve->stop, &steve->do_update, &steve->progress);
steve->ready= 1;
return NULL;
@@ -244,6 +289,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *steve)
steve->stop= 0;
steve->ready= 0;
+ steve->progress= 0.0;
BLI_init_threads(&steve->threads, do_job_thread, 1);
BLI_insert_thread(&steve->threads, steve);
@@ -266,6 +312,9 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *steve)
/* signal job to end */
steve->stop= 1;
BLI_end_threads(&steve->threads);
+
+ if(steve->endjob)
+ steve->endjob(steve->run_customdata);
}
if(steve->wt)
@@ -290,28 +339,32 @@ void WM_jobs_stop_all(wmWindowManager *wm)
}
-/* signal job(s) from this owner to stop, timer is required to get handled */
-void WM_jobs_stop(wmWindowManager *wm, void *owner)
+/* signal job(s) from this owner or callback to stop, timer is required to get handled */
+void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob)
{
wmJob *steve;
for(steve= wm->jobs.first; steve; steve= steve->next)
- if(steve->owner==owner)
+ if(steve->owner==owner || steve->startjob==startjob)
if(steve->running)
steve->stop= 1;
}
/* actually terminate thread and job timer */
-void WM_jobs_kill(wmWindowManager *wm, void *owner)
+void WM_jobs_kill(wmWindowManager *wm, void *owner, void *startjob)
{
wmJob *steve;
- for(steve= wm->jobs.first; steve; steve= steve->next)
- if(steve->owner==owner)
- break;
-
- if (steve)
- wm_jobs_kill_job(wm, steve);
+ steve= wm->jobs.first;
+ while(steve) {
+ if(steve->owner==owner || steve->startjob==startjob) {
+ wmJob* bill = steve;
+ steve= steve->next;
+ wm_jobs_kill_job(wm, bill);
+ } else {
+ steve= steve->next;
+ }
+ }
}
@@ -332,6 +385,9 @@ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt)
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
wmJob *steve= wm->jobs.first, *stevenext;
+ float total_progress= 0.f;
+ float jobs_progress=0;
+
for(; steve; steve= stevenext) {
stevenext= steve->next;
@@ -347,10 +403,16 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
steve->update(steve->run_customdata);
if(steve->note)
WM_event_add_notifier(C, steve->note, NULL);
+
+ if (steve->flag & WM_JOB_PROGRESS)
+ WM_event_add_notifier(C, NC_WM|ND_JOB, NULL);
steve->do_update= 0;
}
if(steve->ready) {
+ if(steve->endjob)
+ steve->endjob(steve->run_customdata);
+
/* free own data */
steve->run_free(steve->run_customdata);
steve->run_customdata= NULL;
@@ -365,6 +427,8 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
if(steve->endnote)
WM_event_add_notifier(C, steve->endnote, NULL);
+ WM_event_add_notifier(C, NC_WM|ND_JOB, NULL);
+
/* new job added for steve? */
if(steve->customdata) {
WM_jobs_start(wm, steve);
@@ -377,6 +441,10 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
BLI_remlink(&wm->jobs, steve);
MEM_freeN(steve);
}
+ } else if (steve->flag & WM_JOB_PROGRESS) {
+ /* accumulate global progress for running jobs */
+ jobs_progress++;
+ total_progress += steve->progress;
}
}
else if(steve->suspended) {
@@ -384,5 +452,16 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
}
}
}
+
+ /* on file load 'winactive' can be NULL, possibly it should not happen but for now do a NULL check - campbell */
+ if(wm->winactive) {
+ /* if there are running jobs, set the global progress indicator */
+ if (jobs_progress > 0) {
+ float progress = total_progress / (float)jobs_progress;
+ WM_progress_set(wm->winactive, progress);
+ } else {
+ WM_progress_clear(wm->winactive);
+ }
+ }
}