Nice goodie: Preview renders!

- Added new preview.blend, allowing super wide cinemascope previews
- Draws nicely blended inside widget type, rounded corners
- Preview now renders using all available cpus/cores.
- Uses - hopefully rock stable - method, which doesn't copy or 
  allocate anything for previews, but just uses render API calls.
- Multiple previews are possible! But, added provision in Jobs
  manager to only render one preview job at a time. If you start
  more preview jobs, they're suspended until it's their turn.

Bugfix: new buttons context code crashed when going full-window.

Tweaks are still needed for notifiers. I have to figure out still
how to retrieve SpaceButs button view types...
This commit is contained in:
Ton Roosendaal 2009-06-07 11:12:35 +00:00
parent 1bb8d745b9
commit a2f9ca3b3f
20 changed files with 15772 additions and 11899 deletions

File diff suppressed because it is too large Load Diff

@ -75,5 +75,6 @@ void ED_preview_free_dbase(void);
void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, int sizex, int sizey);
void ED_preview_draw(const struct bContext *C, void *idp, rcti *rect);
#endif

@ -462,7 +462,7 @@ void uiButSetNFunc (uiBut *but, uiButHandleNFunc func, void *argN, void *arg2)
void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg);
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(struct bContext *C, uiBlock *block));
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(const struct bContext *C, void *, struct rcti *rect));
/* Autocomplete
*

@ -662,12 +662,16 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
else if(block->panel)
ui_draw_aligned_panel(ar, &style, block, &rect);
if(block->drawextra) block->drawextra(C, block);
/* widgets */
for(but= block->buttons.first; but; but= but->next) {
ui_but_to_pixelrect(&rect, ar, block, but);
ui_draw_but(ar, &style, but, &rect);
/* temp? roundbox defines size/location of preview, and ID type */
if(but->type==ROUNDBOX)
if(block->drawextra)
block->drawextra(C, but->poin, &rect);
}
/* restore matrix */
@ -2968,7 +2972,7 @@ void uiBlockSetRenameFunc(uiBlock *block, uiButHandleRenameFunc func, void *arg1
}
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)())
void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(const bContext *C, void *idv, rcti *rect))
{
block->drawextra= func;
}

