6335bf03ec3c9c236676fdaa24ad648426266b00
[blender.git] / source / blender / src / previewrender.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /* global includes */
34
35 #include <stdlib.h>
36 #include <math.h>
37 #include <string.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #ifndef WIN32
44 #include <unistd.h>
45 #else
46 #include <io.h>
47 #endif   
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_arithb.h"
51 #include "BLI_blenlib.h"
52
53 #include "MTC_matrixops.h"
54
55 #include "DNA_texture_types.h"
56 #include "DNA_world_types.h"
57 #include "DNA_camera_types.h"
58 #include "DNA_image_types.h"
59 #include "DNA_material_types.h"
60 #include "DNA_node_types.h"
61 #include "DNA_object_types.h"
62 #include "DNA_lamp_types.h"
63 #include "DNA_space_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_scene_types.h"
66 #include "DNA_screen_types.h"
67
68 #include "BKE_global.h"
69 #include "BKE_image.h"
70 #include "BKE_icons.h"
71 #include "BKE_library.h"
72 #include "BKE_main.h"
73 #include "BKE_texture.h"
74 #include "BKE_material.h"
75 #include "BKE_node.h"
76 #include "BKE_world.h"
77 #include "BKE_texture.h"
78 #include "BKE_utildefines.h"
79
80 #include "IMB_imbuf.h"
81 #include "IMB_imbuf_types.h"
82
83 #include "BSE_headerbuttons.h"
84 #include "BSE_node.h"
85 #include "BSE_view.h"
86
87 #include "BIF_gl.h"
88 #include "BIF_screen.h"
89 #include "BIF_space.h"          /* allqueue */
90 #include "BIF_butspace.h"       
91 #include "BIF_mywindow.h"
92 #include "BIF_interface.h"
93 #include "BIF_glutil.h"
94
95 #include "BIF_previewrender.h"  /* include ourself for prototypes */
96
97 #include "PIL_time.h"
98
99 #include "RE_pipeline.h"
100 #include "BLO_readfile.h" 
101
102 #include "blendef.h"    /* CLAMP */
103 #include "interface.h"  /* ui_graphics_to_window(),  SOLVE! (ton) */
104 #include "mydevice.h"
105
106
107 #define PR_XMIN         10
108 #define PR_YMIN         5
109 #define PR_XMAX         200
110 #define PR_YMAX         195
111
112
113 void set_previewrect(RenderInfo *ri, int win)
114 {
115         rctf viewplane;
116         
117         BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
118
119         ui_graphics_to_window_rct(win, &viewplane, &ri->disprect);
120         
121         /* correction for gla draw */
122         BLI_translate_rcti(&ri->disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
123         
124         glMatrixMode(GL_PROJECTION);
125         glPushMatrix();
126         glMatrixMode(GL_MODELVIEW);
127         glPushMatrix();
128         
129         glaDefine2DArea(&curarea->winrct);
130
131         ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
132         ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
133 }
134
135 static void end_previewrect(void)
136 {
137         glMatrixMode(GL_PROJECTION);
138         glPopMatrix();
139         glMatrixMode(GL_MODELVIEW);
140         glPopMatrix();
141         
142         // restore viewport / scissor which was set by glaDefine2DArea
143         glViewport(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
144         glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
145
146 }
147
148 /* unused now */
149 void draw_tex_crop(Tex *tex)
150 {
151         rcti rct;
152         int ret= 0;
153         
154         if(tex==0) return;
155         
156         if(tex->type==TEX_IMAGE) {
157                 if(tex->cropxmin==0.0f) ret++;
158                 if(tex->cropymin==0.0f) ret++;
159                 if(tex->cropxmax==1.0f) ret++;
160                 if(tex->cropymax==1.0f) ret++;
161                 if(ret==4) return;
162                 
163                 rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
164                 rct.xmax= PR_XMIN+2+tex->cropxmax*(PR_XMAX-PR_XMIN-4);
165                 rct.ymin= PR_YMIN+2+tex->cropymin*(PR_YMAX-PR_YMIN-4);
166                 rct.ymax= PR_YMIN+2+tex->cropymax*(PR_YMAX-PR_YMIN-4);
167
168                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
169
170                 glColor3ub(0, 0, 0);
171                 glRecti(rct.xmin+1,  rct.ymin-1,  rct.xmax+1,  rct.ymax-1); 
172
173                 glColor3ub(255, 255, 255);
174                 glRecti(rct.xmin,  rct.ymin,  rct.xmax,  rct.ymax);
175
176                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);                      
177         }
178         
179 }
180
181 /* temporal abuse; if id_code is -1 it only does texture.... solve! */
182 void BIF_preview_changed(short id_code)
183 {
184         ScrArea *sa;
185         
186         for(sa= G.curscreen->areabase.first; sa; sa= sa->next) {
187                 if(sa->spacetype==SPACE_BUTS) {
188                         SpaceButs *sbuts= sa->spacedata.first;
189                         if(sbuts->mainb==CONTEXT_SHADING) {
190                                 int tab= sbuts->tab[CONTEXT_SHADING];
191                                 if(tab==TAB_SHADING_MAT && (id_code==ID_MA || id_code==ID_TE)) {
192                                         if (sbuts->ri) sbuts->ri->cury= 0;
193                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
194                                 }
195                                 else if(tab==TAB_SHADING_TEX && (id_code==ID_TE || id_code==-1)) {
196                                         if (sbuts->ri) sbuts->ri->cury= 0;
197                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
198                                 }
199                                 else if(tab==TAB_SHADING_LAMP && (id_code==ID_LA || id_code==ID_TE)) {
200                                         if (sbuts->ri) sbuts->ri->cury= 0;
201                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
202                                 }
203                                 else if(tab==TAB_SHADING_WORLD && (id_code==ID_WO || id_code==ID_TE)) {
204                                         if (sbuts->ri) sbuts->ri->cury= 0;
205                                         addafterqueue(sa->win, RENDERPREVIEW, 1);
206                                 }
207                         }
208                 }
209                 else if(sa->spacetype==SPACE_NODE) {
210                         SpaceNode *snode= sa->spacedata.first;
211                         if(snode->treetype==NTREE_SHADER && (id_code==ID_MA || id_code==ID_TE)) {
212                                 snode_tag_dirty(snode);
213                         }
214                 }
215                 else if(sa->spacetype==SPACE_VIEW3D) {
216                         View3D *vd= sa->spacedata.first;
217                         /* if is has a renderinfo, we consider that reason for signalling */
218                         if (vd->ri) {
219                                 vd->ri->cury= 0;
220                                 addafterqueue(sa->win, RENDERPREVIEW, 1);
221                         }
222                 }
223         }
224 }
225
226 /* *************************** Preview for buttons *********************** */
227
228 static Main *pr_main= NULL;
229
230 void BIF_preview_init_dbase(void)
231 {
232         BlendReadError bre;
233         BlendFileData *bfd;
234         extern int datatoc_preview_blend_size;
235         extern char datatoc_preview_blend[];
236         
237         G.fileflags |= G_FILE_NO_UI;
238         bfd= BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, &bre);
239         if (bfd) {
240                 pr_main= bfd->main;
241                 
242                 MEM_freeN(bfd);
243         }
244         G.fileflags &= ~G_FILE_NO_UI;
245 }
246
247 void BIF_preview_free_dbase(void)
248 {
249         if(pr_main)
250                 free_main(pr_main);
251 }
252
253 /* call this with an ID pointer to initialize preview scene */
254 /* call this with ID NULL to restore assigned ID pointers in preview scene */
255 static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_method)
256 {
257         Scene *sce;
258         Base *base;
259         
260         if(pr_main==NULL) return NULL;
261         
262         sce= pr_main->scene.first;
263         if(sce) {
264                 if(id_type==ID_MA) {
265                         Material *mat= (Material *)id;
266                         
267                         if(id) {
268                                 if(pr_method==PR_ICON_RENDER) {
269                                         sce->lay= 1<<MA_SPHERE_A;
270                                 }
271                                 else {
272                                         sce->lay= 1<<mat->pr_type;
273                                         if(mat->nodetree)
274                                                 ntreeInitPreview(mat->nodetree, ri->pr_rectx, ri->pr_recty);
275                                 }
276                         }                       
277                         for(base= sce->base.first; base; base= base->next) {
278                                 if(base->object->id.name[2]=='p') {
279                                         if(ELEM4(base->object->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL))
280                                                 assign_material(base->object, mat, base->object->actcol);
281                                 }
282                         }
283                 }
284                 else if(id_type==ID_TE) {
285                         Tex *tex= (Tex *)id;
286                         
287                         sce->lay= 1<<MA_TEXTURE;
288                         
289                         for(base= sce->base.first; base; base= base->next) {
290                                 if(base->object->id.name[2]=='t') {
291                                         Material *mat= give_current_material(base->object, base->object->actcol);
292                                         if(mat && mat->mtex[0]) {
293                                                 mat->mtex[0]->tex= tex;
294                                         }
295                                 }
296                         }
297                 }
298                 else if(id_type==ID_LA) {
299                         Lamp *la= (Lamp *)id;
300                         
301                         sce->lay= 1<<MA_LAMP;
302                         
303                         for(base= sce->base.first; base; base= base->next) {
304                                 if(base->object->id.name[2]=='p') {
305                                         if(base->object->type==OB_LAMP)
306                                                 base->object->data= la;
307                                 }
308                         }
309                 }
310                 else if(id_type==ID_WO) {
311                         sce->lay= 1<<MA_SKY;
312                         sce->world= (World *)id;
313                 }
314                 
315                 return sce;
316         }
317         
318         return NULL;
319 }
320
321 static void previewrender_progress(RenderResult *rr, rcti *unused)
322 {
323         RenderLayer *rl;
324         RenderInfo *ri= G.buts->ri;
325         float ofsx, ofsy;
326         
327         rl= rr->layers.first;
328         
329         ofsx= ri->disprect.xmin + rr->tilerect.xmin;
330         ofsy= ri->disprect.ymin + rr->tilerect.ymin;
331         
332         glDrawBuffer(GL_FRONT);
333         glaDrawPixelsSafe(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, GL_RGBA, GL_FLOAT, rl->rectf);
334         glFlush();
335         glDrawBuffer(GL_BACK);
336 }
337
338
339 /* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
340 void BIF_previewrender(struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
341 {
342         Render *re;
343         RenderStats *rstats;
344         Scene *sce;
345         char name [32];
346         
347         if(ri->cury>=ri->pr_recty) return;
348         
349         if(ri->rect==NULL) {
350                 ri->rect= MEM_callocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "butsrect");
351         }
352         
353         /* check for return with a new event */
354         if(pr_method!=PR_ICON_RENDER && qtest()) {
355                 if(area)
356                         addafterqueue(area->win, RENDERPREVIEW, 1);
357                 return;
358         }
359         
360         /* get the stuff from the builtin preview dbase */
361         sce= preview_prepare_scene(ri, GS(id->name), id, pr_method);
362         if(sce==NULL) return;
363         
364         /* just create new render always now */
365         sprintf(name, "ButsPreview %d", area?area->win:0);
366         re= RE_NewRender(name);
367         
368         /* handle cases */
369         if(pr_method==PR_DRAW_RENDER) {
370                 RE_display_draw_cb(re, previewrender_progress);
371                 RE_test_break_cb(re, qtest);
372                 sce->r.scemode |= R_NODE_PREVIEW;
373         }
374         else if(pr_method==PR_DO_RENDER) {
375                 RE_test_break_cb(re, qtest);
376                 sce->r.scemode |= R_NODE_PREVIEW;
377         }
378         else {  /* PR_ICON_RENDER */
379                 sce->r.scemode &= ~R_NODE_PREVIEW;
380         }
381
382         /* entire cycle for render engine */
383         RE_InitState(re, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
384         RE_SetCamera(re, sce->camera);
385         RE_Database_FromScene(re, sce, 1);
386         RE_TileProcessor(re);   // actual render engine
387         RE_Database_Free(re);
388
389         /* handle results */
390         if(pr_method==PR_ICON_RENDER) {
391                 RE_ResultGet32(re, ri->rect);
392         }
393         else {
394                 rstats= RE_GetStats(re);
395                 if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
396                         ri->cury= ri->pr_recty;
397                         RE_ResultGet32(re, ri->rect);
398                         if(GS(id->name)==ID_MA && ((Material *)id)->use_nodes)
399                                 allqueue(REDRAWNODE, 0);
400                         allqueue(REDRAWBUTSSHADING, 0);
401                 }
402                 else {
403                         if(pr_method==PR_DRAW_RENDER && qtest()) {
404                                 addafterqueue(area->win, RENDERPREVIEW, 1);
405                         }
406                 }
407         }
408         /* unassign the pointer */
409         preview_prepare_scene(ri, GS(id->name), NULL, 0);
410         RE_FreeRender(re);
411 }
412
413
414 /* afterqueue call */
415 void BIF_previewrender_buts(SpaceButs *sbuts)
416 {
417         uiBlock *block;
418         struct ID* id = 0;
419         struct ID* idfrom = 0;
420         struct ID* idshow = 0;
421         Object *ob;
422         
423         if (!sbuts->ri) return;
424         
425         /* we safely assume curarea has panel "preview" */
426         /* quick hack for now, later on preview should become uiBlock itself */
427         
428         block= uiFindOpenPanelBlockName(&curarea->uiblocks, "Preview");
429         if(block==NULL) return;
430         
431         ob= ((G.scene->basact)? (G.scene->basact)->object: 0);
432         
433         /* we cant trust this global lockpoin.. for example with headerless window */
434         buttons_active_id(&id, &idfrom);
435         G.buts->lockpoin= id;
436         
437         if(sbuts->mainb==CONTEXT_SHADING) {
438                 int tab= sbuts->tab[CONTEXT_SHADING];
439                 
440                 if(tab==TAB_SHADING_MAT) 
441                         idshow = sbuts->lockpoin;
442                 else if(tab==TAB_SHADING_TEX) 
443                         idshow = sbuts->lockpoin;
444                 else if(tab==TAB_SHADING_LAMP) {
445                         if(ob && ob->type==OB_LAMP) idshow= ob->data;
446                 }
447                 else if(tab==TAB_SHADING_WORLD)
448                         idshow = sbuts->lockpoin;
449         }
450         else if(sbuts->mainb==CONTEXT_OBJECT) {
451                 if(ob && ob->type==OB_LAMP) idshow = ob->data;
452         }
453         
454         if (idshow) {
455                 BKE_icon_changed(BKE_icon_getid(idshow));
456                 uiPanelPush(block);
457                 set_previewrect(sbuts->ri, sbuts->area->win); // uses UImat
458                 BIF_previewrender(idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
459                 uiPanelPop(block);
460                 end_previewrect();
461         }
462         else {
463                 /* no active block to draw. But we do draw black if possible */
464                 if(sbuts->ri->rect) {
465                         memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
466                         sbuts->ri->cury= sbuts->ri->pr_recty;
467                         addqueue(curarea->win, REDRAW, 1);
468                 }
469                 return;
470         }
471 }
472
473
474 /* is panel callback, supposed to be called with correct panel offset matrix */
475 void BIF_previewdraw(ScrArea *sa, uiBlock *block)
476 {
477         SpaceButs *sbuts= sa->spacedata.first;
478         short id_code= 0;
479         
480         if(sbuts->lockpoin) {
481                 ID *id= sbuts->lockpoin;
482                 id_code= GS(id->name);
483         }
484         
485         if (!sbuts->ri) {
486                 sbuts->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
487                 sbuts->ri->cury = 0;
488                 sbuts->ri->rect = NULL;
489         }
490         
491         if (sbuts->ri->rect==NULL) BIF_preview_changed(id_code);
492         else {
493                 RenderInfo *ri= sbuts->ri;
494                 int oldx= ri->pr_rectx, oldy= ri->pr_recty;
495                 
496                 /* we now do scalable previews! */
497                 set_previewrect(ri, sa->win);
498                 if(oldx==ri->pr_rectx && oldy==ri->pr_recty) 
499                         glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
500                 else {
501                         MEM_freeN(ri->rect);
502                         ri->rect= NULL;
503                         sbuts->ri->cury= 0;
504                 }
505                 end_previewrect();
506         }
507         if(sbuts->ri->cury==0) BIF_preview_changed(id_code);
508         
509 }
510
511 /* *************************** Preview for 3d window *********************** */
512 static void view3d_previewrender_stats(RenderStats *rs)
513 {
514         printf("rendered %.3f\n", rs->lastframetime);
515 }
516
517 static void view3d_previewrender_progress(RenderResult *rr, rcti *unused)
518 {
519         RenderLayer *rl;
520         int ofsx, ofsy;
521         
522         rl= rr->layers.first;
523         
524         /* this case is when we render envmaps... */
525         if(rr->rectx>G.vd->ri->pr_rectx || rr->recty>G.vd->ri->pr_recty)
526                 return;
527         
528         ofsx= G.vd->ri->disprect.xmin + rr->tilerect.xmin;
529         ofsy= G.vd->ri->disprect.ymin + rr->tilerect.ymin;
530         
531         glDrawBuffer(GL_FRONT);
532         glaDefine2DArea(&curarea->winrct);
533         glaDrawPixelsSafe(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, GL_RGBA, GL_FLOAT, rl->rectf);
534         glFlush();
535         glDrawBuffer(GL_BACK);
536
537 }
538
539 void BIF_view3d_previewrender_signal(ScrArea *sa, short signal)
540 {
541         View3D *v3d= sa->spacedata.first;
542         
543         /* this can be called from other window... solve! */
544         if(sa->spacetype!=SPACE_VIEW3D)
545                 v3d= G.vd;
546            
547         if(v3d && v3d->ri) {
548                 RenderInfo *ri= v3d->ri;
549                 ri->status &= ~signal;
550                 ri->cury= 0;
551                 if(ri->re && (signal & PR_DBASE))
552                         RE_Database_Free(ri->re);
553
554                 addafterqueue(sa->win, RENDERPREVIEW, 1);
555         }
556 }
557
558 void BIF_view3d_previewrender_free(ScrArea *sa)
559 {
560         View3D *v3d= sa->spacedata.first;
561
562         if(v3d->ri) {
563                 RenderInfo *ri= v3d->ri;
564                 if(ri->re) {
565 //                      printf("free render\n");
566                         RE_Database_Free(ri->re);
567                         RE_FreeRender(ri->re);
568                         ri->re= NULL;
569                 }
570                 ri->status= 0;
571                 ri->cury= 0;
572         }
573 }
574
575 /* returns 1 if OK, do not call while in panel space!  */
576 static int view3d_previewrender_get_rects(ScrArea *sa, rctf *viewplane, RenderInfo *ri, float *clipsta, float *clipend, int *ortho)
577 {
578         int rectx, recty;
579         uiBlock *block;
580         
581         block= uiFindOpenPanelBlockName(&curarea->uiblocks, "Preview");
582         if(block==NULL) return 0;
583         
584         /* calculate preview rect size */
585         BLI_init_rctf(viewplane, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
586         uiPanelPush(block);
587         ui_graphics_to_window_rct(sa->win, viewplane, &ri->disprect);
588         uiPanelPop(block);
589         
590         /* correction for gla draw */
591         BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
592         
593         *ortho= get_view3d_viewplane(sa->winx, sa->winy, viewplane, clipsta, clipend);
594
595         rectx= ri->disprect.xmax - ri->disprect.xmin;
596         recty= ri->disprect.ymax - ri->disprect.ymin;
597         
598         if(rectx<4 || recty<4) return 0;
599         
600         if(ri->rect && (rectx!=ri->pr_rectx || recty!=ri->pr_recty)) {
601                 MEM_freeN(ri->rect);
602                 ri->rect= NULL;
603         }
604         ri->pr_rectx= rectx;
605         ri->pr_recty= recty;
606         
607         return 1;
608 }
609
610 /* called before a panel gets moved/scaled, makes sure we can see through */
611 void BIF_view3d_previewrender_clear(ScrArea *sa)
612 {
613         View3D *v3d= sa->spacedata.first;
614
615         if(v3d->ri) {
616                 RenderInfo *ri= v3d->ri;
617                 ri->cury= 0;
618                 if(ri->rect)
619                         MEM_freeN(ri->rect);
620                 ri->rect= NULL;
621         }
622 }
623
624 /* afterqueue call */
625 void BIF_view3d_previewrender(ScrArea *sa)
626 {
627         View3D *v3d= sa->spacedata.first;
628         Render *re;
629         RenderInfo *ri; /* preview struct! */
630         RenderStats *rstats;
631         RenderData rdata;
632         rctf viewplane;
633         float clipsta, clipend;
634         int orth;
635         
636         /* first get the render info right */
637         if (!v3d->ri)
638                 ri= v3d->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
639         ri= v3d->ri;
640         
641         if(0==view3d_previewrender_get_rects(sa, &viewplane, ri, &clipsta, &clipend, &orth))
642                 return;
643         
644         /* render is finished, so return */
645         if(ri->cury>=ri->pr_rectx) return;
646
647         /* or return with a new event */
648         if(qtest()) {
649                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
650                 return;
651         }
652         
653         /* ok, are we rendering all over? */
654         if(ri->re==NULL) {
655                 char name[32];
656                 
657                 ri->status= 0;
658                 
659                 sprintf(name, "View3dPreview %d", sa->win);
660                 re= ri->re= RE_NewRender(name);
661                 RE_display_draw_cb(re, view3d_previewrender_progress);
662                 RE_stats_draw_cb(re, view3d_previewrender_stats);
663                 RE_test_break_cb(re, qtest);
664                 
665                 /* no osa, blur, seq, for preview render */
666                 rdata= G.scene->r;
667                 rdata.mode &= ~(R_OSA|R_MBLUR|R_DOSEQ);
668                 rdata.layers.first= rdata.layers.last= NULL;
669         
670                 RE_InitState(re, &rdata, sa->winx, sa->winy, &ri->disprect);
671         
672                 if(orth)
673                         RE_SetOrtho(re, &viewplane, clipsta, clipend);
674                 else
675                         RE_SetWindow(re, &viewplane, clipsta, clipend);
676                 
677                 /* until here are no escapes */
678                 ri->status |= PR_DISPRECT;
679         }
680
681         re= ri->re;
682         
683         PIL_sleep_ms(100);      /* wait 0.1 second if theres really no event... */
684         if(qtest()==0)  {
685                 
686                 /* check status */
687                 if((ri->status & PR_DISPRECT)==0) {
688                         RE_SetDispRect(ri->re, &ri->disprect);
689                         if(orth)
690                                 RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
691                         else
692                                 RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
693                         ri->status |= PR_DISPRECT;
694                 }
695                 if((ri->status & PR_DBASE)==0) {
696                         unsigned int lay= G.scene->lay;
697                         
698                         RE_SetView(re, G.vd->viewmat);
699                         
700                         /* allow localview render for objects with lights in normal layers */
701                         if(v3d->lay & 0xFF000000)
702                                 G.scene->lay |= v3d->lay;
703                         else G.scene->lay= v3d->lay;
704                         
705                         RE_Database_FromScene(re, G.scene, 0);          // 0= dont use camera view
706                         G.scene->lay= lay;
707                         
708                         rstats= RE_GetStats(re);
709                         if(rstats->convertdone) 
710                                 ri->status |= PR_DBASE|PR_PROJECTED|PR_ROTATED;
711                 }
712                 if((ri->status & PR_PROJECTED)==0) {
713                         if(ri->status & PR_DBASE) {
714                                 if(orth)
715                                         RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
716                                 else
717                                         RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
718                                 RE_DataBase_ApplyWindow(re);
719                                 ri->status |= PR_PROJECTED;
720                         }
721                 }
722         
723                 /* OK, can we enter render code? */
724                 if(ri->status==(PR_DISPRECT|PR_DBASE|PR_PROJECTED|PR_ROTATED)) {
725                         RE_TileProcessor(ri->re);
726         
727                         if(ri->rect==NULL)
728                                 ri->rect= MEM_callocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "preview view3d rect");
729                         
730                         RE_ResultGet32(ri->re, ri->rect);
731                 }
732                 
733                 rstats= RE_GetStats(ri->re);
734                 if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
735                         ri->cury= 12000;        /* arbitrary... */
736                         addqueue(sa->win, REDRAW, 1);
737                 }
738                 else {
739                         addafterqueue(curarea->win, RENDERPREVIEW, 1);
740                         ri->cury= 0;
741                 }
742         }
743         else {
744                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
745                 ri->cury= 0;
746         }
747 }
748
749 /* in panel space! */
750 static void view3d_previewdraw_rect(ScrArea *sa, uiBlock *block, RenderInfo *ri)
751 {
752         rctf dispf;
753         
754         if(ri->rect==NULL)
755                 return;
756         
757         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
758         ui_graphics_to_window_rct(sa->win, &dispf, &ri->disprect);
759
760         /* correction for gla draw */
761         BLI_translate_rcti(&ri->disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
762         
763         /* when panel scale changed, free rect */
764         if(ri->disprect.xmax-ri->disprect.xmin != ri->pr_rectx ||
765            ri->disprect.ymax-ri->disprect.ymin != ri->pr_recty) {
766                 MEM_freeN(ri->rect);
767                 ri->rect= NULL;
768         }
769         else {
770                 glaDefine2DArea(&sa->winrct);
771                 glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
772         }       
773 }
774
775 /* is panel callback, supposed to be called with correct panel offset matrix */
776 void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block)
777 {
778         View3D *v3d= sa->spacedata.first;
779
780         if (v3d->ri==NULL || v3d->ri->rect==NULL) 
781                 addafterqueue(sa->win, RENDERPREVIEW, 1);
782         else {
783                 view3d_previewdraw_rect(sa, block, v3d->ri);
784                 if(v3d->ri->cury==0) 
785                         addafterqueue(sa->win, RENDERPREVIEW, 1);
786         }
787 }
788