Two in one:
[blender.git] / source / blender / src / renderwin.c
index 95ff209fc903935dcf09c4ae6cc29e14267dbd29..8ca96f89936090edb891d19bfb1e88366ce115ea 100644 (file)
 #include <limits.h>
 
 #include "BLI_blenlib.h"
+#include "BLI_threads.h"
 
 #include "MEM_guardedalloc.h"
 
 #include "BMF_Api.h"
 
-#include "DNA_view3d_types.h"
+#include "DNA_image_types.h"
+#include "DNA_space_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
 #include "DNA_vec_types.h"
 
 #include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
 #include "BKE_scene.h"
 #include "BKE_utildefines.h"
+#include "BKE_writeavi.h"      /* movie handle */
 
+#include "BIF_drawimage.h"
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 #include "BIF_graphics.h"
 #include "BIF_screen.h"
 #include "BIF_space.h"
 #include "BIF_mywindow.h"
-#include "BIF_previewrender.h"
 #include "BIF_renderwin.h"
 #include "BIF_resources.h"
 #include "BIF_toets.h"
+#include "BIF_toolbox.h"
+#include "BIF_writeimage.h"
 
+#include "BDR_sculptmode.h"
 #include "BDR_editobject.h"
 #include "BPY_extern.h" /* for BPY_do_all_scripts */
 
 #include "BSE_filesel.h"
 #include "BSE_headerbuttons.h"
 
+#include "RE_pipeline.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
 #include "blendef.h"
 #include "mydevice.h"
 #include "winlay.h"
-#include "render.h"
 
 /* ------------ renderwin struct, to prevent too much global vars --------- */
 /* ------------ only used for display in a 2nd window  --------- */
 /* forces draw of alpha */
 #define RW_FLAGS_ALPHA         (1<<4)
 
-/* space for info text */
-#define RW_HEADERY             18
 
 typedef struct {
        Window *win;
 
+       int rectx, recty;       /* size of image */
+       
+       int sparex, sparey;     /* spare rect size */
+       unsigned int *rectspare;
+       float *rectsparef;
+       
        float zoom, zoomofs[2];
        int active;
+       short storespare, showspare;
        
-       int mbut[3];
+       int mbut[5];
        int lmouse[2];
        
        unsigned int flags;
@@ -146,17 +165,18 @@ static RenderWin *render_win= NULL;
 /* only called in function open_renderwin */
 static RenderWin *renderwin_alloc(Window *win)
 {
-       RenderWin *rw= MEM_mallocN(sizeof(*rw), "RenderWin");
+       RenderWin *rw= MEM_callocN(sizeof(*rw), "RenderWin");
        rw->win= win;
        rw->zoom= 1.0;
        rw->active= 0;
        rw->flags= 0;
        rw->zoomofs[0]= rw->zoomofs[1]= 0;
        rw->info_text= NULL;
-       rw->render_text= rw->render_text_spare= NULL;
+       rw->render_text= MEM_callocN(RW_MAXTEXT, "rendertext");
+       rw->render_text_spare= MEM_callocN(RW_MAXTEXT, "rendertext spare");
 
        rw->lmouse[0]= rw->lmouse[1]= 0;
-       rw->mbut[0]= rw->mbut[1]= rw->mbut[2]= 0;
+       rw->mbut[0]= rw->mbut[1]= rw->mbut[2]= rw->mbut[3] = rw->mbut[4] = 0;
 
        return rw;
 }
@@ -172,7 +192,7 @@ static void renderwin_reshape(RenderWin *rw)
        ;
 }
 
-static void renderwin_get_disprect(RenderWin *rw, float disprect_r[2][2])
+static void renderwin_get_fullrect(RenderWin *rw, float fullrect_r[2][2])
 {
        float display_w, display_h;
        float cent_x, cent_y;
@@ -181,15 +201,15 @@ static void renderwin_get_disprect(RenderWin *rw, float disprect_r[2][2])
        window_get_size(rw->win, &w, &h);
        h-= RW_HEADERY;
 
-       display_w= R.rectx*rw->zoom;
-       display_h= R.recty*rw->zoom;
-       cent_x= (rw->zoomofs[0] + R.rectx/2)*rw->zoom;
-       cent_y= (rw->zoomofs[1] + R.recty/2)*rw->zoom;
+       display_w= rw->rectx*rw->zoom;
+       display_h= rw->recty*rw->zoom;
+       cent_x= (rw->zoomofs[0] + rw->rectx/2)*rw->zoom;
+       cent_y= (rw->zoomofs[1] + rw->recty/2)*rw->zoom;
        
-       disprect_r[0][0]= w/2 - cent_x;
-       disprect_r[0][1]= h/2 - cent_y;
-       disprect_r[1][0]= disprect_r[0][0] + display_w;
-       disprect_r[1][1]= disprect_r[0][1] + display_h;
+       fullrect_r[0][0]= w/2 - cent_x;
+       fullrect_r[0][1]= h/2 - cent_y;
+       fullrect_r[1][0]= fullrect_r[0][0] + display_w;
+       fullrect_r[1][1]= fullrect_r[0][1] + display_h;
 }
 
        /** 
@@ -198,14 +218,14 @@ static void renderwin_get_disprect(RenderWin *rw, float disprect_r[2][2])
         */
 static int renderwin_win_to_image_co(RenderWin *rw, int winco[2], int imgco_r[2])
 {
-       float disprect[2][2];
+       float fullrect[2][2];
        
-       renderwin_get_disprect(rw, disprect);
+       renderwin_get_fullrect(rw, fullrect);
        
-       imgco_r[0]= (int) ((winco[0]-disprect[0][0])/rw->zoom);
-       imgco_r[1]= (int) ((winco[1]-disprect[0][1])/rw->zoom);
+       imgco_r[0]= (int) ((winco[0]-fullrect[0][0])/rw->zoom);
+       imgco_r[1]= (int) ((winco[1]-fullrect[0][1])/rw->zoom);
        
-       return (imgco_r[0]>=0 && imgco_r[1]>=0 && imgco_r[0]<R.rectx && imgco_r[1]<R.recty);
+       return (imgco_r[0]>=0 && imgco_r[1]>=0 && imgco_r[0]<rw->rectx && imgco_r[1]<rw->recty);
 }
 
        /**
@@ -233,29 +253,17 @@ static void renderwin_set_infotext(RenderWin *rw, char *info_text)
 
 static void renderwin_reset_view(RenderWin *rw)
 {
-       int w, h, rectx, recty;
+       int w, h;
 
        if (rw->info_text) renderwin_set_infotext(rw, NULL);
 
        /* now calculate a zoom for when image is larger than window */
        window_get_size(rw->win, &w, &h);
        h-= RW_HEADERY;