@ -255,7 +255,7 @@ struct uiBlock {
void *handle_func_arg;
/* extra draw function for custom blocks */
void (*drawextra)();
void (*drawextra)(const struct bContext *C, void *idv, rcti *rect);
int afterval, flag;

@ -33,6 +33,7 @@
#include "BKE_utildefines.h"
#include "ED_screen.h"
#include "ED_previewrender.h"
#include "RNA_access.h"
@ -1277,6 +1278,16 @@ uiLayout *uiTemplateGroup(uiLayout *layout, Object *ob, Group *group)
#define B_MATPRV 1
static void do_preview_buttons(bContext *C, void *arg, int event)
{
switch(event) {
case B_MATPRV:
WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
break;
}
}
void uiTemplatePreview(uiLayout *layout, ID *id)
{
uiLayout *row, *col;
@ -1294,8 +1305,12 @@ void uiTemplatePreview(uiLayout *layout, ID *id)
col= uiLayoutColumn(row, 0);
uiLayoutSetKeepAspect(col, 1);
uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, id, 0.0, 0.0, 0, 0, "");
/* extra draw is tied to roundbox for now */
uiBlockSetDrawExtraFunc(block, ED_preview_draw);
uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
if(GS(id->name) == ID_MA) {
ma= (Material*)id;

@ -88,6 +88,7 @@
#include "WM_types.h"
#include "ED_anim_api.h"
#include "ED_previewrender.h"
#include "ED_view3d.h"
#include "UI_interface.h"
@ -113,6 +114,7 @@ typedef struct ShaderPreview {
int sizex, sizey;
int pr_method;
} ShaderPreview;
@ -620,45 +622,43 @@ void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
}
}
/* is panel callback, supposed to be called with correct panel offset matrix */
void BIF_previewdraw(ScrArea *sa, uiBlock *block)
/* new UI convention: draw is in pixel space already. */
/* uses ROUNDBOX button in block to get the rect */
void ED_preview_draw(const bContext *C, void *idp, rcti *rect)
{
ARegion *ar= NULL; // XXX
ScrArea *sa= CTX_wm_area(C);
SpaceButs *sbuts= sa->spacedata.first;
short id_code= 0;
RenderResult rres;
int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
int ok= 0;
char name[32];
if(sbuts->lockpoin) {
ID *id= sbuts->lockpoin;
id_code= GS(id->name);
}
if (!sbuts->ri) {
sbuts->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
sbuts->ri->tottile = 10000;
}
if (sbuts->ri->rect==NULL) BIF_preview_changed(id_code);
else {
RenderInfo *ri= sbuts->ri;
int oldx= ri->pr_rectx, oldy= ri->pr_recty;
/* we now do scalable previews! */
set_previewrect(sa, ri);
if( ABS(oldx-ri->pr_rectx)<2 && ABS(oldy-ri->pr_recty)<2 ) {
/* restore old values for drawing! */
ri->pr_rectx= oldx;
ri->pr_recty= oldy;
glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
sprintf(name, "Preview %p", sa);
RE_GetResultImage(RE_GetRender(name), &rres);
if(rres.rectf) {
if(rres.rectx==newx && rres.recty==newy) {
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
glEnable(GL_BLEND);
glaDrawPixelsSafe(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_FLOAT, rres.rectf);
ok= 1;
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else {
MEM_freeN(ri->rect);
ri->rect= NULL;
sbuts->ri->curtile= 0;
}
end_previewrect(ar);
}
if(sbuts->ri->curtile==0) BIF_preview_changed(id_code);
/* check for spacetype... */
if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) {
sbuts->preview= 0;
ok= 0;
}
if(ok==0) {
printf("added shader job\n");
ED_preview_shader_job(C, sa, idp, newx, newy);
}
}
@ -975,7 +975,7 @@ void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block)
/* **************************** New preview system ****************** */
/* called by renderer, sets job update value */
/* inside thread, called by renderer, sets job update value */
static void shader_preview_draw(void *spv, RenderResult *rr, volatile struct rcti *rect)
{
ShaderPreview *sp= spv;
@ -991,12 +991,20 @@ static int shader_preview_break(void *spv)
return *(sp->stop);
}
/* outside thread, called before redraw notifiers, it moves finished preview over */
static void shader_preview_updatejob(void *spv)
{
// ShaderPreview *sp= spv;
}
/* runs inside thread */
static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
{
ShaderPreview *sp= customdata;
Render *re;
Scene *sce;
float oldlens;
char name [32];
sp->stop= stop;
@ -1010,35 +1018,39 @@ static void shader_preview_startjob(void *customdata, short *stop, short *do_upd
re= RE_GetRender(name);
/* full refreshed render from first tile */
if(re==NULL) {
if(re==NULL)
re= RE_NewRender(name);
/* sce->r gets copied in RE_InitState! */
if(sp->pr_method==PR_DO_RENDER) {
sce->r.scemode |= R_NODE_PREVIEW;
sce->r.scemode &= ~R_NO_IMAGE_LOAD;
}
else { /* PR_ICON_RENDER */
sce->r.scemode &= ~R_NODE_PREVIEW;
sce->r.scemode |= R_NO_IMAGE_LOAD;
}
/* allocates render result */
RE_InitState(re, NULL, &sce->r, sp->sizex, sp->sizey, NULL);
/* sce->r gets copied in RE_InitState! */
if(sp->pr_method==PR_DO_RENDER) {
sce->r.scemode |= R_NODE_PREVIEW;
sce->r.scemode &= ~R_NO_IMAGE_LOAD;
sce->r.mode |= R_OSA;
}
else { /* PR_ICON_RENDER */
sce->r.scemode &= ~R_NODE_PREVIEW;
sce->r.scemode |= R_NO_IMAGE_LOAD;
}
/* allocates or re-uses render result */
RE_InitState(re, NULL, &sce->r, sp->sizex, sp->sizey, NULL);
/* callbacs are cleared on GetRender() */
if(sp->pr_method==PR_DO_RENDER) {
RE_display_draw_cb(re, sp, shader_preview_draw);
RE_test_break_cb(re, sp, shader_preview_break);
}
/* lens adjust */
oldlens= ((Camera *)sce->camera->data)->lens;
((Camera *)sce->camera->data)->lens *= (float)sp->sizey/(float)sp->sizex;
/* entire cycle for render engine */
RE_SetCamera(re, sce->camera);
RE_Database_FromScene(re, sce, 1);
RE_TileProcessor(re, 0, 0); // actual render engine
RE_TileProcessor(re, 0, 1); // actual render engine
RE_Database_Free(re);
((Camera *)sce->camera->data)->lens= oldlens;
*do_update= 1;
/* handle results */
@ -1047,6 +1059,12 @@ static void shader_preview_startjob(void *customdata, short *stop, short *do_upd
// ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
//RE_ResultGet32(re, ri->rect);
}
else {
/* validate owner */
//if(ri->rect==NULL)
// ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
//RE_ResultGet32(re, ri->rect);
}
/* unassign the pointers, reset vars */
preview_prepare_scene(sp->scene, GS(sp->id->name), NULL);
@ -1076,9 +1094,9 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, in
/* setup job */
WM_jobs_customdata(steve, sp, shader_preview_free);
WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL);
WM_jobs_callbacks(steve, shader_preview_startjob, NULL, NULL);
WM_jobs_callbacks(steve, shader_preview_startjob, NULL, shader_preview_updatejob);
WM_jobs_start(steve);
WM_jobs_start(CTX_wm_manager(C), steve);
}

@ -32,38 +32,6 @@
/* internal exports only */
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
/* stores rendered preview - is also used for icons */
typedef struct RenderInfo {
int pr_rectx;
int pr_recty;
short curtile, tottile, status;
rcti disprect; /* storage for view3d preview rect */
unsigned int* rect;
struct Render *re; /* persistant render */
} RenderInfo;
/* ri->status */
#define PR_DBASE 1
#define PR_DISPRECT 2
#define PR_PROJECTED 4
#define PR_ROTATED 8
/* Render the preview
pr_method:
- PR_DRAW_RENDER: preview is rendered and drawn, as indicated by called context (buttons panel)
- PR_ICON_RENDER: the preview is not drawn and the function is not dynamic,
so no events are processed. Hopefully fast enough for at least 32x32
- PR_DO_RENDER: preview is rendered, not drawn, but events are processed for afterqueue,
in use for node editor now.
*/
#define PR_DRAW_RENDER 0
#define PR_ICON_RENDER 1
#define PR_DO_RENDER 2
#endif /* PREVIEWRENDER_INTERN_H */

@ -2541,7 +2541,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
// BKE_report in render!
// RE_error_cb(re, error_cb);
WM_jobs_start(steve);
WM_jobs_start(CTX_wm_manager(C), steve);
G.afbreek= 0;

@ -309,7 +309,7 @@ static int screencast_exec(bContext *C, wmOperator *op)
WM_jobs_timer(steve, 0.1, 0, NC_SCREEN|ND_SCREENCAST);
WM_jobs_callbacks(steve, screenshot_startjob, NULL, screenshot_updatejob);
WM_jobs_start(steve);
WM_jobs_start(CTX_wm_manager(C), steve);
WM_event_add_notifier(C, NC_SCREEN|ND_SCREENCAST, screen);

@ -389,7 +389,7 @@ static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
{
SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
ButsContextPath *path= sbuts->path;
ButsContextPath *path= sbuts?sbuts->path:NULL;
if(!path)
return 0;

@ -240,15 +240,21 @@ static void buttons_header_area_draw(const bContext *C, ARegion *ar)
}
/* reused! */
static void buttons_area_listener(ARegion *ar, wmNotifier *wmn)
static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
{
SpaceButs *sbuts= sa->spacedata.first;
/* context changes */
switch(wmn->category) {
case NC_SCENE:
switch(wmn->data) {
case ND_FRAME:
ED_area_tag_redraw(sa);
break;
case ND_OB_ACTIVE:
ED_region_tag_redraw(ar);
ED_area_tag_redraw(sa);
sbuts->preview= 1;
break;
}
break;
@ -258,10 +264,25 @@ static void buttons_area_listener(ARegion *ar, wmNotifier *wmn)
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
case ND_GEOM_SELECT:
ED_region_tag_redraw(ar);
ED_area_tag_redraw(sa);
break;
}
break;
case NC_MATERIAL:
ED_area_tag_redraw(sa);
switch(wmn->data) {
case ND_SHADING:
case ND_SHADING_DRAW:
/* currently works by redraws... if preview is set, it (re)starts job */
sbuts->preview= 1;
printf("shader notifier \n");
break;
}
break;
case NC_WORLD:
ED_area_tag_redraw(sa);
sbuts->preview= 1;
}
}
@ -279,6 +300,7 @@ void ED_spacetype_buttons(void)
st->duplicate= buttons_duplicate;
st->operatortypes= buttons_operatortypes;
st->keymap= buttons_keymap;
st->listener= buttons_area_listener;
st->context= buttons_context;
/* regions: main window */
@ -286,7 +308,6 @@ void ED_spacetype_buttons(void)
art->regionid = RGN_TYPE_WINDOW;
art->init= buttons_main_area_init;
art->draw= buttons_main_area_draw;
art->listener= buttons_area_listener;
art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@ -300,7 +321,6 @@ void ED_spacetype_buttons(void)
art->init= buttons_header_area_init;
art->draw= buttons_header_area_draw;
art->listener= buttons_area_listener;
BLI_addhead(&st->regiontypes, art);
/* regions: channels */

@ -183,7 +183,7 @@ void snode_composite_job(const bContext *C, ScrArea *sa)
WM_jobs_timer(steve, 0.1, NC_SCENE, NC_SCENE|ND_COMPO_RESULT);
WM_jobs_callbacks(steve, compo_startjob, compo_initjob, compo_updatejob);
WM_jobs_start(steve);
WM_jobs_start(CTX_wm_manager(C), steve);
}

