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:
authorTon Roosendaal <ton@blender.org>2009-01-22 17:59:49 +0300
committerTon Roosendaal <ton@blender.org>2009-01-22 17:59:49 +0300
commit9cc59fb0c329bb788defe9c56b69d0919caaba96 (patch)
treef6f1c48441ba6de4f2ff1faf19a0540ce1dc6ba5 /source/blender/windowmanager
parenta017982074b3b11fd0157d8d604e02858411db70 (diff)
2.5
Added WM Jobs manager - WM can manage threaded jobs for you; just provide a couple of components to get it work: - customdata, free callback for it - timer step, notifier code - start callback, update callback - Once started, each job runs an own timer, and will for every time step check necessary updates, or close the job when ready. - No drawing happens in jobs, that's for notifiers! - Every job stores an owner pointer, and based on this owner it will prevent multiple jobs to enter the stack. Instead it will re-use a running job, signal it to stop and allow caller to re-initialize it even. - Check new wm_jobs.c for more explanation. Jobs API is still under construction. Fun: BLI_addtail(&wm->jobs, steve); :) Put Node shader previews back using wmJobs - Preview calculating is now fully threaded (1 thread still) - Thanks to new event system + notifiers, you can see previews update even while dragging sliders! - Currently it only starts when you change a node setting. Warning: the thread render shares Node data, so don't delete nodes while it renders! This topic is on the todo to make safe. Also: - bug in region initialize (do_versions) showed channel list in node editor wrong. - flagged the channel list 'hidden' now, it was really in the way! This is for later to work on anyway. - recoded Render API callbacks so it gets handlers passed on, no globals to use anymore, remember? - previewrender code gets now so much nicer! Will remove a lot of stuff from code soon.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h17
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c7
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c270
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c4
-rw-r--r--source/blender/windowmanager/wm.h4
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
7 files changed, 301 insertions, 5 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index d7559eac306..13104b58a04 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -36,9 +36,13 @@ struct IDProperty;
struct wmEvent;
struct wmEventHandler;
struct wmGesture;
+struct wmJob;
+struct wmNotifier;
struct rcti;
struct PointerRNA;
+typedef struct wmJob wmJob;
+
/* general API */
void WM_setprefsize (int stax, int stay, int sizx, int sizy);
@@ -168,5 +172,18 @@ void wmOrtho2 (float x1, float x2, float y1, float y2);
void WM_set_framebuffer_index_color(int index);
int WM_framebuffer_to_index(unsigned int col);
+ /* threaded Jobs Manager */
+
+struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void *owner);
+
+void WM_jobs_customdata(struct wmJob *, void *customdata, void (*free)(void *));
+void WM_jobs_timer(struct wmJob *, double timestep, unsigned int note);
+void WM_jobs_callbacks(struct wmJob *,
+ void (*startjob)(void *, short *, short *),
+ void (*listener)(struct wmJob *, struct wmNotifier *),
+ void (*update)(void *));
+
+void WM_jobs_start(struct wmJob *);
+
#endif /* WM_API_H */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 69e974e3863..6fc67242d69 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -517,7 +517,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
static int wm_event_always_pass(wmEvent *event)
{
/* some events we always pass on, to ensure proper communication */
- return ELEM4(event->type, TIMER, TIMER0, TIMER1, TIMER2);
+ return ELEM5(event->type, TIMER, TIMER0, TIMER1, TIMER2, TIMERJOBS);
}
/* Warning: this function removes a modal handler, when finished */
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 4f8e84df08c..dc36cf2d62c 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -82,6 +82,7 @@
#include "wm_files.h"
#include "wm_window.h"
+#include "ED_previewrender.h"
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_util.h"
@@ -142,7 +143,7 @@ void WM_init(bContext *C)
sound_init_listener();
// init_node_butfuncs();
-// XXX BIF_preview_init_dbase();
+ ED_preview_init_dbase();
GPU_extensions_init();
@@ -215,7 +216,8 @@ void WM_exit(bContext *C)
#endif
// fastshade_free_render(); /* shaded view */
- free_blender(); /* blender.c, does entire library */
+ ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */
+ free_blender(); /* blender.c, does entire library and spacetypes */
// free_matcopybuf();
// free_ipocopybuf();
free_actcopybuf();
@@ -260,7 +262,6 @@ void WM_exit(bContext *C)
UI_exit();
BLI_freelistN(&U.themes);
-// XXX BIF_preview_free_dbase();
RNA_exit();
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
new file mode 100644
index 00000000000..1f320df7587
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -0,0 +1,270 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_window.h"
+#include "wm_event_system.h"
+#include "wm_event_types.h"
+#include "wm.h"
+
+#include "ED_screen.h"
+
+#include "RNA_types.h"
+
+/* ********************** Threaded Jobs Manager ****************************** */
+
+/*
+Add new job
+- register in WM
+- configure callbacks
+
+Start or re-run job
+- if job running
+ - signal job to end
+ - add timer notifier to verify when it has ended, to start it
+- else
+ - start job
+ - add timer notifier to handle progress
+
+Stop job
+ - signal job to end
+ on end, job will tag itself as sleeping
+
+Remove job
+- signal job to end
+ on end, job will remove itself
+
+When job is done:
+- it puts timer to sleep (or removes?)
+
+ */
+
+struct wmJob {
+ struct wmJob *next, *prev;
+
+ /* job originating from, keep track of this when deleting windows */
+ wmWindow *win;
+
+ /* should store entire own context, for start, free or listeners */
+ void *customdata;
+ void (*startjob)(void *, short *stop, short *do_update);
+ void (*free)(void *);
+
+ /* running jobs each have own timer */
+ double timestep;
+ wmTimer *wt;
+ /* the notifier event timers should send */
+ unsigned int note;
+
+ /* managing */
+ void (*listener)(struct wmJob *, struct wmNotifier *);
+
+ /* update gets called if thread defines so, and max once per timerstep */
+ /* no drawing, send notifiers! */
+ void (*update)(void *);
+
+/* internal */
+ void *owner;
+ short running, ready, do_update, stop;
+
+ /* once running, we store this separately */
+ void *run_customdata;
+ void (*run_free)(void *);
+
+ /* we use BLI_threads api, but per job only 1 thread runs */
+ ListBase threads;
+
+};
+
+/* ******************* public API ***************** */
+
+/* returns current or adds new job, but doesnt run it */
+wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner)
+{
+ wmJob *steve;
+
+ for(steve= wm->jobs.first; steve; steve= steve->next)
+ if(steve->owner==owner)
+ break;
+
+ if(steve==NULL) {
+ steve= MEM_callocN(sizeof(wmJob), "new job");
+
+ BLI_addtail(&wm->jobs, steve);
+ steve->win= win;
+ steve->owner= owner;
+ }
+
+ return steve;
+}
+
+void WM_jobs_customdata(wmJob *steve, void *customdata, void (*free)(void *))
+{
+ /* pending job? just free */
+ if(steve->customdata)
+ steve->free(steve->customdata);
+
+ steve->customdata= customdata;
+ steve->free= free;
+
+ if(steve->running) {
+ /* signal job to end */
+ steve->stop= 1;
+ }
+}
+
+void WM_jobs_timer(wmJob *steve, double timestep, unsigned int note)
+{
+ steve->timestep = timestep;
+ steve->note = note;
+}
+
+void WM_jobs_callbacks(wmJob *steve,
+ void (*startjob)(void *, short *, short *),
+ void (*listener)(struct wmJob *, struct wmNotifier *),
+ void (*update)(void *))
+{
+ steve->startjob= startjob;
+ steve->listener= listener;
+ steve->update= update;
+}
+
+static void *do_job_thread(void *job_v)
+{
+ wmJob *steve= job_v;
+
+ steve->stop= steve->ready= 0;
+ steve->startjob(steve->run_customdata, &steve->stop, &steve->do_update);
+ steve->ready= 1;
+
+ return NULL;
+}
+
+void WM_jobs_start(wmJob *steve)
+{
+ if(steve->running) {
+ /* signal job to end and restart */
+ steve->stop= 1;
+ }
+ else {
+ if(steve->customdata && steve->startjob) {
+
+ /* copy to ensure proper free in end */
+ steve->run_customdata= steve->customdata;
+ steve->run_free= steve->free;
+ steve->free= NULL;
+ steve->customdata= NULL;
+ steve->running= 1;
+
+ BLI_init_threads(&steve->threads, do_job_thread, 1);
+ BLI_insert_thread(&steve->threads, steve);
+
+ /* restarted job has timer already */
+ if(steve->wt==NULL)
+ steve->wt= WM_event_add_window_timer(steve->win, TIMERJOBS, steve->timestep);
+ }
+ else printf("job fails, not initialized\n");
+ }
+}
+
+/* hardcoded to event TIMERJOBS */
+static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmJob *steve= wm->jobs.first;
+
+ for(; steve; steve= steve->next) {
+
+ if(evt->customdata==steve->wt) {
+ /* running threads */
+ if(steve->threads.first) {
+
+ if(steve->do_update) {
+ if(steve->update)
+ steve->update(steve->customdata);
+ if(steve->note)
+ WM_event_add_notifier(C, steve->note, NULL);
+ steve->do_update= 0;
+ }
+
+ if(steve->ready) {
+ /* free own data */
+ steve->run_free(steve->run_customdata);
+ steve->run_customdata= NULL;
+ steve->run_free= NULL;
+
+ steve->running= 0;
+ BLI_end_threads(&steve->threads);
+
+ /* new job added for steve? */
+ if(steve->customdata) {
+ WM_jobs_start(steve);
+ }
+ else {
+ WM_event_remove_window_timer(steve->win, steve->wt);
+ steve->wt= NULL;
+
+ /* remove steve */
+ BLI_remlink(&wm->jobs, steve);
+ MEM_freeN(steve);
+ }
+ }
+ }
+ return OPERATOR_FINISHED;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+void WM_OT_jobs_timer(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Jobs timer";
+ ot->idname= "WM_OT_jobs_timer";
+
+ /* api callbacks */
+ ot->invoke= wm_jobs_timer;
+
+ ot->poll= ED_operator_screenactive;
+
+}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 1ce6aaf837b..58f2be80922 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -874,6 +874,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_tweak_gesture);
WM_operatortype_append(WM_OT_open_recentfile);
WM_operatortype_append(WM_OT_open_mainfile);
+ WM_operatortype_append(WM_OT_jobs_timer);
WM_operatortype_append(WM_OT_save_as_mainfile);
}
@@ -882,6 +883,9 @@ void wm_window_keymap(wmWindowManager *wm)
{
ListBase *keymap= WM_keymap_listbase(wm, "Window", 0, 0);
+ /* items to make WM work */
+ WM_keymap_verify_item(keymap, "WM_OT_jobs_timer", TIMERJOBS, KM_ANY, KM_ANY, 0);
+
/* note, this doesn't replace existing keymap items */
WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", AKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
WM_keymap_verify_item(keymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index c063226b96f..ecb40f34174 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -59,5 +59,9 @@ void wm_gesture_draw(struct wmWindow *win);
int wm_gesture_evaluate(bContext *C, wmGesture *gesture);
void wm_gesture_tag_redraw(bContext *C);
+/* wm_jobs.h */
+void WM_OT_jobs_timer(struct wmOperatorType *ot);
+
+
#endif /* WM_H */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 6a8174b351a..41c451755fc 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -75,7 +75,7 @@
#define TIMER0 0x0111 /* timer event, slot for internal use */
#define TIMER1 0x0112 /* timer event, slot for internal use */
#define TIMER2 0x0113 /* timer event, slot for internal use */
-#define TIMER3 0x0114 /* timer event, slot for internal use */
+#define TIMERJOBS 0x0114 /* timer event, internal use */
/* standard keyboard */