-       
-       /* at this point the r.rectx/y values are not correct yet */
-       rectx= (G.scene->r.size*G.scene->r.xsch)/100;
-       recty= (G.scene->r.size*G.scene->r.ysch)/100;
-       
-       /* crop option makes image smaller */
-       if ((G.scene->r.mode & R_BORDER) && (G.scene->r.mode & R_MOVIECROP)) { 
-               if(!(G.scene->r.scemode & R_OGL)) {
-                       rectx*= (G.scene->r.border.xmax-G.scene->r.border.xmin);
-                       recty*= (G.scene->r.border.ymax-G.scene->r.border.ymin);
-               }
-       }
-       
-       if(rectx>w || recty>h) {
-               if(rectx-w > recty-h) rw->zoom= ((float)w)/((float)rectx);
-               else rw->zoom= ((float)h)/((float)recty);
+
+       if(rw->rectx>w || rw->recty>h) {
+               if(rw->rectx-w > rw->recty-h) rw->zoom= ((float)w)/((float)rw->rectx);
+               else rw->zoom= ((float)h)/((float)rw->recty);
        }
        else rw->zoom= 1.0;
 
@@ -269,6 +277,7 @@ static void renderwin_draw_render_info(RenderWin *rw)
        if(RW_HEADERY) {
                float colf[3];
                rcti rect;
+               char *str;
                
                window_get_size(rw->win, &rect.xmax, &rect.ymax);
                rect.xmin= 0;
@@ -282,24 +291,31 @@ static void renderwin_draw_render_info(RenderWin *rw)
                glClearColor(colf[0], colf[1], colf[2], 1.0); 
                glClear(GL_COLOR_BUFFER_BIT);
                
-               if(rw->render_text) {
+               if(rw->showspare)
+                       str= rw->render_text_spare;
+               else
+                       str= rw->render_text;
+               
+               if(str) {
                        BIF_ThemeColor(TH_TEXT);
                        glRasterPos2i(12, 5);
-                       BMF_DrawString(G.fonts, rw->render_text);
+                       BMF_DrawString(G.fonts, str);
                }
+               
+               BIF_SetTheme(curarea);  // restore theme
        }       
        
 }
 
 static void renderwin_draw(RenderWin *rw, int just_clear)
 {
-       float disprect[2][2];
+       float fullrect[2][2];
        int set_back_mainwindow;
        rcti rect;
-       
+
        /* since renderwin uses callbacks (controlled by ghost) it can
-          mess up active window output with redraw events after a render. 
-          this is patchy, still WIP */
+               mess up active window output with redraw events after a render. 
+               this is patchy, still WIP */
        set_back_mainwindow = (winlay_get_active_window() != rw->win);
        window_make_active(rw->win);
        
@@ -307,7 +323,7 @@ static void renderwin_draw(RenderWin *rw, int just_clear)
        window_get_size(rw->win, &rect.xmax, &rect.ymax);
        rect.ymax-= RW_HEADERY;
        
-       renderwin_get_disprect(rw, disprect);
+       renderwin_get_fullrect(rw, fullrect);
        
        /* do this first, so window ends with correct scissor */
        renderwin_draw_render_info(rw);
@@ -318,27 +334,51 @@ static void renderwin_draw(RenderWin *rw, int just_clear)
        glClearColor(.1875, .1875, .1875, 1.0); 
        glClear(GL_COLOR_BUFFER_BIT);
 
-       if (just_clear || !R.rectot) {
+       if (just_clear) {
                glColor3ub(0, 0, 0);
-               glRectfv(disprect[0], disprect[1]);
+               glRectfv(fullrect[0], fullrect[1]);
        } else {
-               glPixelZoom(rw->zoom, rw->zoom);
-               if(rw->flags & RW_FLAGS_ALPHA) {
-                       char *rect= (char *)R.rectot;
-                       
-                       glColorMask(1, 0, 0, 0);
-                       glaDrawPixelsSafe(disprect[0][0], disprect[0][1], R.rectx, R.recty, rect+3);
-                       glColorMask(0, 1, 0, 0);
-                       glaDrawPixelsSafe(disprect[0][0], disprect[0][1], R.rectx, R.recty, rect+2);
-                       glColorMask(0, 0, 1, 0);
-                       glaDrawPixelsSafe(disprect[0][0], disprect[0][1], R.rectx, R.recty, rect+1);
-                       glColorMask(1, 1, 1, 1);
-                       
+               RenderResult rres;
+               
+               if(rw->showspare) {
+                       rres.rectx= rw->sparex;
+                       rres.recty= rw->sparey;
+                       rres.rect32= rw->rectspare;
+                       rres.rectf= rw->rectsparef;
                }
-               else {
-                       glaDrawPixelsSafe(disprect[0][0], disprect[0][1], R.rectx, R.recty, R.rectot);
+               else
+                       RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
+               
+               if(rres.rectf || rres.rect32) {
+                       
+                       glPixelZoom(rw->zoom, rw->zoom);
+                       if(rw->flags & RW_FLAGS_ALPHA) {
+                               if(rres.rect32) {
+                                       /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
+                                       if(G.order==B_ENDIAN)
+                                               glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+                                       glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_LUMINANCE, GL_UNSIGNED_INT, rres.rect32);
+                                       glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+                               }
+                               else {
+                                       float *trectf= MEM_mallocN(rres.rectx*rres.recty*4, "temp");
+                                       int a, b;
+                                       
+                                       for(a= rres.rectx*rres.recty -1, b= 4*a+3; a>=0; a--, b-=4)
+                                               trectf[a]= rres.rectf[b];
+                                       
+                                       glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_LUMINANCE, GL_FLOAT, trectf);
+                                       MEM_freeN(trectf);
+                               }
+                       }
+                       else {
+                               if(rres.rect32)
+                                       glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rres.rect32);
+                               else if(rres.rectf)
+                                       glaDrawPixelsSafe_to32(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, rres.rectf);
+                       }
+                       glPixelZoom(1.0, 1.0);
                }
-               glPixelZoom(1.0, 1.0);
        }
        
        /* info text is overlayed on bottom */
@@ -360,25 +400,48 @@ static void renderwin_draw(RenderWin *rw, int just_clear)
        if (set_back_mainwindow) mainwindow_make_active();      
 }
 
+
 /* ------ interactivity calls for RenderWin ------------- */
+static void renderwin_zoom(RenderWin *rw, int ZoomIn) {
+       if (ZoomIn) {
+               if (rw->zoom>0.26) {
+                       if(rw->zoom>1.0 && rw->zoom<2.0) rw->zoom= 1.0;
+                       else rw->zoom*= 0.5;
+               }
+       } else {
+               if (rw->zoom<15.9) {
+                       if(rw->zoom>0.5 && rw->zoom<1.0) rw->zoom= 1.0;
+                       else rw->zoom*= 2.0;
+               }
+       }
+       if (rw->zoom>1.0) rw->flags |= RW_FLAGS_OLDZOOM;
+       if (rw->zoom==1.0) rw->flags &= ~RW_FLAGS_OLDZOOM;
+       renderwin_queue_redraw(rw);
+}
 
 static void renderwin_mouse_moved(RenderWin *rw)
 {
+       RenderResult rres;
+       
+       RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
+
        if (rw->flags & RW_FLAGS_PIXEL_EXAMINING) {
-               int imgco[2];
-               char buf[64];
-               int *pxlz;      // zbuffer is signed 
+               int imgco[2], ofs=0;
+               char buf[128];
                char *pxl;
 
-               if (R.rectot && renderwin_win_to_image_co(rw, rw->lmouse, imgco)) {
-                       pxl= (char*) &R.rectot[R.rectx*imgco[1] + imgco[0]];
-                       
-                       if (R.rectz) {
-                               pxlz= &R.rectz[R.rectx*imgco[1] + imgco[0]];                    
-                               sprintf(buf, "R: %d, G: %d, B: %d, A: %d, Z: %f", pxl[0], pxl[1], pxl[2], pxl[3], 0.5+0.5*( ((float)*pxlz)/(float)INT_MAX) );
+               if (renderwin_win_to_image_co(rw, rw->lmouse, imgco)) {
+                       if (rres.rect32) {
+                               pxl= (char*) &rres.rect32[rres.rectx*imgco[1] + imgco[0]];
+                               ofs= sprintf(buf, "R: %d G: %d B: %d A: %d", pxl[0], pxl[1], pxl[2], pxl[3]);   
                        }
-                       else {
-                               sprintf(buf, "R: %d, G: %d, B: %d, A: %d", pxl[0], pxl[1], pxl[2], pxl[3]);                     
+                       if (rres.rectf) {
+                               float *pxlf= rres.rectf + 4*(rres.rectx*imgco[1] + imgco[0]);
+                               ofs+= sprintf(buf+ofs, " | R: %.3f G: %.3f B: %.3f A: %.3f ", pxlf[0], pxlf[1], pxlf[2], pxlf[3]);
+                       }
+                       if (rres.rectz) {
+                               float *pxlz= &rres.rectz[rres.rectx*imgco[1] + imgco[0]];                       
+                               sprintf(buf+ofs, "| Z: %.3f", *pxlz );
                        }
 
                        renderwin_set_infotext(rw, buf);
@@ -394,8 +457,8 @@ static void renderwin_mouse_moved(RenderWin *rw)
        
                rw->zoomofs[0]= rw->pan_ofs_start[0] - delta_x/rw->zoom;
                rw->zoomofs[1]= rw->pan_ofs_start[1] - delta_y/rw->zoom;
-               rw->zoomofs[0]= CLAMPIS(rw->zoomofs[0], -R.rectx/2, R.rectx/2);
-               rw->zoomofs[1]= CLAMPIS(rw->zoomofs[1], -R.recty/2, R.recty/2);
+               rw->zoomofs[0]= CLAMPIS(rw->zoomofs[0], -rres.rectx/2, rres.rectx/2);
+               rw->zoomofs[1]= CLAMPIS(rw->zoomofs[1], -rres.recty/2, rres.recty/2);
 
                renderwin_queue_redraw(rw);
        } 
@@ -407,8 +470,8 @@ static void renderwin_mouse_moved(RenderWin *rw)
                h-= RW_HEADERY;
                renderwin_win_to_ndc(rw, rw->lmouse, ndc);
 
-               rw->zoomofs[0]= -0.5*ndc[0]*(w-R.rectx*rw->zoom)/rw->zoom;
-               rw->zoomofs[1]= -0.5*ndc[1]*(h-R.recty*rw->zoom)/rw->zoom;
+               rw->zoomofs[0]= -0.5*ndc[0]*(w-rres.rectx*rw->zoom)/rw->zoom;
+               rw->zoomofs[1]= -0.5*ndc[1]*(h-rres.recty*rw->zoom)/rw->zoom;
 
                renderwin_queue_redraw(rw);
        }
@@ -425,8 +488,13 @@ static void renderwin_mousebut_changed(RenderWin *rw)
                rw->pan_mouse_start[1]= rw->lmouse[1];
                rw->pan_ofs_start[0]= rw->zoomofs[0];
                rw->pan_ofs_start[1]= rw->zoomofs[1];
-       } 
-       else {
+       } else if (rw->mbut[3]) {
+               renderwin_zoom(rw, 0);
+               rw->mbut[3]=0;
+       } else if (rw->mbut[4]) {
+               renderwin_zoom(rw, 1);
+               rw->mbut[4]=0;
+       } else {
                if (rw->flags & RW_FLAGS_PANNING) {
                        rw->flags &= ~RW_FLAGS_PANNING;
                        renderwin_queue_redraw(rw);
@@ -446,7 +514,7 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
        RenderWin *rw= user_data;
 
        // added this for safety, while render it's just creating bezerk results
-       if(R.flag & R_RENDERING) {
+       if(G.rendering) {
                if(evt==ESCKEY && val) 
                        rw->flags|= RW_FLAGS_ESCAPE;
                return;
@@ -473,6 +541,11 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
                rw->lmouse[evt==MOUSEY]= val;
                renderwin_mouse_moved(rw);
        } 
+       else if (ELEM(evt, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+               int which=(evt==WHEELUPMOUSE?3:4); 
+               rw->mbut[which]=val;
+               renderwin_mousebut_changed(rw);
+       }
        else if (ELEM3(evt, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
                int which= (evt==LEFTMOUSE)?0:(evt==MIDDLEMOUSE)?1:2;
                rw->mbut[which]= val;
@@ -496,7 +569,7 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
                        renderwin_queue_redraw(render_win);
                }
                else if (evt==JKEY) {
-                       if(R.flag==0) BIF_swap_render_rects();
+                       if(G.rendering==0) BIF_swap_render_rects();
                } 
                else if (evt==ZKEY) {
                        if (rw->flags&RW_FLAGS_OLDZOOM) {
@@ -508,19 +581,11 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
                                renderwin_mouse_moved(rw);
                        }
                } 
-               else if (evt==PADPLUSKEY) {
-                       if (rw->zoom<15.9) {
-                               if(rw->zoom>0.5 && rw->zoom<1.0) rw->zoom= 1.0;
-                               else rw->zoom*= 2.0;
-                               renderwin_queue_redraw(rw);
-                       }
+               else if (ELEM(evt,PADPLUSKEY,PAGEUPKEY))  {
+                       renderwin_zoom(rw, 0);
                } 
-               else if (evt==PADMINUS) {
-                       if (rw->zoom>0.26) {
-                               if(rw->zoom>1.0 && rw->zoom<2.0) rw->zoom= 1.0;
-                               else rw->zoom*= 0.5;
-                               renderwin_queue_redraw(rw);
-                       }
+               else if (ELEM(evt,PADMINUS,PAGEDOWNKEY)) {
+                       renderwin_zoom(rw, 1);
                } 
                else if (evt==PADENTER || evt==HOMEKEY) {
                        if (rw->flags&RW_FLAGS_OLDZOOM) {
@@ -529,20 +594,20 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
                        renderwin_reset_view(rw);
                } 
                else if (evt==F3KEY) {
-                       if(R.flag==0) {
+                       if(G.rendering==0) {
                                mainwindow_raise();
                                mainwindow_make_active();
                                rw->active= 0;
                                areawinset(find_biggest_area()->win);
-                               BIF_save_rendered_image();
+                               BIF_save_rendered_image_fs();
                        }
                } 
                else if (evt==F11KEY) {
                        BIF_toggle_render_display();
                } 
                else if (evt==F12KEY) {
-                       /* if it's rendering, this flag is set */
-                       if(R.flag==0) BIF_do_render(0);
+                       if(G.rendering==0) 
+                               BIF_do_render(0);
                }
        }
 }
@@ -555,8 +620,8 @@ static char *renderwin_get_title(int doswap)
        swap+= doswap;
        
        if(swap & 1) {
-               if (G.scene->r.renderer==R_YAFRAY) title = "YafRay:Render (spare)";
-               else title = "Blender:Render (spare)";
+               if (G.scene->r.renderer==R_YAFRAY) title = "YafRay:Render (previous)";
+               else title = "Blender:Render (previous)";
        }
        else {
                if (G.scene->r.renderer==R_YAFRAY) title = "YafRay:Render";
@@ -567,7 +632,7 @@ static char *renderwin_get_title(int doswap)
 }
 
 /* opens window and allocs struct */
-static void open_renderwin(int winpos[2], int winsize[2])
+static void open_renderwin(int winpos[2], int winsize[2], int imagesize[2])
 {
        extern void mywindow_build_and_set_renderwin( int orx, int ory, int sizex, int sizey); // mywindow.c
        Window *win;
@@ -577,7 +642,9 @@ static void open_renderwin(int winpos[2], int winsize[2])
        win= window_open(title, winpos[0], winpos[1], winsize[0], winsize[1]+RW_HEADERY, 0);
 
        render_win= renderwin_alloc(win);
-
+       render_win->rectx= imagesize[0];
+       render_win->recty= imagesize[1];
+       
        /* Ghost calls handler */
        window_set_handler(win, renderwin_handler, render_win);
 
@@ -597,35 +664,20 @@ static void open_renderwin(int winpos[2], int winsize[2])
 /* -------------- callbacks for render loop: Window (RenderWin) ----------------------- */
 
 /* calculations for window size and position */
-void calc_renderwin_rectangle(int posmask, int renderpos_r[2], int rendersize_r[2]) 
+void calc_renderwin_rectangle(int rectx, int recty, int posmask, int renderpos_r[2], int rendersize_r[2]) 
 {
        int scr_w, scr_h, x, y, div= 0;
        float ndc_x= 0.0, ndc_y= 0.0;
 
-               /* XXX, we temporarily hack the screen size and position so
-                * the window is always 60 pixels away from a side, really need
-                * a GHOST_GetMaxWindowBounds or so - zr
-                */
        winlay_get_screensize(&scr_w, &scr_h);
-       
-       rendersize_r[0]= (G.scene->r.size*G.scene->r.xsch)/100;
-       rendersize_r[1]= (G.scene->r.size*G.scene->r.ysch)/100;
-       
-       /* crop option makes image smaller */
-       if ((G.scene->r.mode & R_BORDER) && (G.scene->r.mode & R_MOVIECROP)) { 
-               rendersize_r[0]*= (G.scene->r.border.xmax-G.scene->r.border.xmin);
-               rendersize_r[1]*= (G.scene->r.border.ymax-G.scene->r.border.ymin);
-       }
-       
-       if(G.scene->r.mode & R_PANORAMA) {
-               rendersize_r[0]*= G.scene->r.xparts;
-               rendersize_r[1]*= G.scene->r.yparts;
-       }
-       /* increased size of clipping for OSX, should become an option instead */
-       rendersize_r[0]= CLAMPIS(rendersize_r[0], 100, scr_w-120);
-       rendersize_r[1]= CLAMPIS(rendersize_r[1], 100, scr_h-120);
 
-       for (y=-1; y<=1; y++) {
+       rendersize_r[0]= rectx;
+       rendersize_r[1]= recty;
+
+       rendersize_r[0]= CLAMPIS(rendersize_r[0], 0, scr_w);     
+       rendersize_r[1]= CLAMPIS(rendersize_r[1], 0, scr_h-RW_HEADERY);  
+       
+       for (y=-1; y<=1; y++) {
                for (x=-1; x<=1; x++) {
                        if (posmask & (1<<((y+1)*3 + (x+1)))) {
                                ndc_x+= x;
@@ -639,21 +691,30 @@ void calc_renderwin_rectangle(int posmask, int renderpos_r[2], int rendersize_r[
                ndc_x/= div;
                ndc_y/= div;
        }
-               
-       renderpos_r[0]= 60 + (scr_w-90-rendersize_r[0])*(ndc_x*0.5 + 0.5);
-       renderpos_r[1]= 30 + (scr_h-90-rendersize_r[1])*(ndc_y*0.5 + 0.5);
+       
+       renderpos_r[0]= (scr_w-rendersize_r[0])*(ndc_x*0.5 + 0.5);
+#ifdef __APPLE__
+       /* 44 pixels is topbar and window header... awaiting better fixes in ghost :) */
+       rendersize_r[1]= CLAMPIS(rendersize_r[1], 0, scr_h-44-RW_HEADERY);       
+       renderpos_r[1]= -44-RW_HEADERY+(scr_h-rendersize_r[1])*(ndc_y*0.5 + 0.5);
+#else
+       renderpos_r[1]= -RW_HEADERY+(scr_h-rendersize_r[1])*(ndc_y*0.5 + 0.5);
+#endif
 }
        
 /* init renderwin, alloc/open/resize */
-static void renderwin_init_display_cb(void
+static void renderwin_init_display_cb(RenderResult *rr
 {
-       if (G.afbreek == 0) {
-               int rendersize[2], renderpos[2];
+       if (G.afbreek != 1) {
+               int rendersize[2], renderpos[2], imagesize[2];
 
-               calc_renderwin_rectangle(G.winpos, renderpos, rendersize);
+               calc_renderwin_rectangle(rr->rectx, rr->recty, G.winpos, renderpos, rendersize);
+               
+               imagesize[0]= rr->rectx;
+               imagesize[1]= rr->recty;
 
                if (!render_win) {
-                       open_renderwin(renderpos, rendersize);
+                       open_renderwin(renderpos, rendersize, imagesize);
                        renderwin_reset_view(render_win); // incl. autozoom for large images
                } else {
                        int win_x, win_y;
@@ -676,7 +737,7 @@ static void renderwin_init_display_cb(void)
                                 */
                        if(rendersize[0]!= win_w || rendersize[1]!= win_h) {
                                BIF_close_render_display();
-                               open_renderwin(renderpos, rendersize);
+                               open_renderwin(renderpos, rendersize, imagesize);
                        }
                        else {
                                window_raise(render_win->win);
@@ -693,19 +754,20 @@ static void renderwin_init_display_cb(void)
                        }
 
                        renderwin_reset_view(render_win);
-                       render_win->flags&= ~RW_FLAGS_ESCAPE;
                        render_win->active= 1;
                }
                /* make sure we are in normal draw again */
                render_win->flags &= ~RW_FLAGS_ALPHA;
+               
+               glFinish();
        }
 }
 
 /* callback for redraw render win */
-static void renderwin_clear_display_cb(short ignore
+static void renderwin_clear_display_cb(RenderResult *rr
 {
        if (render_win) {
-               window_make_active(render_win->win);    
+               window_make_active(render_win->win);
                renderwin_draw(render_win, 1);
        }
 }
@@ -719,205 +781,163 @@ static void renderwin_clear_display_cb(short ignore)
 * Note: blocked queue handling while rendering to prevent that (ton)
 */
 
-/* in render window; display a couple of scanlines of rendered image (see callback below) */
-static void renderwin_progress(RenderWin *rw, int start_y, int nlines, int rect_w, int rect_h, unsigned char *rect)
+/* can get as well the full picture, as the parts while rendering */
+static void renderwin_progress(RenderWin *rw, RenderResult *rr, volatile rcti *renrect)
 {
-       float disprect[2][2];
        rcti win_rct;
-
+       float *rectf= NULL, fullrect[2][2];
+       unsigned int *rect32= NULL;
+       int ymin, ymax, xmin, xmax;
+       
+       /* if renrect argument, we only display scanlines */
+       if(renrect) {
+                /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
+               if(rr->renlay==NULL || renrect->ymax>=rr->recty)
+                       return;
+               
+               /* xmin here is first subrect x coord, xmax defines subrect width */
+               xmin = renrect->xmin;
+               xmax = renrect->xmax - xmin;
+               if (xmax<2) return;
+               
+               ymin= renrect->ymin;
+               ymax= renrect->ymax - ymin;
+               if(ymax<2)
+                       return;
+               renrect->ymin= renrect->ymax;
+       }
+       else {
+               xmin = ymin = 0;
+               xmax = rr->rectx - 2*rr->crop;
+               ymax = rr->recty - 2*rr->crop;
+       }
+       
+       /* renderwindow cruft */
        win_rct.xmin= win_rct.ymin= 0;
        window_get_size(rw->win, &win_rct.xmax, &win_rct.ymax);
        win_rct.ymax-= RW_HEADERY;
+       renderwin_get_fullrect(rw, fullrect);
+       
+       /* find current float rect for display, first case is after composit... still weak */
+       if(rr->rectf)
+               rectf= rr->rectf;
+       else {
+               if(rr->rect32)
+                       rect32= rr->rect32;
+               else {
+                       if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
+                       rectf= rr->renlay->rectf;
+               }
+       }
+       if(rectf) {
+               /* if scanline updates... */
+               rectf+= 4*(rr->rectx*ymin + xmin);
        
-       renderwin_get_disprect(rw, disprect);
+               /* when rendering more pixels than needed, we crop away cruft */
+               if(rr->crop)
+                       rectf+= 4*(rr->crop*rr->rectx + rr->crop);
+       }
        
-       /* for efficiency & speed; not drawing in Blender UI while rendering */
-       //window_make_active(rw->win);
+       /* tilerect defines drawing offset from (0,0) */
+       /* however, tilerect (xmin, ymin) is first pixel */
+       fullrect[0][0] += (rr->tilerect.xmin + rr->crop + xmin)*rw->zoom;
+       fullrect[0][1] += (rr->tilerect.ymin + rr->crop + ymin)*rw->zoom;
 
        glEnable(GL_SCISSOR_TEST);
        glaDefine2DArea(&win_rct);
 
+#ifdef __APPLE__
+#else
        glDrawBuffer(GL_FRONT);
+#endif
        glPixelZoom(rw->zoom, rw->zoom);
-       glaDrawPixelsSafe(disprect[0][0], disprect[0][1] + start_y*rw->zoom, rect_w, nlines, &rect[start_y*rect_w*4]);
+
+       if(rect32)
+               glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], xmax, ymax, rr->rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect32);
+       else
+               glaDrawPixelsSafe_to32(fullrect[0][0], fullrect[0][1], xmax, ymax, rr->rectx, rectf);
+       
        glPixelZoom(1.0, 1.0);
+       
+#ifdef __APPLE__
+       window_swap_buffers(render_win->win);
+#else
        glFlush();
        glDrawBuffer(GL_BACK);
+#endif 
 }
 
 
 /* in render window; display a couple of scanlines of rendered image */
-static void renderwin_progress_display_cb(int y1, int y2, int w, int h, unsigned int *rect)
+static void renderwin_progress_display_cb(RenderResult *rr, volatile rcti *rect)
 {
        if (render_win) {
-               renderwin_progress(render_win, y1, y2-y1+1, w, h, (unsigned char*) rect);
+               renderwin_progress(render_win, rr, rect);
        }
 }
 
+/* -------------- callbacks for render loop: interactivity ----------------------- */
 
-/* -------------- callbacks for render loop: in View3D ----------------------- */
-
-
-static View3D *render_view3d = NULL;
-
-/* init Render view callback */
-static void renderview_init_display_cb(void)
-{
-       ScrArea *sa;
-
-               /* Choose the first view with a persp camera,
-                * if one doesn't exist we will get the first
-                * View3D window.
-                */ 
-       render_view3d= NULL;
-       for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
-               if (sa->win && sa->spacetype==SPACE_VIEW3D) {
-                       View3D *vd= sa->spacedata.first;
-                       
-                       if (vd->persp==2 && vd->camera==G.scene->camera) {
-                               render_view3d= vd;
-                               break;
-                       } else if (!render_view3d) {
-                               render_view3d= vd;
-                       }
-               }
-       }
-}
-
-
-/* in 3d view; display a couple of scanlines of rendered image */
-static void renderview_progress_display_cb(int y1, int y2, int w, int h, unsigned int *rect)
+/* string is RW_MAXTEXT chars min */
+void make_renderinfo_string(RenderStats *rs, char *str)
 {
-       if (render_view3d) {
-               View3D *v3d= render_view3d;
-               int nlines= y2-y1+1;
-               float sx, sy, facx, facy;
-               rcti win_rct, vb;
-
-               calc_viewborder(v3d, &vb);
-               
-               /* if border render  */
-               if(G.scene->r.mode & R_BORDER) { 
-                       
-                       /* but, if image is full (at end of border render, without crop) we don't */
-                       if(R.rectx != (G.scene->r.size*G.scene->r.xsch)/100 ||
-                          R.recty != (G.scene->r.size*G.scene->r.ysch)/100 ) {
-                       
-                               facx= (float) (vb.xmax-vb.xmin);
-                               facy= (float) (vb.ymax-vb.ymin);
-                               
-                               vb.xmax= vb.xmin + facx*G.scene->r.border.xmax;
-                               vb.ymax= vb.ymin + facy*G.scene->r.border.ymax;
-                               vb.xmin+= facx*G.scene->r.border.xmin;
-                               vb.ymin+= facy*G.scene->r.border.ymin;
-                       }
-               }
-                       
-               facx= (float) (vb.xmax-vb.xmin)/R.rectx;
-               facy= (float) (vb.ymax-vb.ymin)/R.recty;
-
-               bwin_get_rect(v3d->area->win, &win_rct);
-
-               glaDefine2DArea(&win_rct);
+       extern char info_time_str[32];  // header_info.c
+       extern unsigned long mem_in_use, mmap_in_use;
+       float megs_used_memory, mmap_used_memory;
+       char *spos= str;
+       
+       megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
+       mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
+       
+       if(G.scene->lay & 0xFF000000)
+               spos+= sprintf(spos, "Localview | ");
+       else if(G.scene->r.scemode & R_SINGLE_LAYER)
+               spos+= sprintf(spos, "Single Layer | ");
+       
+       if(rs->tothalo)
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->tothalo, rs->totlamp, megs_used_memory, mmap_used_memory);
+       else 
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d La:%d Mem:%.2fM (%.2fM) ", (G.scene->r.cfra), rs->totvert, rs->totface, rs->totlamp, megs_used_memory, mmap_used_memory);
+       
+       if(rs->curfield)
+               spos+= sprintf(spos, "Field %d ", rs->curfield);
+       if(rs->curblur)
+               spos+= sprintf(spos, "Blur %d ", rs->curblur);
+       
+       BLI_timestr(rs->lastframetime, info_time_str);
+       spos+= sprintf(spos, "Time:%s ", info_time_str);
+       
+       if(rs->infostr)
+               spos+= sprintf(spos, "| %s ", rs->infostr);
+       
+       /* very weak... but 512 characters is quite safe... we cannot malloc during thread render */
+       if(spos >= str+RW_MAXTEXT)
+               printf("WARNING! renderwin text beyond limit \n");
        
-               glDrawBuffer(GL_FRONT);
-               
-               sx= vb.xmin;
-               sy= vb.ymin + facy*y1;
-
-               glPixelZoom(facx, facy);
-               glaDrawPixelsSafe(sx, sy, w, nlines, rect+w*y1);
-               glPixelZoom(1.0, 1.0);
-
-               glFlush();
-               glDrawBuffer(GL_BACK);
-               v3d->flag |= V3D_DISPIMAGE;
-               v3d->area->win_swap= WIN_FRONT_OK;
-               
-       }
-}
-
-/* in 3d view; display stats of rendered image */
-static void renderview_draw_render_info(char *str)
-{
-       if (render_view3d) {
-               View3D *v3d= render_view3d;
-               rcti vb, win_rct;
-               
-               calc_viewborder(v3d, &vb);
-               
-               bwin_get_rect(v3d->area->win, &win_rct);
-               glaDefine2DArea(&win_rct);
-               
-               glDrawBuffer(GL_FRONT);
-               
-               /* clear header rect */
-               BIF_ThemeColor(TH_HEADER);
-               glRecti(vb.xmin, vb.ymax, vb.xmax, vb.ymax+RW_HEADERY);
-               
-               if(str) {
-                       BIF_ThemeColor(TH_TEXT);
-                       glRasterPos2i(vb.xmin+12, vb.ymax+5);
-                       BMF_DrawString(G.fonts, str);
-               }
-               
-               glFlush();
-               glDrawBuffer(GL_BACK);
-
-               v3d->area->win_swap= WIN_FRONT_OK;
-               
-       }
 }
 
-
-/* -------------- callbacks for render loop: interactivity ----------------------- */
-
-
 /* callback for print info in top header of renderwin */
-/* time is only not zero on last call, we then don't update the other stats */ 
-static void printrenderinfo_cb(double time, int sample)
+static void renderwin_renderinfo_cb(RenderStats *rs)
 {
-       extern int mem_in_use;
-       static int totvert=0, totvlak=0, tothalo=0, totlamp=0;
-       static float megs_used_memory=0.0;
-       char str[300], *spos= str;
-               
-       if(time==0.0) {
-               megs_used_memory= mem_in_use/(1024.0*1024.0);
-               totvert= R.totvert;
-               totvlak= R.totvlak;
-               totlamp= R.totlamp;
-               tothalo= R.tothalo;
-       }
-       
-       if(tothalo)
-               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d Ha:%d La:%d Mem:%.2fM", (G.scene->r.cfra), totvert, totvlak, tothalo, totlamp, megs_used_memory);
-       else 
-               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d La:%d Mem:%.2fM", (G.scene->r.cfra), totvert, totvlak, totlamp, megs_used_memory);
-
-       if(time==0.0) {
-               if (R.r.mode & R_FIELDS) {
-                       spos+= sprintf(spos, "Field %c ", (R.flag&R_SEC_FIELD)?'B':'A');
-               }
-               if (sample!=-1) {
-                       spos+= sprintf(spos, "Sample: %d    ", sample);
-               }
-       }
-       else {
-               extern char info_time_str[32];  // header_info.c
-               timestr(time, info_time_str);
-               spos+= sprintf(spos, " Time:%s ", info_time_str);
-       }
        
        if(render_win) {
-               if(render_win->render_text) MEM_freeN(render_win->render_text);
-               render_win->render_text= BLI_strdup(str);
+               
+               make_renderinfo_string(rs, render_win->render_text);
+               
+#ifdef __APPLE__
+#else
                glDrawBuffer(GL_FRONT);
+#endif
                renderwin_draw_render_info(render_win);
+               
+#ifdef __APPLE__
+               window_swap_buffers(render_win->win);
+#else
                glFlush();
                glDrawBuffer(GL_BACK);
+#endif
        }
-       else renderview_draw_render_info(str);
+
 }
 
 /* -------------- callback system to allow ESC from rendering ----------------------- */
@@ -973,6 +993,17 @@ static void end_test_break_callback()
 #else
 /* all other OS's support signal(SIGVTALRM) */
 
+/* XXX The ESC problem: some unix users reported that ESC doesn't cancel
+ * renders anymore. Most complaints came from linux, but it's not
+ * general, not all linux users have the problem.
+ *
+ * From tests, the systems that do have it are not signalling SIGVTALRM
+ * interrupts (an issue with signals and threads). Using SIGALRM instead
+ * fixes the problem, at least while we investigate better.
+ *
+ * ITIMER_REAL (SIGALRM): timer that counts real system time
+ * ITIMER_VIRTUAL (SIGVTALRM): only counts time spent in its owner process */
+
 /* POSIX: this function goes in the signal() callback */
 static void interruptESC(int sig)
 {
@@ -980,7 +1011,7 @@ static void interruptESC(int sig)
        if(G.afbreek==0) G.afbreek= 2;  /* code for read queue */
 
        /* call again, timer was reset */
-       signal(SIGVTALRM, interruptESC);
+       signal(SIGALRM, interruptESC);
 }
 
 /* POSIX: initialize timer and signal */
@@ -991,13 +1022,12 @@ static void init_test_break_callback()
 
        tmevalue.it_interval.tv_sec = 0;
        tmevalue.it_interval.tv_usec = 250000;
-       /* wanneer de eerste ? */
+       /* when the first ? */
        tmevalue.it_value.tv_sec = 0;
        tmevalue.it_value.tv_usec = 10000;
 
-       signal(SIGVTALRM, interruptESC);
-       setitimer(ITIMER_VIRTUAL, &tmevalue, 0);
-
+       signal(SIGALRM, interruptESC);
+       setitimer(ITIMER_REAL, &tmevalue, 0);
 }
 
 /* POSIX: stop timer and callback */
@@ -1005,10 +1035,10 @@ static void end_test_break_callback()
 {
        struct itimerval tmevalue;
 
-       tmevalue.it_value.tv_sec = 0;
-       tmevalue.it_value.tv_usec = 0;
-       setitimer(ITIMER_VIRTUAL, &tmevalue, 0);
-       signal(SIGVTALRM, SIG_IGN);
+       memset(&tmevalue, 0, sizeof(struct itimerval));
+
+       setitimer(ITIMER_REAL, &tmevalue, 0);
+       signal(SIGALRM, SIG_IGN);
 
 }
 
@@ -1021,134 +1051,167 @@ static void end_test_break_callback()
 
 
 /* - initialize displays
-   - both opengl render as blender render
    - set callbacks
    - cleanup
 */
 
-static void do_render(View3D *ogl_render_view3d, int anim, int force_dispwin)
+static void do_render(int anim)
 {
+       Image *ima;
+       Render *re= RE_NewRender(G.scene->id.name);
+       unsigned int lay= G.scene->lay;
+       int scemode= G.scene->r.scemode;
+       int sculptmode= G.f & G_SCULPTMODE;
        
-       /* we set this flag to prevent renderwindow queue to execute another render */
-       R.flag= R_RENDERING;
-       G.afbreek= 0;
+       /* UGLY! we set this flag to prevent renderwindow queue to execute another render */
+       /* is reset in RE_BlenderFrame */
+       G.rendering= 1;
 
-       if (G.displaymode == R_DISPLAYWIN || force_dispwin) {
-               RE_set_initrenderdisplay_callback(NULL);
-               RE_set_clearrenderdisplay_callback(renderwin_clear_display_cb);
-               RE_set_renderdisplay_callback(renderwin_progress_display_cb);
-
-               renderwin_init_display_cb();
-       } 
-       else {
-               BIF_close_render_display();
-               RE_set_initrenderdisplay_callback(renderview_init_display_cb);
-               RE_set_clearrenderdisplay_callback(NULL);
-               RE_set_renderdisplay_callback(renderview_progress_display_cb);
-       }
-
-       init_test_break_callback();
-       RE_set_test_break_callback(test_break);
-       
-       RE_set_timecursor_callback(set_timecursor);
-       RE_set_printrenderinfo_callback(printrenderinfo_cb);
+       /* set render callbacks, also starts ESC timer */
+       BIF_init_render_callbacks(re, 1);
        
-       if (render_win) {
-               window_set_cursor(render_win->win, CURSOR_WAIT);
-               // when opening new window... not cross platform identical behaviour, so
-               // for now call it each time
-               // if(ogl_render_view3d) init_gl_stuff();
-       }
        waitcursor(1);
-
-       if(G.obedit && !(G.scene->r.scemode & R_OGL)) {
+       if(render_win) 
+               window_set_cursor(render_win->win, CURSOR_WAIT);
+       
+       if(G.obedit)
                exit_editmode(0);       /* 0 = no free data */
-       }
 
-       if(anim) {
-               RE_animrender(ogl_render_view3d);
-       }
-       else {
-               RE_initrender(ogl_render_view3d);
-       }
+       if(sculptmode) set_sculptmode();
 
-       scene_update_for_newframe(G.scene, G.scene->lay);       // no redraw needed, this restores to view as we left it
+       /* allow localview render for objects with lights in normal layers */
+       if(curarea->spacetype==SPACE_VIEW3D) {
+               if(G.vd->lay & 0xFF000000) {
+                       G.scene->lay |= G.vd->lay;
+                       G.scene->r.scemode |= R_SINGLE_LAYER;
+               }
+               else G.scene->lay= G.vd->lay;
+       }
+       
+       if(anim)
+               RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
+       else
+               RE_BlenderFrame(re, G.scene, G.scene->r.cfra);
+
+       /* restore local view exception */
+       G.scene->lay= lay;
+       G.scene->r.scemode= scemode;
+       
+       if(render_win) window_set_cursor(render_win->win, CURSOR_STD);
        
-       if (render_win) window_set_cursor(render_win->win, CURSOR_STD);
-
        free_filesel_spec(G.scene->r.pic);
 
        G.afbreek= 0;
-       end_test_break_callback();
+       BIF_end_render_callbacks();
+       
+       /* after an envmap creation...  */
+//             if(R.flag & R_REDRAW_PRV) {
+//                     BIF_preview_changed(ID_TE);
+//             }
+               
+       scene_update_for_newframe(G.scene, G.scene->lay);       // no redraw needed, this restores to view as we left it
        
-       /* in dispiew it will destroy the image otherwise
-          window_make_active() raises window at osx and sends redraws */
-       if(G.displaymode==R_DISPLAYWIN) {
-               mainwindow_make_active();
+       /* get a render result image, and make sure it is clean */
+       ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
+       BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
        
-               /* after an envmap creation...  */
-               if(R.flag & R_REDRAW_PRV) {
-                       BIF_all_preview_changed();
-               }
-               allqueue(REDRAWBUTSSCENE, 0);   // visualize fbuf for example
-       }
+       if(sculptmode) set_sculptmode();
        
-       R.flag= 0;
-       waitcursor(0);  // waitcursor checks rendering R.flag...
+       waitcursor(0);
 }
 
-/* finds area with a 'dispview' set */
-static ScrArea *find_dispimage_v3d(void)
+/* called before render, store old render in spare buffer */
+static void renderwin_store_spare(void)
 {
-       ScrArea *sa;
+       RenderResult rres;
        
-       for (sa= G.curscreen->areabase.first; sa; sa= sa->next) {
-               if (sa->spacetype==SPACE_VIEW3D) {
-                       View3D *vd= sa->spacedata.first;
-                       if (vd->flag & V3D_DISPIMAGE)
-                               return sa;
-               }
-       }
+       if(render_win==0 || render_win->storespare==0)
+               return;
+       
+       /* only store when it does not show spare */
+       if(render_win->showspare==0)
+               return;
+       
+       render_win->showspare= 0;
+       window_set_title(render_win->win, renderwin_get_title(1));
+       
+       BLI_strncpy(render_win->render_text_spare, render_win->render_text, RW_MAXTEXT);
+       
+       if(render_win->rectspare) MEM_freeN(render_win->rectspare);
+       render_win->rectspare= NULL;
+       if(render_win->rectsparef) MEM_freeN(render_win->rectsparef);
+       render_win->rectsparef= NULL;
        
-       return NULL;
+       RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
+       
+       if(rres.rect32)
+               render_win->rectspare= MEM_dupallocN(rres.rect32);
+       else if(rres.rectf)
+               render_win->rectsparef= MEM_dupallocN(rres.rectf);
+
+       render_win->sparex= rres.rectx;
+       render_win->sparey= rres.recty;
 }
 
-/* used for swapping with spare buffer, when images are different size */
-static void scalefastrect(unsigned int *recto, unsigned int *rectn, int oldx, int oldy, int newx, int newy)
+/* -------------- API: externally called --------------- */
+
+static void error_cb(char *str){error(str);}
+static int esc_timer_set= 0;
+
+/* set callbacks, exported to sequence render too. 
+   Only call in foreground (UI) renders. */
+
+void BIF_init_render_callbacks(Render *re, int do_display)
 {
-       unsigned int *rect, *newrect;
-       int x, y;
-       int ofsx, ofsy, stepx, stepy;
-
-       stepx = (int)((65536.0 * (oldx - 1.0) / (newx - 1.0)) + 0.5);
-       stepy = (int)((65536.0 * (oldy - 1.0) / (newy - 1.0)) + 0.5);
-       ofsy = 32768;
-       newrect= rectn;
-       
-       for (y = newy; y > 0 ; y--){
-               rect = recto;
-               rect += (ofsy >> 16) * oldx;
-               ofsy += stepy;
-               ofsx = 32768;
-               for (x = newx ; x>0 ; x--){
-                       *newrect++ = rect[ofsx >> 16];
-                       ofsx += stepx;
+       if(do_display) {
+               if(G.displaymode!=R_DISPLAYWIN) {
+                       if(render_win)
+                               BIF_close_render_display();
+                       imagewindow_render_callbacks(re);
+               }
+               else {
+                       RE_display_init_cb(re, renderwin_init_display_cb);
+                       RE_display_draw_cb(re, renderwin_progress_display_cb);
+                       RE_display_clear_cb(re, renderwin_clear_display_cb);
+                       RE_stats_draw_cb(re, renderwin_renderinfo_cb);
                }
        }
-}
+       
+       RE_error_cb(re, error_cb);
+       
+       G.afbreek= 0;
+       if(render_win)
+               render_win->flags &= ~RW_FLAGS_ESCAPE;
 
-/* -------------- API: externally called --------------- */
+       /* start esc timer. ensure it happens once only */
+       if(esc_timer_set==0)
+               init_test_break_callback();
+       esc_timer_set++;
+       
+       RE_test_break_cb(re, test_break);
+       RE_timecursor_cb(re, set_timecursor);
+       
+}
 
-/* not used anywhere ??? */
-#if 0
-void BIF_renderwin_make_active(void)
+/* the init/end callbacks can be called multiple times (sequence render) */
+void BIF_end_render_callbacks(void)
 {
-       if(render_win) {
-               window_make_active(render_win->win);
-               mywinset(2);
+       esc_timer_set--;
+       if(esc_timer_set==0) {
+               end_test_break_callback();
+               
+               if(render_win)
+                       mainwindow_make_active();
        }
 }
-#endif
+
+void BIF_store_spare(void)
+{
+       if(render_win)
+               renderwin_store_spare();
+       else
+               imagewin_store_spare();
+}
 
 /* set up display, render an image or scene */
 void BIF_do_render(int anim)
@@ -1162,96 +1225,166 @@ void BIF_do_render(int anim)
                        slink_flag = 1;
                }
        }
+       
+       BIF_store_spare();
 
-       /* if start render in 3d win, use layer from window (e.g also local view) */
-       if(curarea && curarea->spacetype==SPACE_VIEW3D) {
-               int lay= G.scene->lay;
-               if(G.vd->lay & 0xFF000000)      // localview
-                       G.scene->lay |= G.vd->lay;
-               else G.scene->lay= G.vd->lay;
-               
-               do_render(NULL, anim, 0);
-               
-               G.scene->lay= lay;
-       }
-       else do_render(NULL, anim, 0);
+       do_render(anim);
 
+       if(G.scene->use_nodes) {
+               allqueue(REDRAWNODE, 1);
+               allqueue(REDRAWIMAGE, 1);
+       }
        if (slink_flag) G.f |= G_DOSCRIPTLINKS;
        if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_POSTRENDER);
 }
 
 /* set up display, render the current area view in an image */
-void BIF_do_ogl_render(View3D *ogl_render_view3d, int anim)
+/* the RE_Render is only used to make sure we got the picture in the result */
+void BIF_do_ogl_render(View3D *v3d, int anim)
 {
-       G.scene->r.scemode |= R_OGL;
-       do_render(ogl_render_view3d, anim, 1);
-       G.scene->r.scemode &= ~R_OGL;
+       Render *re= RE_NewRender(G.scene->id.name);
+       RenderResult *rr;
+       int winx, winy;
+       
+       G.afbreek= 0;
+       init_test_break_callback();
+       
+       winx= (G.scene->r.size*G.scene->r.xsch)/100;
+       winy= (G.scene->r.size*G.scene->r.ysch)/100;
+       
+       RE_InitState(re, &G.scene->r, winx, winy, NULL);
+       
+       /* for now, result is defaulting to floats still... */
+       rr= RE_GetResult(re);
+       if(rr->rect32==NULL)
+               rr->rect32= MEM_mallocN(sizeof(int)*winx*winy, "32 bits rects");
+       
+       /* open window */
+       renderwin_init_display_cb(rr);
+       if(render_win)
+               render_win->flags &= ~RW_FLAGS_ESCAPE;
+
+       init_gl_stuff();
+       
+       waitcursor(1);
+
+       if(anim) {
+               bMovieHandle *mh= BKE_get_movie_handle(G.scene->r.imtype);
+               int cfrao= CFRA;
+               
+               if(BKE_imtype_is_movie(G.scene->r.imtype))
+                       mh->start_movie(&G.scene->r, winx, winy);
+               
+               for(CFRA= SFRA; CFRA<=EFRA; CFRA++) {
+                       /* user event can close window */
+                       if(render_win==NULL)
+                               break;
+                       drawview3d_render(v3d, winx, winy);
+                       glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32);
+                       window_swap_buffers(render_win->win);
+                       
+                       if(BKE_imtype_is_movie(G.scene->r.imtype)) {
+                               mh->append_movie(CFRA, rr->rect32, winx, winy);
+                               printf("Append frame %d", G.scene->r.cfra);
+                       }
+                       else {
+                               ImBuf *ibuf= IMB_allocImBuf(winx, winy, G.scene->r.planes, 0, 0);
+                               char name[FILE_MAXDIR+FILE_MAXFILE];
+                               int ok;
+                               
+                               BKE_makepicstring(name, G.scene->r.pic, G.scene->r.cfra, G.scene->r.imtype);
+
+                               ibuf->rect= rr->rect32;    
+                               ok= BKE_write_ibuf(ibuf, name, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality);
+                               
+                               if(ok==0) {
+                                       printf("Write error: cannot save %s\n", name);
+                                       break;
+                               }
+                               else printf("Saved: %s", name);
+                               
+                /* imbuf knows which rects are not part of ibuf */
+                               IMB_freeImBuf(ibuf);    
+                       }
+                       /* movie stats prints have no line break */
+                       printf("\n");
+                       
+                       if(test_break()) break;
+               }
+               
+               if(BKE_imtype_is_movie(G.scene->r.imtype))
+                       mh->end_movie();
+               
+               CFRA= cfrao;
+       }
+       else {
+               drawview3d_render(v3d, winx, winy);
+               glReadPixels(0, 0, winx, winy, GL_RGBA, GL_UNSIGNED_BYTE, rr->rect32);
+               window_swap_buffers(render_win->win);
+       }
+       
+       if(render_win)
+               renderwin_draw(render_win, 0);
+
+       mainwindow_make_active();
+       
+       if(anim)
+               scene_update_for_newframe(G.scene, G.scene->lay);       // no redraw needed, this restores to view as we left it
+       
+       end_test_break_callback();
+       waitcursor(0);
 }
 
 void BIF_redraw_render_rect(void)
 {
-       
        /* redraw */
-       if (G.displaymode == R_DISPLAYWIN) {
-               // don't open render_win if rendering has been
-           // canceled or the render_win has been actively closed
-               if (render_win) {
-                       renderwin_queue_redraw(render_win);
-               }
-       } else {
-               renderview_init_display_cb();
-               renderview_progress_display_cb(0, R.recty-1, R.rectx, R.recty, R.rectot);
+       if (render_win) {
+               renderwin_queue_redraw(render_win);
+       }
+       else {
+               allqueue(REDRAWIMAGE, 0);
        }
 }      
 
 void BIF_swap_render_rects(void)
 {
-       unsigned int *temp;
-
-       if(R.rectspare==0) {
-               R.rectspare= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
-               R.sparex= R.rectx;
-               R.sparey= R.recty;
-       }
-       else if(R.sparex!=R.rectx || R.sparey!=R.recty) {
-               temp= (unsigned int *)MEM_callocN(sizeof(int)*R.rectx*R.recty, "rectot");
-                                       
-               scalefastrect(R.rectspare, temp, R.sparex, R.sparey, R.rectx, R.recty);
-               MEM_freeN(R.rectspare);
-               R.rectspare= temp;
-                                       
-               R.sparex= R.rectx;
-               R.sparey= R.recty;
-       }
+       RenderResult rres;
        
-       temp= R.rectot;
-       R.rectot= R.rectspare;
-       R.rectspare= temp;
-       
-       if (G.displaymode == R_DISPLAYWIN) {
-               if (render_win) {
-                       char *tmp= render_win->render_text_spare;
-                       render_win->render_text_spare= render_win->render_text;
-                       render_win->render_text= tmp;
+       if(G.displaymode!=R_DISPLAYWIN) {
+               imagewindow_swap_render_rects();
+       }
+       else if(render_win) {
+               
+               render_win->storespare= 1;
+               render_win->showspare ^= 1;
                        
-                       window_set_title(render_win->win, renderwin_get_title(1));
+               RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
                        
+               if(render_win->sparex!=rres.rectx || render_win->sparey!=rres.recty) {
+                       if(render_win->rectspare) MEM_freeN(render_win->rectspare);
+                       render_win->rectspare= NULL;
+                       if(render_win->rectsparef) MEM_freeN(render_win->rectsparef);
+                       render_win->rectsparef= NULL;
                }
+               
+               window_set_title(render_win->win, renderwin_get_title(1));
        }
-
+       
        /* redraw */
        BIF_redraw_render_rect();
+
 }                              
 
 /* called from usiblender.c too, to free and close renderwin */
 void BIF_close_render_display(void)
 {
        if (render_win) {
-
                if (render_win->info_text) MEM_freeN(render_win->info_text);
                if (render_win->render_text) MEM_freeN(render_win->render_text);
                if (render_win->render_text_spare) MEM_freeN(render_win->render_text_spare);
-
+               if (render_win->rectspare) MEM_freeN(render_win->rectspare);
+               if (render_win->rectsparef) MEM_freeN(render_win->rectsparef);
+                       
                window_destroy(render_win->win); /* ghost close window */
                MEM_freeN(render_win);
 
@@ -1263,35 +1396,26 @@ void BIF_close_render_display(void)
 /* typical with F11 key, show image or hide/close */
 void BIF_toggle_render_display(void) 
 {
-       ScrArea *sa= find_dispimage_v3d();
        
-       if(R.rectot==NULL);             // do nothing
-       else if (render_win && G.displaymode==R_DISPLAYWIN) {
-               if(render_win->active) {
-                       mainwindow_raise();
-                       mainwindow_make_active();
-                       render_win->active= 0;
-               }
-               else {
-                       window_raise(render_win->win);
-                       window_make_active(render_win->win);
-                       render_win->active= 1;
-               }
-       } 
-       else if (sa && G.displaymode==R_DISPLAYVIEW) {
-               View3D *vd= sa->spacedata.first;
-               vd->flag &= ~V3D_DISPIMAGE;
-               scrarea_queue_winredraw(sa);
-       } 
+       if (G.displaymode!=R_DISPLAYWIN) {
+               imagewindow_toggle_render();
+       }
        else {
-               if (G.displaymode == R_DISPLAYWIN) {
-                       renderwin_init_display_cb();
-               } else {
-                       if (render_win) {
-                               BIF_close_render_display();
+               if (render_win) {
+                       if(render_win->active) {
+                               mainwindow_raise();
+                               mainwindow_make_active();
+                               render_win->active= 0;
+                       }
+                       else {
+                               window_raise(render_win->win);
+                               window_make_active(render_win->win);
+                               render_win->active= 1;
                        }
-                       renderview_init_display_cb();
-                       renderview_progress_display_cb(0, R.recty-1, R.rectx, R.recty, R.rectot);
+               } 
+               else {
+                       RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name));
+                       if(rr) renderwin_init_display_cb(rr);
                }
        }
 }