@ -121,7 +121,7 @@ typedef struct SpaceButs {
struct RenderInfo *ri;
short cursens, curact;
short align, pad; /* align for panels */
short align, preview; /* align for panels, preview is signal to refresh */
View2D v2d; /* depricated, copied to region */
short mainb, menunr; /* texnr and menunr have to remain shorts */

@ -744,6 +744,7 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "amb");
RNA_def_property_range(prop, 0, 1);
RNA_def_property_ui_text(prop, "Ambient", "Amount of global ambient color the material receives.");
RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
prop= RNA_def_property(srna, "emit", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0, 2);
@ -752,6 +753,7 @@ void RNA_def_material(BlenderRNA *brna)
prop= RNA_def_property(srna, "translucency", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0, 1);
RNA_def_property_ui_text(prop, "Translucency", "Amount of diffuse shading on the back side.");
RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
prop= RNA_def_property(srna, "cubic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shade_flag", MA_CUBIC);
@ -775,12 +777,14 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "shad_alpha");
RNA_def_property_range(prop, 0.001, 1);
RNA_def_property_ui_text(prop, "Shadow Casting Alpha", "Shadow casting alpha, only in use for Irregular Shadowbuffer.");
RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
prop= RNA_def_property(srna, "light_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "group");
RNA_def_property_struct_type(prop, "Group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Light Group", "Limit lighting to lamps in this Group.");
RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL);
/* flags */

