2.5 Material:
[blender-staging.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_view3d.h"
92
93 #include "UI_interface.h"
94
95 #include "previewrender_intern.h"
96
97 #define PR_XMIN         10
98 #define PR_YMIN         5
99 #define PR_XMAX         200
100 #define PR_YMAX         195
101
102 /* XXX */
103 static int qtest() {return 0;}
104 /* XXX */
105
106 typedef struct ShaderPreview {
107         /* from wmJob */
108         void *owner;
109         short *stop, *do_update;
110         
111         Scene *scene;
112         ID *id;
113         
114         int sizex, sizey;
115         int pr_method;
116 } ShaderPreview;
117
118
119 static void set_previewrect(ScrArea *sa, RenderInfo *ri)
120 {
121         ARegion *ar= NULL; // XXX
122         rctf viewplane;
123         
124         BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
125
126 //      ui_graphics_to_window_rct(ar->win, &viewplane, &ri->disprect);
127         
128         /* correction for gla draw */
129         BLI_translate_rcti(&ri->disprect, -ar->winrct.xmin, -ar->winrct.ymin);
130         
131         glMatrixMode(GL_PROJECTION);
132         glPushMatrix();
133         glMatrixMode(GL_MODELVIEW);
134         glPushMatrix();
135         
136         glaDefine2DArea(&ar->winrct);
137
138         ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
139         ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
140 }
141
142 static void end_previewrect(ARegion *ar)
143 {
144         glMatrixMode(GL_PROJECTION);
145         glPopMatrix();
146         glMatrixMode(GL_MODELVIEW);
147         glPopMatrix();
148         
149         // restore viewport / scissor which was set by glaDefine2DArea
150         glViewport(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
151         glScissor(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
152
153 }
154
155 /* unused now */
156 void draw_tex_crop(Tex *tex)
157 {
158         rcti rct;
159         int ret= 0;
160         
161         if(tex==0) return;
162         
163         if(tex->type==TEX_IMAGE) {
164                 if(tex->cropxmin==0.0f) ret++;
165                 if(tex->cropymin==0.0f) ret++;
166                 if(tex->cropxmax==1.0f) ret++;
167                 if(tex->cropymax==1.0f) ret++;
168                 if(ret==4) return;
169                 
170                 rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
171                 rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
172                 rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
173                 rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
174
175                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
176
177                 glColor3ub(0, 0, 0);
178                 glRecti(rct.xmin+1,  rct.ymin-1,  rct.xmax+1,  rct.ymax-1); 
179
180                 glColor3ub(255, 255, 255);
181                 glRecti(rct.xmin,  rct.ymin,  rct.xmax,  rct.ymax);
182
183                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);                      
184         }
185         
186 }
187
188 /* temporal abuse; if id_code is -1 it only does texture.... solve! */
189 void BIF_preview_changed(short id_code)
190 {
191 #if 0   
192         ScrArea *sa;
193         
194         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
195                 if(sa->spacetype==SPACE_BUTS) {
196                         SpaceButs *sbuts= sa->spacedata.first;
197                         if(sbuts->mainb==CONTEXT_SHADING) {
198                                 int tab= sbuts->tab[CONTEXT_SHADING];
199                                 if(tab==TAB_SHADING_MAT && (id_code==ID_MA || id_code==ID_TE)) {
200                                         if (sbuts->ri) sbuts->ri->curtile= 0;
201                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
202                                 }
203                                 else if(tab==TAB_SHADING_TEX && (id_code==ID_TE || id_code==-1)) {
204                                         if (sbuts->ri) sbuts->ri->curtile= 0;
205                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
206                                 }
207                                 else if(tab==TAB_SHADING_LAMP && (id_code==ID_LA || id_code==ID_TE)) {
208                                         if (sbuts->ri) sbuts->ri->curtile= 0;
209                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
210                                 }
211                                 else if(tab==TAB_SHADING_WORLD && (id_code==ID_WO || id_code==ID_TE)) {
212                                         if (sbuts->ri) sbuts->ri->curtile= 0;
213                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
214                                 }
215                         }
216                         else if (sbuts->ri) 
217                                 sbuts->ri->curtile= 0;  /* ensure changes always result in re-render when context is restored */
218                 }
219                 else if(sa->spacetype==SPACE_NODE) {
220                         SpaceNode *snode= sa->spacedata.first;
221                         if(snode->treetype==NTREE_SHADER && (id_code==ID_MA || id_code==ID_TE)) {
222                                 snode_tag_dirty(snode);
223                         }
224                 }
225                 else if(sa->spacetype==SPACE_VIEW3D) {
226                         View3D *vd= sa->spacedata.first;
227                         /* if is has a renderinfo, we consider that reason for signalling */
228                         if (vd->ri) {
229                                 vd->ri->curtile= 0;
230                                 addafterqueue(sa->win, RENDERPREVIEW, 1);
231                         }
232                 }
233         }
234
235         if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) {
236                 Object *ob;
237                 Material *ma;
238
239                 if(id_code == ID_WO) {
240                         for(ma=G.main->mat.first; ma; ma=ma->id.next) {
241                                 if(ma->gpumaterial.first) {
242                                         GPU_material_free(ma);
243                                 }
244                         }
245                 }
246                 else if(id_code == ID_LA) {
247                         for(ob=G.main->object.first; ob; ob=ob->id.next) {
248                                 if(ob->gpulamp.first) {
249                                         GPU_lamp_free(ob);
250                                 }
251                         }
252                 } else if(OBACT) {
253                         Object *ob = OBACT;
254
255                         ma= give_current_material(ob, ob->actcol);
256                         if(ma && ma->gpumaterial.first) {
257                                 GPU_material_free(ma);
258                         }
259                 }
260         }
261 #endif
262 }
263
264 /* *************************** Preview for buttons *********************** */
265
266 static Main *pr_main= NULL;
267
268 void ED_preview_init_dbase(void)
269 {
270         BlendFileData *bfd;
271         extern int datatoc_preview_blend_size;
272         extern char datatoc_preview_blend[];
273         
274         G.fileflags |= G_FILE_NO_UI;
275         bfd= BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, NULL);
276         if (bfd) {
277                 pr_main= bfd->main;
278                 
279                 MEM_freeN(bfd);
280         }
281         G.fileflags &= ~G_FILE_NO_UI;
282 }
283
284 void ED_preview_free_dbase(void)
285 {
286         if(pr_main)
287                 free_main(pr_main);
288 }
289
290 static Object *find_object(ListBase *lb, const char *name)
291 {
292         Object *ob;
293         for(ob= lb->first; ob; ob= ob->id.next)
294                 if(strcmp(ob->id.name+2, name)==0)
295                         break;
296         return ob;
297 }
298
299 /* call this with a pointer to initialize preview scene */
300 /* call this with NULL to restore assigned ID pointers in preview scene */
301 static Scene *preview_prepare_scene(Scene *scene, int id_type, ShaderPreview *sp)
302 {
303         Scene *sce;
304         Base *base;
305         ID *id= sp?sp->id:NULL;
306         
307         if(pr_main==NULL) return NULL;
308         
309         sce= pr_main->scene.first;
310         if(sce) {
311                 /* this flag tells render to not execute depsgraph or ipos etc */
312                 sce->r.scemode |= R_PREVIEWBUTS;
313                 /* set world always back, is used now */
314                 sce->world= pr_main->world.first;
315                 /* now: exposure copy */
316                 if(scene->world) {
317                         sce->world->exp= scene->world->exp;
318                         sce->world->range= scene->world->range;
319                 }
320                 
321                 sce->r.cfra= scene->r.cfra;
322                 
323                 if(id_type==ID_MA) {
324                         Material *mat= (Material *)id;
325                         
326                         if(id) {
327                                 init_render_material(mat, 0, NULL);             /* call that retrieves mode_l */
328                                 end_render_material(mat);
329                                 
330                                 /* turn on raytracing if needed */
331                                 if(mat->mode_l & (MA_RAYTRANSP|MA_RAYMIRROR))
332                                         sce->r.mode |= R_RAYTRACE;
333                                 if(mat->sss_flag & MA_DIFF_SSS)
334                                         sce->r.mode |= R_SSS;
335                                 
336                                 /* turn off fake shadows if needed */
337                                 /* this only works in a specific case where the preview.blend contains
338                                  * an object starting with 'c' which has a material linked to it (not the obdata)
339                                  * and that material has a fake shadow texture in the active texture slot */
340                                 for(base= sce->base.first; base; base= base->next) {
341                                         if(base->object->id.name[2]=='c') {
342                                                 Material *shadmat= give_current_material(base->object, base->object->actcol);
343                                                 if(shadmat) {
344                                                         if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
345                                                         else shadmat->septex |= 1;
346                                                 }
347                                         }
348                                 }
349
350                                 
351                                 if(sp->pr_method==PR_ICON_RENDER) {
352                                         if (mat->material_type == MA_TYPE_HALO) {
353                                                 sce->lay= 1<<MA_FLAT;
354                                         } 
355                                         else {
356                                                 sce->lay= 1<<MA_SPHERE_A;
357                                         }
358                                 }
359                                 else {
360                                         sce->lay= 1<<mat->pr_type;
361                                         if(mat->nodetree)
362                                                 ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
363                                 }
364                         }
365                         else {
366                                 sce->r.mode &= ~(R_OSA|R_RAYTRACE|R_SSS);
367                         }
368                         
369                         for(base= sce->base.first; base; base= base->next) {
370                                 if(base->object->id.name[2]=='p') {
371                                         if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL))
372                                                 assign_material(base->object, mat, base->object->actcol);
373                                 }
374                         }
375                 }
376                 else if(id_type==ID_TE) {
377                         Tex *tex= (Tex *)id;
378                         
379                         sce->lay= 1<<MA_TEXTURE;
380                         
381                         for(base= sce->base.first; base; base= base->next) {
382                                 if(base->object->id.name[2]=='t') {
383                                         Material *mat= give_current_material(base->object, base->object->actcol);
384                                         if(mat && mat->mtex[0]) {
385                                                 mat->mtex[0]->tex= tex;
386                                                 /* show alpha in this case */
387                                                 if(tex==NULL || (tex->flag & TEX_PRV_ALPHA)) {
388                                                         mat->mtex[0]->mapto |= MAP_ALPHA;
389                                                         mat->alpha= 0.0f;
390                                                 }
391                                                 else {
392                                                         mat->mtex[0]->mapto &= ~MAP_ALPHA;
393                                                         mat->alpha= 1.0f;
394                                                 }
395                                         }
396                                 }
397                         }
398                 }
399                 else if(id_type==ID_LA) {
400                         Lamp *la= (Lamp *)id;
401                         
402                         if(la && la->type==LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
403                                 sce->lay= 1<<MA_ATMOS;
404                                 sce->world= scene->world;
405                                 sce->camera= (Object *)find_object(&pr_main->object, "CameraAtmo");
406                         }
407                         else {
408                                 sce->lay= 1<<MA_LAMP;
409                                 sce->world= NULL;
410                                 sce->camera= (Object *)find_object(&pr_main->object, "Camera");
411                         }
412                         sce->r.mode &= ~R_SHADOW;
413                         
414                         for(base= sce->base.first; base; base= base->next) {
415                                 if(base->object->id.name[2]=='p') {
416                                         if(base->object->type==OB_LAMP)
417                                                 base->object->data= la;
418                                 }
419                         }
420                 }
421                 else if(id_type==ID_WO) {
422                         sce->lay= 1<<MA_SKY;
423                         sce->world= (World *)id;
424                 }
425                 
426                 return sce;
427         }
428         
429         return NULL;
430 }
431
432 void previewrender_progress(void *handle, RenderResult *rr, volatile rcti *renrect)
433 {
434         SpaceButs *sbuts= NULL; // XXX
435         RenderLayer *rl;
436         RenderInfo *ri= sbuts->ri;
437         float ofsx, ofsy;
438         
439         if(renrect) return;
440         
441         rl= rr->layers.first;
442         
443         ofsx= ri->disprect.xmin + rr->tilerect.xmin;
444         ofsy= ri->disprect.ymin + rr->tilerect.ymin;
445         
446         glDrawBuffer(GL_FRONT);
447         glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
448         bglFlush();
449         glDrawBuffer(GL_BACK);
450 }
451
452
453 /* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
454 void BIF_previewrender(Scene *scene, struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
455 {
456         SpaceButs *sbuts= NULL; // XXX
457         Render *re;
458         RenderStats *rstats;
459         Scene *sce;
460         int oldx= ri->pr_rectx, oldy= ri->pr_recty;
461         char name [32];
462         
463         if(ri->tottile && ri->curtile>=ri->tottile) return;
464         
465         /* check for return with a new event */
466         if(pr_method!=PR_ICON_RENDER && qtest()) {
467 //              if(area)
468 //                      addafterqueue(area->win, RENDERPREVIEW, 1);
469                 return;
470         }
471         
472         /* get the stuff from the builtin preview dbase */
473 //      sce= preview_prepare_scene(scene, ri, GS(id->name), id, pr_method);
474         if(sce==NULL) return;
475         
476         /* set drawing conditions OK */
477         if(area) {
478                 sbuts= area->spacedata.first;   /* needed for flag */
479                 
480                 set_previewrect(area, ri); // uses UImat
481                 
482                 /* because preview render size can differs */
483                 if(ri->rect && (oldx!=ri->pr_rectx || oldy!=ri->pr_recty)) {
484                         MEM_freeN(ri->rect);
485                         ri->rect= NULL;
486                         ri->curtile= 0;
487                 }
488         }
489         
490 // XXX  sprintf(name, "ButsPreview %d", area?area->win:0);
491         re= RE_GetRender(name);
492         
493         /* full refreshed render from first tile */
494         if(re==NULL || ri->curtile==0) {
495                 
496                 re= RE_NewRender(name);
497                 
498                 /* handle cases */
499                 if(pr_method==PR_DRAW_RENDER) {
500 //                      RE_display_draw_cb(re, previewrender_progress);
501 //                      RE_test_break_cb(re, qtest);
502                         sce->r.scemode |= R_NODE_PREVIEW;
503                         if(sbuts->flag & SB_PRV_OSA)
504                                 sce->r.mode |= R_OSA;
505                         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
506                 }
507                 else if(pr_method==PR_DO_RENDER) {
508 //                      RE_test_break_cb(re, qtest);
509                         sce->r.scemode |= R_NODE_PREVIEW;
510                         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
511                 }
512                 else {  /* PR_ICON_RENDER */
513                         sce->r.scemode &= ~R_NODE_PREVIEW;
514                         sce->r.scemode |= R_NO_IMAGE_LOAD;
515                 }
516                 
517                 /* allocates render result */
518                 RE_InitState(re, NULL, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
519                 
520                 /* enforce preview image clear */
521                 if(GS(id->name)==ID_MA) {
522                         Material *ma= (Material *)id;
523                         ntreeClearPreview(ma->nodetree);
524                 }
525         }
526         /* entire cycle for render engine */
527         RE_SetCamera(re, sce->camera);
528         RE_Database_FromScene(re, sce, 1);
529         RE_TileProcessor(re, ri->curtile, 0);   // actual render engine
530         RE_Database_Free(re);
531         
532         /* handle results */
533         if(pr_method==PR_ICON_RENDER) {
534                 if(ri->rect==NULL)
535                         ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
536                 RE_ResultGet32(re, ri->rect);
537         }
538         else {
539                 rstats= RE_GetStats(re);
540                 
541                 if(rstats->partsdone!=ri->curtile) {
542                         if(ri->rect==NULL)
543                                 ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
544                         RE_ResultGet32(re, ri->rect);
545                 }
546                 
547                 if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
548                         // allqueues
549                 }
550                 else {
551 //                      if(pr_method==PR_DRAW_RENDER && qtest())
552 //                              addafterqueue(area->win, RENDERPREVIEW, 1);
553                 }
554                 
555                 ri->curtile= rstats->partsdone;
556                 ri->tottile= rstats->totpart;
557         }
558
559         /* unassign the pointers, reset vars */
560 //      preview_prepare_scene(scene, ri, GS(id->name), NULL, 0);
561         
562 }
563
564
565 /* afterqueue call */
566 void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
567 {
568 //      ScrArea *sa= NULL; // XXX
569         ARegion *ar= NULL; // XXX
570         uiBlock *block;
571         struct ID* id = 0;
572 //      struct ID* idfrom = 0;
573         struct ID* idshow = 0;
574         Object *ob;
575         
576         if (!sbuts->ri) return;
577         
578         
579 //      block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
580         if(block==NULL) return;
581         
582         ob= ((scene->basact)? (scene->basact)->object: 0);
583         
584         /* we cant trust this global lockpoin.. for example with headerless window */
585 //      buttons_active_id(&id, &idfrom);
586         sbuts->lockpoin= id;
587         
588         if(sbuts->mainb==CONTEXT_SHADING) {
589                 int tab= sbuts->tab[CONTEXT_SHADING];
590                 
591                 if(tab==TAB_SHADING_MAT) 
592                         idshow = sbuts->lockpoin;
593                 else if(tab==TAB_SHADING_TEX) 
594                         idshow = sbuts->lockpoin;
595                 else if(tab==TAB_SHADING_LAMP) {
596                         if(ob && ob->type==OB_LAMP) idshow= ob->data;
597                 }
598                 else if(tab==TAB_SHADING_WORLD)
599                         idshow = sbuts->lockpoin;
600         }
601         else if(sbuts->mainb==CONTEXT_OBJECT) {
602                 if(ob && ob->type==OB_LAMP) idshow = ob->data;
603         }
604         
605         if (idshow) {
606                 BKE_icon_changed(BKE_icon_getid(idshow));
607 //              uiPanelPush(block);
608 //              BIF_previewrender(scene, idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
609 //              uiPanelPop(block);
610                 end_previewrect(ar);
611         }
612         else {
613                 /* no active block to draw. But we do draw black if possible */
614                 if(sbuts->ri->rect) {
615                         memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
616                         sbuts->ri->tottile= 10000;
617 //                      addqueue(sa->win, REDRAW, 1);
618                 }
619                 return;
620         }
621 }
622
623
624 /* is panel callback, supposed to be called with correct panel offset matrix */
625 void BIF_previewdraw(ScrArea *sa, uiBlock *block)
626 {
627         ARegion *ar= NULL; // XXX
628         SpaceButs *sbuts= sa->spacedata.first;
629         short id_code= 0;
630         
631         if(sbuts->lockpoin) {
632                 ID *id= sbuts->lockpoin;
633                 id_code= GS(id->name);
634         }
635         
636         if (!sbuts->ri) {
637                 sbuts->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
638                 sbuts->ri->tottile = 10000;
639         }
640         
641         if (sbuts->ri->rect==NULL) BIF_preview_changed(id_code);
642         else {
643                 RenderInfo *ri= sbuts->ri;
644                 int oldx= ri->pr_rectx, oldy= ri->pr_recty;
645                 
646                 /* we now do scalable previews! */
647                 set_previewrect(sa, ri);
648                 if( ABS(oldx-ri->pr_rectx)<2 && ABS(oldy-ri->pr_recty)<2 ) {
649                         /* restore old values for drawing! */
650                         ri->pr_rectx= oldx;
651                         ri->pr_recty= oldy;
652                         glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
653                 }
654                 else {
655                         MEM_freeN(ri->rect);
656                         ri->rect= NULL;
657                         sbuts->ri->curtile= 0;
658                 }
659                 end_previewrect(ar);
660         }
661         if(sbuts->ri->curtile==0) BIF_preview_changed(id_code);
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 /* 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
995 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
996 {
997         ShaderPreview *sp= customdata;
998         Render *re;
999         Scene *sce;
1000         char name [32];
1001
1002         sp->stop= stop;
1003         sp->do_update= do_update;
1004         
1005         /* get the stuff from the builtin preview dbase */
1006         sce= preview_prepare_scene(sp->scene, GS(sp->id->name), sp);
1007         if(sce==NULL) return;
1008         
1009         sprintf(name, "Preview %p", sp->owner);
1010         re= RE_GetRender(name);
1011         
1012         /* full refreshed render from first tile */
1013         if(re==NULL) {
1014                 re= RE_NewRender(name);
1015                 
1016                 /* sce->r gets copied in RE_InitState! */
1017                 if(sp->pr_method==PR_DO_RENDER) {
1018                         sce->r.scemode |= R_NODE_PREVIEW;
1019                         sce->r.scemode &= ~R_NO_IMAGE_LOAD;
1020                 }
1021                 else {  /* PR_ICON_RENDER */
1022                         sce->r.scemode &= ~R_NODE_PREVIEW;
1023                         sce->r.scemode |= R_NO_IMAGE_LOAD;
1024                 }
1025                 
1026                 /* allocates render result */
1027                 RE_InitState(re, NULL, &sce->r, sp->sizex, sp->sizey, NULL);
1028         }
1029         
1030         /* callbacs are cleared on GetRender() */
1031         if(sp->pr_method==PR_DO_RENDER) {
1032                 RE_display_draw_cb(re, sp, shader_preview_draw);
1033                 RE_test_break_cb(re, sp, shader_preview_break);
1034         }
1035
1036         /* entire cycle for render engine */
1037         RE_SetCamera(re, sce->camera);
1038         RE_Database_FromScene(re, sce, 1);
1039         RE_TileProcessor(re, 0, 0);     // actual render engine
1040         RE_Database_Free(re);
1041
1042         *do_update= 1;
1043
1044         /* handle results */
1045         if(sp->pr_method==PR_ICON_RENDER) {
1046                 //if(ri->rect==NULL)
1047                 //      ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
1048                 //RE_ResultGet32(re, ri->rect);
1049         }
1050
1051         /* unassign the pointers, reset vars */
1052         preview_prepare_scene(sp->scene, GS(sp->id->name), NULL);
1053
1054 }
1055
1056 static void shader_preview_free(void *customdata)
1057 {
1058         ShaderPreview *sp= customdata;
1059         
1060         MEM_freeN(sp);
1061 }
1062
1063 void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, int sizey)
1064 {
1065         wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner);
1066         ShaderPreview *sp= MEM_callocN(sizeof(ShaderPreview), "shader preview");
1067
1068         /* customdata for preview thread */
1069         sp->scene= CTX_data_scene(C);
1070         sp->owner= owner;
1071         sp->sizex= sizex;
1072         sp->sizey= sizey;
1073         sp->pr_method= PR_DO_RENDER;
1074         sp->id = id;
1075         
1076         /* setup job */
1077         WM_jobs_customdata(steve, sp, shader_preview_free);
1078         WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL);
1079         WM_jobs_callbacks(steve, shader_preview_startjob, NULL, NULL);
1080         
1081         WM_jobs_start(steve);
1082 }
1083
1084