Fix: buttons previewrender was re-rendering on scrolling a lot, this due
[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( ABS(oldx-ri->pr_rectx)<2 && ABS(oldy-ri->pr_recty)<2 ) {
499                         /* restore old values for drawing! */
500                         ri->pr_rectx= oldx;
501                         ri->pr_recty= oldy;
502                         glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
503                 }
504                 else {
505                         MEM_freeN(ri->rect);
506                         ri->rect= NULL;
507                         sbuts->ri->cury= 0;
508                 }
509                 end_previewrect();
510         }
511         if(sbuts->ri->cury==0) BIF_preview_changed(id_code);
512         
513 }
514
515 /* *************************** Preview for 3d window *********************** */
516 static void view3d_previewrender_stats(RenderStats *rs)
517 {
518         printf("rendered %.3f\n", rs->lastframetime);
519 }
520
521 static void view3d_previewrender_progress(RenderResult *rr, rcti *unused)
522 {
523         RenderLayer *rl;
524         int ofsx, ofsy;
525         
526         rl= rr->layers.first;
527         
528         /* this case is when we render envmaps... */
529         if(rr->rectx>G.vd->ri->pr_rectx || rr->recty>G.vd->ri->pr_recty)
530                 return;
531         
532         ofsx= G.vd->ri->disprect.xmin + rr->tilerect.xmin;
533         ofsy= G.vd->ri->disprect.ymin + rr->tilerect.ymin;
534         
535         glDrawBuffer(GL_FRONT);
536         glaDefine2DArea(&curarea->winrct);
537         glaDrawPixelsSafe(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, GL_RGBA, GL_FLOAT, rl->rectf);
538         glFlush();
539         glDrawBuffer(GL_BACK);
540
541 }
542
543 void BIF_view3d_previewrender_signal(ScrArea *sa, short signal)
544 {
545         View3D *v3d= sa->spacedata.first;
546         
547         /* this can be called from other window... solve! */
548         if(sa->spacetype!=SPACE_VIEW3D)
549                 v3d= G.vd;
550            
551         if(v3d && v3d->ri) {
552                 RenderInfo *ri= v3d->ri;
553                 ri->status &= ~signal;
554                 ri->cury= 0;
555                 if(ri->re && (signal & PR_DBASE))
556                         RE_Database_Free(ri->re);
557
558                 addafterqueue(sa->win, RENDERPREVIEW, 1);
559         }
560 }
561
562 void BIF_view3d_previewrender_free(ScrArea *sa)
563 {
564         View3D *v3d= sa->spacedata.first;
565
566         if(v3d->ri) {
567                 RenderInfo *ri= v3d->ri;
568                 if(ri->re) {
569 //                      printf("free render\n");
570                         RE_Database_Free(ri->re);
571                         RE_FreeRender(ri->re);
572                         ri->re= NULL;
573                 }
574                 ri->status= 0;
575                 ri->cury= 0;
576         }
577 }
578
579 /* returns 1 if OK, do not call while in panel space!  */
580 static int view3d_previewrender_get_rects(ScrArea *sa, rctf *viewplane, RenderInfo *ri, float *clipsta, float *clipend, int *ortho)
581 {
582         int rectx, recty;
583         uiBlock *block;
584         
585         block= uiFindOpenPanelBlockName(&curarea->uiblocks, "Preview");
586         if(block==NULL) return 0;
587         
588         /* calculate preview rect size */
589         BLI_init_rctf(viewplane, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
590         uiPanelPush(block);
591         ui_graphics_to_window_rct(sa->win, viewplane, &ri->disprect);
592         uiPanelPop(block);
593         
594         /* correction for gla draw */
595         BLI_translate_rcti(&ri->disprect, -sa->winrct.xmin, -sa->winrct.ymin);
596         
597         *ortho= get_view3d_viewplane(sa->winx, sa->winy, viewplane, clipsta, clipend);
598
599         rectx= ri->disprect.xmax - ri->disprect.xmin;
600         recty= ri->disprect.ymax - ri->disprect.ymin;
601         
602         if(rectx<4 || recty<4) return 0;
603         
604         if(ri->rect && (rectx!=ri->pr_rectx || recty!=ri->pr_recty)) {
605                 MEM_freeN(ri->rect);
606                 ri->rect= NULL;
607         }
608         ri->pr_rectx= rectx;
609         ri->pr_recty= recty;
610         
611         return 1;
612 }
613
614 /* called before a panel gets moved/scaled, makes sure we can see through */
615 void BIF_view3d_previewrender_clear(ScrArea *sa)
616 {
617         View3D *v3d= sa->spacedata.first;
618
619         if(v3d->ri) {
620                 RenderInfo *ri= v3d->ri;
621                 ri->cury= 0;
622                 if(ri->rect)
623                         MEM_freeN(ri->rect);
624                 ri->rect= NULL;
625         }
626 }
627
628 /* afterqueue call */
629 void BIF_view3d_previewrender(ScrArea *sa)
630 {
631         View3D *v3d= sa->spacedata.first;
632         Render *re;
633         RenderInfo *ri; /* preview struct! */
634         RenderStats *rstats;
635         RenderData rdata;
636         rctf viewplane;
637         float clipsta, clipend;
638         int orth;
639         
640         /* first get the render info right */
641         if (!v3d->ri)
642                 ri= v3d->ri= MEM_callocN(sizeof(RenderInfo), "butsrenderinfo");
643         ri= v3d->ri;
644         
645         if(0==view3d_previewrender_get_rects(sa, &viewplane, ri, &clipsta, &clipend, &orth))
646                 return;
647         
648         /* render is finished, so return */
649         if(ri->cury>=ri->pr_rectx) return;
650
651         /* or return with a new event */
652         if(qtest()) {
653                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
654                 return;
655         }
656         
657         /* ok, are we rendering all over? */
658         if(ri->re==NULL) {
659                 char name[32];
660                 
661                 ri->status= 0;
662                 
663                 sprintf(name, "View3dPreview %d", sa->win);
664                 re= ri->re= RE_NewRender(name);
665                 RE_display_draw_cb(re, view3d_previewrender_progress);
666                 RE_stats_draw_cb(re, view3d_previewrender_stats);
667                 RE_test_break_cb(re, qtest);
668                 
669                 /* no osa, blur, seq, for preview render */
670                 rdata= G.scene->r;
671                 rdata.mode &= ~(R_OSA|R_MBLUR|R_DOSEQ);
672                 rdata.layers.first= rdata.layers.last= NULL;
673         
674                 RE_InitState(re, &rdata, sa->winx, sa->winy, &ri->disprect);
675         
676                 if(orth)
677                         RE_SetOrtho(re, &viewplane, clipsta, clipend);
678                 else
679                         RE_SetWindow(re, &viewplane, clipsta, clipend);
680                 
681                 /* until here are no escapes */
682                 ri->status |= PR_DISPRECT;
683         }
684
685         re= ri->re;
686         
687         PIL_sleep_ms(100);      /* wait 0.1 second if theres really no event... */
688         if(qtest()==0)  {
689                 
690                 /* check status */
691                 if((ri->status & PR_DISPRECT)==0) {
692                         RE_SetDispRect(ri->re, &ri->disprect);
693                         if(orth)
694                                 RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
695                         else
696                                 RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
697                         ri->status |= PR_DISPRECT;
698                 }
699                 if((ri->status & PR_DBASE)==0) {
700                         unsigned int lay= G.scene->lay;
701                         
702                         RE_SetView(re, G.vd->viewmat);
703                         
704                         /* allow localview render for objects with lights in normal layers */
705                         if(v3d->lay & 0xFF000000)
706                                 G.scene->lay |= v3d->lay;
707                         else G.scene->lay= v3d->lay;
708                         
709                         RE_Database_FromScene(re, G.scene, 0);          // 0= dont use camera view
710                         G.scene->lay= lay;
711                         
712                         rstats= RE_GetStats(re);
713                         if(rstats->convertdone) 
714                                 ri->status |= PR_DBASE|PR_PROJECTED|PR_ROTATED;
715                 }
716                 if((ri->status & PR_PROJECTED)==0) {
717                         if(ri->status & PR_DBASE) {
718                                 if(orth)
719                                         RE_SetOrtho(ri->re, &viewplane, clipsta, clipend);
720                                 else
721                                         RE_SetWindow(ri->re, &viewplane, clipsta, clipend);
722                                 RE_DataBase_ApplyWindow(re);
723                                 ri->status |= PR_PROJECTED;
724                         }
725                 }
726         
727                 /* OK, can we enter render code? */
728                 if(ri->status==(PR_DISPRECT|PR_DBASE|PR_PROJECTED|PR_ROTATED)) {
729                         RE_TileProcessor(ri->re);
730         
731                         if(ri->rect==NULL)
732                                 ri->rect= MEM_callocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "preview view3d rect");
733                         
734                         RE_ResultGet32(ri->re, ri->rect);
735                 }
736                 
737                 rstats= RE_GetStats(ri->re);
738                 if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
739                         ri->cury= 12000;        /* arbitrary... */
740                         addqueue(sa->win, REDRAW, 1);
741                 }
742                 else {
743                         addafterqueue(curarea->win, RENDERPREVIEW, 1);
744                         ri->cury= 0;
745                 }
746         }
747         else {
748                 addafterqueue(curarea->win, RENDERPREVIEW, 1);
749                 ri->cury= 0;
750         }
751 }
752
753 /* in panel space! */
754 static void view3d_previewdraw_rect(ScrArea *sa, uiBlock *block, RenderInfo *ri)
755 {
756         rctf dispf;
757         
758         if(ri->rect==NULL)
759                 return;
760         
761         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
762         ui_graphics_to_window_rct(sa->win, &dispf, &ri->disprect);
763
764         /* correction for gla draw */
765         BLI_translate_rcti(&ri->disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
766         
767         /* when panel scale changed, free rect */
768         if(ri->disprect.xmax-ri->disprect.xmin != ri->pr_rectx ||
769            ri->disprect.ymax-ri->disprect.ymin != ri->pr_recty) {
770                 MEM_freeN(ri->rect);
771                 ri->rect= NULL;
772         }
773         else {
774                 glaDefine2DArea(&sa->winrct);
775                 glaDrawPixelsSafe(ri->disprect.xmin, ri->disprect.ymin, ri->pr_rectx, ri->pr_recty, ri->pr_rectx, GL_RGBA, GL_UNSIGNED_BYTE, ri->rect);
776         }       
777 }
778
779 /* is panel callback, supposed to be called with correct panel offset matrix */
780 void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block)
781 {
782         View3D *v3d= sa->spacedata.first;
783
784         if (v3d->ri==NULL || v3d->ri->rect==NULL) 
785                 addafterqueue(sa->win, RENDERPREVIEW, 1);
786         else {
787                 view3d_previewdraw_rect(sa, block, v3d->ri);
788                 if(v3d->ri->cury==0) 
789                         addafterqueue(sa->win, RENDERPREVIEW, 1);
790         }
791 }
792