@ -34,6 +34,8 @@
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "WM_types.h"
#ifdef RNA_RUNTIME
static PointerRNA rna_World_ambient_occlusion_get(PointerRNA *ptr)
@ -348,11 +350,13 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "horr");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Horizon Color", "Color at the horizon.");
RNA_def_property_update(prop, NC_WORLD, NULL);
prop= RNA_def_property(srna, "zenith_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "zenr");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Zenith Color", "Color at the zenith.");
RNA_def_property_update(prop, NC_WORLD, NULL);
prop= RNA_def_property(srna, "ambient_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "ambr");
@ -374,6 +378,7 @@ void RNA_def_world(BlenderRNA *brna)
prop= RNA_def_property(srna, "blend_sky", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYBLEND);
RNA_def_property_ui_text(prop, "Blend Sky", "Renders background with natural progression from horizon to zenith.");
RNA_def_property_update(prop, NC_WORLD, NULL);
prop= RNA_def_property(srna, "paper_sky", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYPAPER);
@ -382,6 +387,7 @@ void RNA_def_world(BlenderRNA *brna)
prop= RNA_def_property(srna, "real_sky", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYREAL);
RNA_def_property_ui_text(prop, "Real Sky", "Renders background with a real horizon.");
RNA_def_property_update(prop, NC_WORLD, NULL);
/* physics */
prop= RNA_def_property(srna, "physics_engine", PROP_ENUM, PROP_NONE);

@ -1120,11 +1120,17 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy
/* always call, checks for gamma, gamma tables and jitter too */
make_sample_tables(re);
/* make empty render result, so display callbacks can initialize */
RE_FreeRenderResult(re->result);
re->result= MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx= re->rectx;
re->result->recty= re->recty;
/* if preview render, we try to keep old result */
if(re->result && (re->r.scemode & R_NODE_PREVIEW) &&
re->result->rectx==re->rectx && re->result->recty==re->recty);
else {
/* make empty render result, so display callbacks can initialize */
RE_FreeRenderResult(re->result);
re->result= MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx= re->rectx;
re->result->recty= re->recty;
}
/* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */
re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx);

