a17c488f1c974eb39d83f445ab419e4d0ba182e4
[blender.git] / source / blender / editors / preview / previewrender.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /* global includes */
31
32 #include <stdlib.h>
33 #include <math.h>
34 #include <string.h>
35
36 #ifndef WIN32
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #endif   
41 #include "MEM_guardedalloc.h"
42
43 #include "BLO_readfile.h" 
44
45 #include "BLI_arithb.h"
46 #include "BLI_blenlib.h"
47
48 #include "DNA_texture_types.h"
49 #include "DNA_world_types.h"
50 #include "DNA_camera_types.h"
51 #include "DNA_image_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_node_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_lamp_types.h"
56 #include "DNA_space_types.h"
57 #include "DNA_view3d_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_screen_types.h"
60
61 #include "BKE_context.h"
62 #include "BKE_depsgraph.h"
63 #include "BKE_global.h"
64 #include "BKE_image.h"
65 #include "BKE_icons.h"
66 #include "BKE_library.h"
67 #include "BKE_main.h"
68 #include "BKE_texture.h"
69 #include "BKE_material.h"
70 #include "BKE_node.h"
71 #include "BKE_world.h"
72 #include "BKE_texture.h"
73 #include "BKE_utildefines.h"
74
75 #include "IMB_imbuf.h"
76 #include "IMB_imbuf_types.h"
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80
81 #include "PIL_time.h"
82
83 #include "RE_pipeline.h"
84
85 #include "GPU_material.h"
86
87 #include "WM_api.h"
88 #include "WM_types.h"
89
90 #include "ED_anim_api.h"
91 #include "ED_previewrender.h"
92 #include "ED_view3d.h"
93
94 #include "UI_interface.h"
95
96 #include "previewrender_intern.h"
97
98 #define PR_XMIN         10
99 #define PR_YMIN         5
100 #define PR_XMAX         200
101 #define PR_YMAX         195
102
103 /* XXX */
104 static int qtest() {return 0;}
105 /* XXX */
106
107 typedef struct ShaderPreview {
108         /* from wmJob */
109         void *owner;
110         short *stop, *do_update;
111         
112         Scene *scene;
113         ID *id;
114         
115         int sizex, sizey;
116         int pr_method;
117         
118 } ShaderPreview;
119
120
121 static void set_previewrect(ScrArea *sa, RenderInfo *ri)
122 {
123         ARegion *ar= NULL; // XXX
124         rctf viewplane;
125         
126         BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
127
128 //      ui_graphics_to_window_rct(ar->win, &viewplane, &ri->disprect);
129         
130         /* correction for gla draw */
131         BLI_translate_rcti(&ri->disprect, -ar->winrct.xmin, -ar->winrct.ymin);
132         
133         glMatrixMode(GL_PROJECTION);
134         glPushMatrix();
135         glMatrixMode(GL_MODELVIEW);
136         glPushMatrix();
137         
138         glaDefine2DArea(&ar->winrct);
139
140         ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
141         ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
142 }
143
144 static void end_previewrect(ARegion *ar)
145 {
146         glMatrixMode(GL_PROJECTION);
147         glPopMatrix();
148         glMatrixMode(GL_MODELVIEW);
149         glPopMatrix();
150         
151         // restore viewport / scissor which was set by glaDefine2DArea
152         glViewport(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
153         glScissor(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
154
155 }
156
157 /* unused now */
158 void draw_tex_crop(Tex *tex)
159 {
160         rcti rct;
161         int ret= 0;
162         
163         if(tex==0) return;
164         
165         if(tex->type==TEX_IMAGE) {
166                 if(tex->cropxmin==0.0f) ret++;
167                 if(tex->cropymin==0.0f) ret++;
168                 if(tex->cropxmax==1.0f) ret++;
169                 if(tex->cropymax==1.0f) ret++;
170                 if(ret==4) return;
171                 
172                 rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
173                 rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
174                 rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
175                 rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
176
177                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
178
179                 glColor3ub(0, 0, 0);
180                 glRecti(rct.xmin+1,  rct.ymin-1,  rct.xmax+1,  rct.ymax-1); 
181
182                 glColor3ub(255, 255, 255);
183                 glRecti(rct.xmin,  rct.ymin,  rct.xmax,  rct.ymax);
184
185                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);                      
186         }
187         
188 }
189
190 /* temporal abuse; if id_code is -1 it only does texture.... solve! */
191 void BIF_preview_changed(short id_code)
192 {
193 #if 0   
194         ScrArea *sa;
195         
196         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
197                 if(sa->spacetype==SPACE_BUTS) {
198                         SpaceButs *sbuts= sa->spacedata.first;
199                         if(sbuts->mainb==CONTEXT_SHADING) {
200                                 int tab= sbuts->tab[CONTEXT_SHADING];
201                                 if(tab==TAB_SHADING_MAT && (id_code==ID_MA || id_code==ID_TE)) {
202                                         if (sbuts->ri) sbuts->ri->curtile= 0;
203                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
204                                 }
205                                 else if(tab==TAB_SHADING_TEX && (id_code==ID_TE || id_code==-1)) {
206                                         if (sbuts->ri) sbuts->ri->curtile= 0;
207                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
208                                 }
209                                 else if(tab==TAB_SHADING_LAMP && (id_code==ID_LA || id_code==ID_TE)) {
210                                         if (sbuts->ri) sbuts->ri->curtile= 0;
211                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
212                                 }
213                                 else if(tab==TAB_SHADING_WORLD && (id_code==ID_WO || id_code==ID_TE)) {
214                                         if (sbuts->ri) sbuts->ri->curtile= 0;
215                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
216                                 }
217                         }
218                         else if (sbuts->ri) 
219                                 sbuts->ri->curtile= 0;  /* ensure changes always result in re-render when context is restored */
220                 }
221                 else if(sa->spacetype==SPACE_NODE) {
222                         SpaceNode *snode= sa->spacedata.first;
223                         if(snode->treetype==NTREE_SHADER && (id_code==ID_MA || id_code==ID_TE)) {
224                                 snode_tag_dirty(snode);
225                         }
226                 }
227                 else if(sa->spacetype==SPACE_VIEW3D) {
228                         View3D *vd= sa->spacedata.first;
229                         /* if is has a renderinfo, we consider that reason for signalling */
230                         if (vd->ri) {
231                                 vd->ri->curtile= 0;
232                                 addafterqueue(sa->win, RENDERPREVIEW, 1);
233                         }
234                 }
235         }
236
237         if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) {
238                 Object *ob;
239                 Material *ma;
240
241                 if(id_code == ID_WO) {
242                         for(ma=G.main->mat.first; ma; ma=ma->id.next) {
243                                 if(ma->gpumaterial.first) {
244                                         GPU_material_free(ma);
245                                 }
246                         }
247                 }
248                 else if(id_code == ID_LA) {
249                         for(ob=G.main->object.first; ob; ob=ob->id.next) {
250                                 if(ob->gpulamp.first) {
251                                         GPU_lamp_free(ob);
252                                 }
253                         }
254                 } else if(OBACT) {
255                         Object *ob = OBACT;
256
257                         ma= give_current_material(ob, ob->actcol);
258                         if(ma && ma->gpumaterial.first) {
259                                 GPU_material_free(ma);
260                         }
261                 }
262         }
263 #endif
264 }
265
266 /* *************************** Preview for buttons *********************** */
267
268 static Main *pr_main= NULL;
269
270 void ED_preview_init_dbase(void)
271 {
272         BlendFileData *bfd;
273         extern int datatoc_preview_blend_size;
274         extern char datatoc_preview_blend[];
275         
276         G.fileflags |= G_FILE_NO_UI;
277         bfd= BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, NULL);
278         if (bfd) {
279                 pr_main= bfd->main;
280                 
281                 MEM_freeN(bfd);
282         }
283         G.fileflags &= ~G_FILE_NO_UI;
284 }
285
286 void ED_preview_free_dbase(void)
287 {
288         if(pr_main)
289                 free_main(pr_main);
290 }
291
292 static Object *find_object(ListBase *lb, const char *name)
293 {
294         Object *ob;
295         for(ob= lb->first; ob; ob= ob->id.next)
296                 if(strcmp(ob->id.name+2, name)==0)
297                         break;
298         return ob;
299 }
300
301 /* call this with a pointer to initialize preview scene */
302 /* call this with NULL to restore assigned ID pointers in preview scene */
303 static Scene *preview_prepare_scene(Scene *scene, int id_type, ShaderPreview *sp)
304 {
305         Scene *sce;
306         Base *base;
307         ID *id= sp?sp->id:NULL;
308         
309         if(pr_main==NULL) return NULL;
310         
311         sce= pr_main->scene.first;
312         if(sce) {
313                 /* this flag tells render to not execute depsgraph or ipos etc */
314                 sce->r.scemode |= R_PREVIEWBUTS;
315                 /* set world always back, is used now */
316                 sce->world= pr_main->world.first;
317                 /* now: exposure copy */
318                 if(scene->world) {
319                         sce->world->exp= scene->world->exp;
320                         sce->world->range= scene->world->range;
321                 }
322                 
323                 sce->r.cfra= scene->r.cfra;
324                 
325                 if(id_type==ID_MA) {
326                         Material *mat= (Material *)id;
327                         
328                         if(id) {
329                                 init_render_material(mat, 0, NULL);             /* call that retrieves mode_l */
330                                 end_render_material(mat);
331                                 
332                                 /* turn on raytracing if needed */
333                                 if(mat->mode_l & (MA_RAYTRANSP|MA_RAYMIRROR))
334                                         sce->r.mode |= R_RAYTRACE;
335                                 if(mat->sss_flag & MA_DIFF_SSS)
336                                         sce->r.mode |= R_SSS;
337                                 
338                                 /* turn off fake shadows if needed */
339                                 /* this only works in a specific case where the preview.blend contains
340                                  * an object starting with 'c' which has a material linked to it (not the obdata)
341                                  * and that material has a fake shadow texture in the active texture slot */
342                                 for(base= sce->base.first; base; base= base->next) {
343                                         if(base->object->id.name[2]=='c') {
344                                                 Material *shadmat= give_current_material(base->object, base->object->actcol);
345                                                 if(shadmat) {
346                                                         if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
347                                                         else shadmat->septex |= 1;
348                                                 }
349                                         }
350                                 }
351
352                                 
353                                 if(sp->pr_method==PR_ICON_RENDER) {
354                                         if (mat->material_type == MA_TYPE_HALO) {
355                                                 sce->lay= 1<<MA_FLAT;
356                                         } 
357                                         else {
358                                                 sce->lay= 1<<MA_SPHERE_A;
359                                         }
360                                 }
361                                 else {
362                                         sce->lay= 1<<mat->pr_type;
363                                         if(mat->nodetree)
364                                                 ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
365                                 }
366                         }
367                         else {
368                                 sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
369                         }
370                         
371                         for(base= sce->base.first; base; base= base->next) {
372                                 if(base->object->id.name[2]=='p') {
373                                         if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL))
374                                                 assign_material(base->object, mat, base->object->actcol);
375                                 }
376                         }
377                 }
378                 else if(id_type==ID_TE) {
379                         Tex *tex= (Tex *)id;
380                         
381                         sce->lay= 1<<MA_TEXTURE;
382                         
383                         for(base= sce->base.first; base; base= base->next) {
384                                 if(base->object->id.name[2]=='t') {
385                                         Material *mat= give_current_material(base->object, base->object->actcol);
386                                         if(mat && mat->mtex[0]) {
387                                                 mat->mtex[0]->tex= tex;
388                                                 /* show alpha in this case */
389                                                 if(tex==NULL || (tex->flag & TEX_PRV_ALPHA)) {
390                                                         mat->mtex[0]->mapto |= MAP_ALPHA;
391                                                         mat->alpha= 0.0f;
392                                                 }
393                                                 else {
394                                                         mat->mtex[0]->mapto &= ~MAP_ALPHA;
395                                                         mat->alpha= 1.0f;
396                                                 }
397                                         }
398                                 }
399                         }
400                 }
401                 else if(id_type==ID_LA) {
402                         Lamp *la= (Lamp *)id;
403                         
404                         if(la && la->type==LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
405                                 sce->lay= 1<<MA_ATMOS;
406                                 sce->world= scene->world;
407                                 sce->camera= (Object *)find_object(&pr_main->object, "CameraAtmo");
408                         }
409                         else {
410                                 sce->lay= 1<<MA_LAMP;
411                                 sce->world= NULL;
412                                 sce->camera= (Object *)find_object(&pr_main->object, "Camera");
413                         }
414                         sce->r.mode &= ~R_SHADOW;
415                         
416                         for(base= sce->base.first; base; base= base->next) {
417                                 if(base->object->id.name[2]=='p') {
418                                         if(base->object->type==OB_LAMP)
419                                                 base->object->data= la;
420                                 }
421                         }
422                 }
423                 else if(id_type==ID_WO) {
424                         sce->lay= 1<<MA_SKY;
425                         sce->world= (World *)id;
426                 }
427                 
428                 return sce;
429         }
430         
431         return NULL;
432 }
433
434 void previewrender_progress(void *handle, RenderResult *rr, volatile rcti *renrect)
435 {
436         SpaceButs *sbuts= NULL; // XXX
437         RenderLayer *rl;
438         RenderInfo *ri= sbuts->ri;
439         float ofsx, ofsy;
440         
441         if(renrect) return;
442         
443         rl= rr->layers.first;
444         
445         ofsx= ri->disprect.xmin + rr->tilerect.xmin;
446         ofsy= ri->disprect.ymin + rr->tilerect.ymin;
447         
448         glDrawBuffer(GL_FRONT);
449         glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
450         bglFlush();
451         glDrawBuffer(GL_BACK);
452 }
453
454
455 /* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
456 void BIF_previewrender(Scene *scene, struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
457 {
458         SpaceButs *sbuts= NULL; // XXX
459         Render *re;
460         RenderStats *rstats;
461         Scene *sce;
462         int oldx= ri->pr_rectx, oldy= ri->pr_recty;
463         char name [32];
464         
465         if(ri->tottile && ri->curtile>=ri->tottile) return;
466         
467         /* check for return with a new event */
468         if(pr_method!=PR_ICON_RENDER && qtest()) {
469 //              if(area)
470 //                      addafterqueue(area->win, RENDERPREVIEW, 1);
471                 return;
472         }
473         
474         /* get the stuff from the builtin preview dbase */
475 //      sce= preview_prepare_scene(scene, ri, GS(id->name), id, pr_method);
476         if(sce==NULL) return;
477         
478         /* set drawing conditions OK */
479         if(area) {
480                 sbuts= area->spacedata.first;   /* needed for flag */
481                 
482                 set_previewrect(area, ri); // uses UImat
483                 
484                 /* because preview render size can differs */
485                 if(ri->rect && (oldx!=ri->pr_rectx || oldy!=ri->pr_recty)) {
486                         MEM_freeN(ri->rect);
487                         ri->rect= NULL;
488                         ri->curtile= 0;
489                 }
490         }
491         
492 // XXX  sprintf(name, "ButsPreview %d", area?area->win:0);
493         re= RE_GetRender(name);
494         
495         /* full refreshed render from first tile */
496         if(re==NULL || ri->curtile==0) {
497                 
498                 re= RE_NewRender(name);
499                 
500                 /* handle cases */
501                 if(pr_method==PR_DRAW_RENDER) {
502 //                      RE_display_draw_cb(re, previewrender_progress);
503 //                      RE_test_break_cb(re, qtest);
504                         sce->r.scemode |= R_NODE_PREVIEW;
505                         if(sbuts->flag & SB_PRV_OSA)
506                                 sce->r.mode |= R_OSA;
507                         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
508                 }
509                 else if(pr_method==PR_DO_RENDER) {
510 //                      RE_test_break_cb(re, qtest);
511                         sce->r.scemode |= R_NODE_PREVIEW;
512                         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
513                 }
514                 else {  /* PR_ICON_RENDER */
515                         sce->r.scemode &= ~R_NODE_PREVIEW;
516                         sce->r.scemode |= R_NO_IMAGE_LOAD;
517                 }
518                 
519                 /* allocates render result */
520                 RE_InitState(re, NULL, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
521                 
522                 /* enforce preview image clear */
523                 if(GS(id->name)==ID_MA) {
524                         Material *ma= (Material *)id;
525                         ntreeClearPreview(ma->nodetree);
526                 }
527         }
528         /* entire cycle for render engine */
529         RE_SetCamera(re, sce->camera);
530         RE_Database_FromScene(re, sce, 1);
531         RE_TileProcessor(re, ri->curtile, 0);   // actual render engine
532         RE_Database_Free(re);
533         
534         /* handle results */
535         if(pr_method==PR_ICON_RENDER) {
536                 if(ri->rect==NULL)
537                         ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
538                 RE_ResultGet32(re, ri->rect);
539         }
540         else {
541                 rstats= RE_GetStats(re);
542                 
543                 if(rstats->partsdone!=ri->curtile) {
544                         if(ri->rect==NULL)
545                                 ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
546                         RE_ResultGet32(re, ri->rect);
547                 }
548                 
549                 if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
550                         // allqueues
551                 }
552                 else {
553 //                      if(pr_method==PR_DRAW_RENDER && qtest())
554 //                              addafterqueue(area->win, RENDERPREVIEW, 1);
555                 }
556                 
557                 ri->curtile= rstats->partsdone;
558                 ri->tottile= rstats->totpart;
559         }
560
561         /* unassign the pointers, reset vars */
562 //      preview_prepare_scene(scene, ri, GS(id->name), NULL, 0);
563         
564 }
565
566
567 /* afterqueue call */
568 void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
569 {
570 //      ScrArea *sa= NULL; // XXX
571         ARegion *ar= NULL; // XXX
572         uiBlock *block;
573         struct ID* id = 0;
574 //      struct ID* idfrom = 0;
575         struct ID* idshow = 0;
576         Object *ob;
577         
578         if (!sbuts->ri) return;
579         
580         
581 //      block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
582         if(block==NULL) return;
583         
584         ob= ((scene->basact)? (scene->basact)->object: 0);
585         
586         /* we cant trust this global lockpoin.. for example with headerless window */
587 //      buttons_active_id(&id, &idfrom);
588         sbuts->lockpoin= id;
589         
590         if(sbuts->mainb==CONTEXT_SHADING) {
591                 int tab= TAB_SHADING_MAT; // XXX sbuts->tab[CONTEXT_SHADING];
592                 
593                 if(tab==TAB_SHADING_MAT) 
594                         idshow = sbuts->lockpoin;
595                 else if(tab==TAB_SHADING_TEX) 
596                         idshow = sbuts->lockpoin;
597                 else if(tab==TAB_SHADING_LAMP) {
598                         if(ob && ob->type==OB_LAMP) idshow= ob->data;
599                 }
600                 else if(tab==TAB_SHADING_WORLD)
601                         idshow = sbuts->lockpoin;
602         }
603         else if(sbuts->mainb==CONTEXT_OBJECT) {
604                 if(ob && ob->type==OB_LAMP) idshow = ob->data;
605         }
606         
607         if (idshow) {
608                 BKE_icon_changed(BKE_icon_getid(idshow));
609 //              uiPanelPush(block);
610 //              BIF_previewrender(scene, idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
611 //              uiPanelPop(block);
612                 end_previewrect(ar);
613         }
614         else {
615                 /* no active block to draw. But we do draw black if possible */
616                 if(sbuts->ri->rect) {
617                         memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
618                         sbuts->ri->tottile= 10000;
619 //                      addqueue(sa->win, REDRAW, 1);
620                 }
621                 return;
622         }
623 }
624
625 /* new UI convention: draw is in pixel space already. */
626 /* uses ROUNDBOX button in block to get the rect */
627 void ED_preview_draw(const bContext *C, void *idp, rcti *rect)
628 {
629         ScrArea *sa= CTX_wm_area(C);
630         SpaceButs *sbuts= sa->spacedata.first;
631         RenderResult rres;
632         int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
633         int ok= 0;
634         char name[32];
635         
636         sprintf(name, "Preview %p", sa);
637         RE_GetResultImage(RE_GetRender(name), &rres);
638
639         if(rres.rectf) {
640                 if(rres.rectx==newx && rres.recty==newy) {
641                         glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
642                         glEnable(GL_BLEND);
643                         
644                         glaDrawPixelsSafe(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_FLOAT, rres.rectf);
645                         ok= 1;
646                         
647                         glDisable(GL_BLEND);
648                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
649                 }
650         }
651         
652         /* check for spacetype... */
653         if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) {
654                 sbuts->preview= 0;
655                 ok= 0;
656         }
657         
658         if(ok==0) {
659                 printf("added shader job\n");
660                 ED_preview_shader_job(C, sa, idp, newx, newy);
661         }
662         
663 }
664
665 /* *************************** Preview for 3d window *********************** */
666
667 void view3d_previewrender_progress(RenderResult *rr, volatile rcti *renrect)
668 {
669 //      ScrArea *sa= NULL; // XXX
670 //      View3D *v3d= NULL; // XXX
671         RenderLayer *rl;
672         int ofsx, ofsy;
673         
674         if(renrect) return;
675         
676         rl= rr->layers.first;
677         
678         /* this case is when we render envmaps... */
679 //      if(rr->rectx > v3d->ri->pr_rectx || rr->recty > v3d->ri->pr_recty)
680 //              return;
681         
682 //      ofsx= v3d->ri->disprect.xmin + rr->tilerect.xmin;
683 //      ofsy= v3d->ri->disprect.ymin + rr->tilerect.ymin;
684         
685         glDrawBuffer(GL_FRONT);
686 //      glaDefine2DArea(&sa->winrct);
687         glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
688         bglFlush();
689         glDrawBuffer(GL_BACK);
690
691 }
692
693 void BIF_view3d_previewrender_signal(ScrArea *sa, short signal)
694 {
695 #if 0
696         View3D *v3d= sa->spacedata.first;
697         
698         /* this can be called from other window... solve! */
699         if(sa->spacetype!=SPACE_VIEW3D)
700                 return; // XXX
701            
702         if(v3d && v3d->ri) {
703                 RenderInfo *ri= v3d->ri;
704                 ri->status &= ~signal;
705                 ri->curtile= 0;
706                 //printf("preview signal %d\n", signal);
707                 if(ri->re && (signal & PR_DBASE))
708                         RE_Database_Free(ri->re);
709
710 //              addafterqueue(sa->win, RENDERPREVIEW, 1);
711         }
712 #endif
713 }
714
715 void BIF_view3d_previewrender_free(View3D *v3d)
716 {
717 #if 0
718         if(v3d->ri) {
719                 RenderInfo *ri= v3d->ri;
720                 if(ri->re) {
721 //                      printf("free render\n");
722                         RE_Database_Free(ri->re);
723                         RE_FreeRender(ri->re);
724                         ri->re= NULL;
725                 }
726                 if (v3d->ri->rect) MEM_freeN(v3d->ri->rect);
727                 MEM_freeN(v3d->ri);
728                 v3d->ri= NULL;
729         }
730 #endif
731 }
732
733 /* returns 1 if OK, do not call while in panel space!  */
734 static int view3d_previewrender_get_rects(ScrArea *sa, rctf *viewplane, RenderInfo *ri, float *clipsta, float *clipend, int *ortho, float *pixsize)
735 {
736         View3D *v3d= NULL; // XXX
737         RegionView3D *rv3d= NULL; // XXX
738         int rectx, recty;
739 //      uiBlock *block;
740         
741 //      block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
742 //      if(block==NULL) return 0;
743         
744         /* calculate preview rect size */
745 //      BLI_init_rctf(viewplane, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
746 //      uiPanelPush(block);
747 //      ui_graphics_to_window_rct(sa->win, viewplane, &ri->disprect);
748 //      uiPanelPop(block);
749         
750         /* correction for gla draw */
751 //      BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
752         
753         *ortho= get_view3d_viewplane(v3d, rv3d, sa->winx, sa->winy, viewplane, clipsta, clipend, pixsize);
754
755         rectx= ri->disprect.xmax - ri->disprect.xmin;
756         recty= ri->disprect.ymax - ri->disprect.ymin;
757         
758         if(rectx<4 || recty<4) return 0;
759         
760         if(ri->rect && (rectx!=ri->pr_rectx || recty!=ri->pr_recty)) {
761                 MEM_freeN(ri->rect);
762                 ri->rect= NULL;
763                 ri->curtile= 0;
764                 printf("changed size\n");
765         }
766         ri->pr_rectx= rectx;
767         ri->pr_recty= recty;
768         
769         return 1;
770 }
771
772 /* called before a panel gets moved/scaled, makes sure we can see through */
773 void BIF_view3d_previewrender_clear(ScrArea *sa)
774 {
775 #if 0
776         View3D *v3d= sa->spacedata.first;
777
778         if(v3d->ri) {
779                 RenderInfo *ri= v3d->ri;
780                 ri->curtile= 0;
781                 if(ri->rect)
782                         MEM_freeN(ri->rect);
783                 ri->rect= NULL;
784         }
785 #endif
786 }
787
788 /* afterqueue call */
789 void BIF_view3d_previewrender(Scene *scene, ScrArea *sa)
790 {
791         bContext *C= NULL;
792         View3D *v3d= sa->spacedata.first;
793         RegionView3D *rv3d= NULL; // XXX
794         Render *re;
795         RenderInfo *ri; /* preview struct! */
796         RenderStats *rstats;
797         RenderData rdata;
798         rctf viewplane;
799         float clipsta, clipend, pixsize;
800         int orth;
801         
802         /* first get the render info right */
803 //      if (!v3d->ri) {
804 //              ri= v3d->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
805 //              ri->tottile= 10000;
806 //      }
807 //      ri= v3d->ri;
808         
809         if(0==view3d_previewrender_get_rects(sa, &viewplane, ri, &clipsta, &clipend, &orth, &pixsize))
810                 return;
811         
812         /* render is finished, so return */
813         if(ri->tottile && ri->curtile>=ri->tottile) return;
814
815         /* or return with a new event */
816         if(qtest()) {
817 //              addafterqueue(sa->win, RENDERPREVIEW, 1);
818                 return;
819         }
820         //printf("Enter previewrender\n");
821         /* ok, are we rendering all over? */
822         if(ri->re==NULL) {
823                 char name[32];
824                 
825                 ri->status= 0;
826                 
827                 sprintf(name, "View3dPreview %p", sa);
828                 re= ri->re= RE_NewRender(name);
829                 //RE_display_draw_cb(re, view3d_previewrender_progress);
830                 //RE_stats_draw_cb(re, view3d_previewrender_stats);
831                 //RE_test_break_cb(re, qtest);
832                 
833                 /* no osa, blur, seq, layers, etc for preview render */
834                 rdata= scene->r;
835                 rdata.mode &= ~(R_OSA|R_MBLUR);
836                 rdata.scemode &= ~(R_DOSEQ|R_DOCOMP|R_FREE_IMAGE);
837                 rdata.layers.first= rdata.layers.last= NULL;
838                 rdata.renderer= R_INTERN;
839                  
840                 RE_InitState(re, NULL, &rdata, sa->winx, sa->winy, &ri->disprect);
841         
842                 if(orth)
843                         RE_SetOrtho(re, &viewplane, clipsta, clipend);
844                 else
845                         RE_SetWindow(re, &viewplane, clipsta, clipend);
846                 RE_SetPixelSize(re, pixsize);
847                 
848                 /* until here are no escapes */
849                 ri->status |= PR_DISPRECT;
850                 ri->curtile= 0;
851                 //printf("new render\n");
852         }
853
854         re= ri->re;
855         
856         PIL_sleep_ms(100);      /* wait 0.1 second if theres really no event... */
857         if(qtest()==0)  {
858                 
859                 /* check status */
860                 if((ri->status & PR_DISPRECT)==0) {
861                         RE_SetDispRect(ri->re, &ri->disprect);
862                         if(orth)
863                                 RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
864                         else
865                                 RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
866                         RE_SetPixelSize(re, pixsize);
867                         ri->status |= PR_DISPRECT;
868                         ri->curtile= 0;
869                         //printf("disprect update\n");
870                 }
871                 if((ri->status & PR_DBASE)==0) {
872                         unsigned int lay= scene->lay;
873                         
874                         RE_SetView(re, rv3d->viewmat);
875                         
876                         /* allow localview render for objects with lights in normal layers */
877                         if(v3d->lay & 0xFF000000)
878                                 scene->lay |= v3d->lay;
879                         else scene->lay= v3d->lay;
880                         
881                         RE_Database_FromScene(re, scene, 0);            // 0= dont use camera view
882                         scene->lay= lay;
883                         
884                         rstats= RE_GetStats(re);
885                         if(rstats->convertdone) 
886                                 ri->status |= PR_DBASE|PR_PROJECTED|PR_ROTATED;
887                         ri->curtile= 0;
888                         
889                         /* database can have created render-resol data... */
890                         if(rstats->convertdone) 
891                                 ED_anim_dag_flush_update(C); // <--- only current scene XXX
892                         
893                         //printf("dbase update\n");
894                 }
895                 if((ri->status & PR_PROJECTED)==0) {
896                         if(ri->status & PR_DBASE) {
897                                 if(orth)
898                                         RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
899                                 else
900                                         RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
901                                 RE_DataBase_ApplyWindow(re);
902                                 ri->status |= PR_PROJECTED;
903                         }
904                         ri->curtile= 0;
905                         //printf("project update\n");
906                 }
907         
908                 /* OK, can we enter render code? */
909                 if(ri->status==(PR_DISPRECT|PR_DBASE|PR_PROJECTED|PR_ROTATED)) {
910                         //printf("curtile %d tottile %d\n", ri->curtile, ri->tottile);
911                         RE_TileProcessor(ri->re, ri->curtile, 0);
912         
913                         if(ri->rect==NULL)
914                                 ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "preview view3d rect");
915                         
916                         RE_ResultGet32(ri->re, ri->rect);
917                 }
918                 
919                 rstats= RE_GetStats(ri->re);
920 //              if(rstats->totpart==rstats->partsdone && rstats->partsdone)
921 //                      addqueue(sa->win, REDRAW, 1);
922 //              else
923 //                      addafterqueue(sa->win, RENDERPREVIEW, 1);
924                 
925                 ri->curtile= rstats->partsdone;
926                 ri->tottile= rstats->totpart;
927         }
928         else {
929 //              addafterqueue(sa->win, RENDERPREVIEW, 1);
930         }
931         
932         //printf("\n");
933 }
934
935 /* in panel space! */
936 static void view3d_previewdraw_rect(ScrArea *sa, uiBlock *block, RenderInfo *ri)
937 {
938 //      rctf dispf;
939         
940         if(ri->rect==NULL)
941                 return;
942         
943 //      BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
944 //      ui_graphics_to_window_rct(sa->win, &dispf, &ri->disprect);
945
946         /* correction for gla draw */
947 //      BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
948         
949         /* when panel scale changed, free rect */
950         if(ri->disprect.xmax-ri->disprect.xmin != ri->pr_rectx ||
951            ri->disprect.ymax-ri->disprect.ymin != ri->pr_recty) {
952                 MEM_freeN(ri->rect);
953                 ri->rect= NULL;
954         }
955         else {
956 //              glaDefine2DArea(&sa->winrct);
957                 glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
958         }       
959 }
960
961 /* is panel callback, supposed to be called with correct panel offset matrix */
962 void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block)
963 {
964         RegionView3D *rv3d= NULL;
965
966 //      if (v3d->ri==NULL || v3d->ri->rect==NULL) 
967 //              addafterqueue(sa->win, RENDERPREVIEW, 1);
968 //      else {
969                 view3d_previewdraw_rect(sa, block, rv3d->ri);
970 //              if(v3d->ri->curtile==0) 
971 //                      addafterqueue(sa->win, RENDERPREVIEW, 1);
972 //      }
973 }
974
975
976 /* **************************** New preview system ****************** */
977
978 /* inside thread, called by renderer, sets job update value */
979 static void shader_preview_draw(void *spv, RenderResult *rr, volatile struct rcti *rect)
980 {
981         ShaderPreview *sp= spv;
982         
983         *(sp->do_update)= 1;
984 }
985
986 /* called by renderer, checks job value */
987 static int shader_preview_break(void *spv)
988 {
989         ShaderPreview *sp= spv;
990         
991         return *(sp->stop);
992 }
993
994 /* outside thread, called before redraw notifiers, it moves finished preview over */
995 static void shader_preview_updatejob(void *spv)
996 {
997 //      ShaderPreview *sp= spv;
998         
999 }
1000
1001 /* runs inside thread */
1002 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
1003 {
1004         ShaderPreview *sp= customdata;
1005         Render *re;
1006         Scene *sce;
1007         float oldlens;
1008         char name [32];
1009
1010         sp->stop= stop;
1011         sp->do_update= do_update;
1012         
1013         /* get the stuff from the builtin preview dbase */
1014         sce= preview_prepare_scene(sp->scene, GS(sp->id->name), sp);
1015         if(sce==NULL) return;
1016         
1017         sprintf(name, "Preview %p", sp->owner);
1018         re= RE_GetRender(name);
1019         
1020         /* full refreshed render from first tile */
1021         if(re==NULL)
1022                 re= RE_NewRender(name);
1023                 
1024         /* sce->r gets copied in RE_InitState! */
1025         if(sp->pr_method==PR_DO_RENDER) {
1026                 sce->r.scemode |= R_NODE_PREVIEW;
1027                 sce->r.scemode &= ~R_NO_IMAGE_LOAD;
1028                 sce->r.mode |= R_OSA;
1029         }
1030         else {  /* PR_ICON_RENDER */
1031                 sce->r.scemode &= ~R_NODE_PREVIEW;
1032                 sce->r.scemode |= R_NO_IMAGE_LOAD;
1033         }
1034
1035         /* allocates or re-uses render result */
1036         RE_InitState(re, NULL, &sce->r, sp->sizex, sp->sizey, NULL);
1037
1038         /* callbacs are cleared on GetRender() */
1039         if(sp->pr_method==PR_DO_RENDER) {
1040                 RE_display_draw_cb(re, sp, shader_preview_draw);
1041                 RE_test_break_cb(re, sp, shader_preview_break);
1042         }
1043         /* lens adjust */
1044         oldlens= ((Camera *)sce->camera->data)->lens;
1045         ((Camera *)sce->camera->data)->lens *= (float)sp->sizey/(float)sp->sizex;
1046
1047         /* entire cycle for render engine */
1048         RE_SetCamera(re, sce->camera);
1049         RE_Database_FromScene(re, sce, 1);
1050         RE_TileProcessor(re, 0, 1);     // actual render engine
1051         RE_Database_Free(re);
1052
1053         ((Camera *)sce->camera->data)->lens= oldlens;
1054         *do_update= 1;
1055
1056         /* handle results */
1057         if(sp->pr_method==PR_ICON_RENDER) {
1058                 //if(ri->rect==NULL)
1059                 //      ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
1060                 //RE_ResultGet32(re, ri->rect);
1061         }
1062         else {
1063                 /* validate owner */
1064                 //if(ri->rect==NULL)
1065                 //      ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
1066                 //RE_ResultGet32(re, ri->rect);
1067         }
1068
1069         /* unassign the pointers, reset vars */
1070         preview_prepare_scene(sp->scene, GS(sp->id->name), NULL);
1071
1072 }
1073
1074 static void shader_preview_free(void *customdata)
1075 {
1076         ShaderPreview *sp= customdata;
1077         
1078         MEM_freeN(sp);
1079 }
1080
1081 void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, int sizey)
1082 {
1083         wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner);
1084         ShaderPreview *sp= MEM_callocN(sizeof(ShaderPreview), "shader preview");
1085
1086         /* customdata for preview thread */
1087         sp->scene= CTX_data_scene(C);
1088         sp->owner= owner;
1089         sp->sizex= sizex;
1090         sp->sizey= sizey;
1091         sp->pr_method= PR_DO_RENDER;
1092         sp->id = id;
1093         
1094         /* setup job */
1095         WM_jobs_customdata(steve, sp, shader_preview_free);
1096         WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL);
1097         WM_jobs_callbacks(steve, shader_preview_startjob, NULL, shader_preview_updatejob);
1098         
1099         WM_jobs_start(CTX_wm_manager(C), steve);
1100 }
1101
1102