@ -207,7 +207,7 @@ void WM_jobs_callbacks(struct wmJob *,
void (*initjob)(void *),
void (*update)(void *));
void WM_jobs_start(struct wmJob *);
void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *);
void WM_jobs_stop(struct wmWindowManager *wm, void *owner);
void WM_jobs_stop_all(struct wmWindowManager *wm);

@ -157,6 +157,7 @@ typedef struct wmNotifier {
#define NC_IMAGE (10<<24)
#define NC_BRUSH (11<<24)
#define NC_TEXT (12<<24)
#define NC_WORLD (13<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000

@ -107,7 +107,7 @@ struct wmJob {
/* internal */
void *owner;
short running, ready, do_update, stop;
short suspended, running, ready, do_update, stop;
/* once running, we store this separately */
void *run_customdata;
@ -121,6 +121,8 @@ struct wmJob {
/* ******************* 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)
{
wmJob *steve;
@ -195,7 +197,26 @@ static void *do_job_thread(void *job_v)
return NULL;
}
void WM_jobs_start(wmJob *steve)
/* dont allow same startjob to be executed twice */
static void wm_jobs_test_suspend(wmWindowManager *wm, wmJob *test)
{
wmJob *steve;
for(steve= wm->jobs.first; steve; steve= steve->next)
if(steve!=test)
if(steve->running)
if(steve->startjob==test->startjob)
break;
if(steve)
test->suspended= 1;
else
test->suspended= 0;
}
/* if job running, the same owner gave it a new job */
/* if different owner starts existing startjob, it suspends itself */
void WM_jobs_start(wmWindowManager *wm, wmJob *steve)
{
if(steve->running) {
/* signal job to end and restart */
@ -204,20 +225,24 @@ void WM_jobs_start(wmJob *steve)
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;
wm_jobs_test_suspend(wm, steve);
if(steve->initjob)
steve->initjob(steve->run_customdata);
BLI_init_threads(&steve->threads, do_job_thread, 1);
BLI_insert_thread(&steve->threads, steve);
if(steve->suspended==0) {
/* 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;
if(steve->initjob)
steve->initjob(steve->run_customdata);
BLI_init_threads(&steve->threads, do_job_thread, 1);
BLI_insert_thread(&steve->threads, steve);
// printf("job started\n");
// printf("job started\n");
}
/* restarted job has timer already */
if(steve->wt==NULL)
@ -269,6 +294,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
for(; steve; steve= steve->next) {
if(evt->customdata==steve->wt) {
/* running threads */
if(steve->threads.first) {
@ -298,7 +324,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
/* new job added for steve? */
if(steve->customdata) {
WM_jobs_start(steve);
WM_jobs_start(wm, steve);
}
else {
WM_event_remove_window_timer(steve->win, steve->wt);
@ -310,6 +336,10 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
}
}
}
else if(steve->suspended) {
WM_jobs_start(wm, steve);
}
return OPERATOR_FINISHED;
}
}