Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 27 Nov 2017 13:08:35 +0000 (14:08 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 27 Nov 2017 13:08:35 +0000 (14:08 +0100)
15 files changed:
1  2 
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/sequencer.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/render/render_opengl.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_camera.c
source/blender/makesrna/intern/rna_scene.c
source/blender/windowmanager/intern/wm_files.c

index 532334c31ff6e973c4106f4bf2ee1c72abf57c37,6c9dc12b44f643f08cce5814cd9f26048c810116..2264167eca13f42ec4a5d6cf3bcdfcbf809fb3c0
@@@ -421,12 -421,21 +421,22 @@@ struct Sequence *BKE_sequencer_add_soun
  struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
  
  /* view3d draw callback, run when not in background view */
+ /* NOTE: Keep in sync with V3D_OFSDRAW_* flags. */
+ enum {
+     SEQ_OFSDRAW_NONE             = (0),
+     SEQ_OFSDRAW_USE_BACKGROUND   = (1 << 0),
+     SEQ_OFSDRAW_USE_FULL_SAMPLE  = (1 << 1),
+     SEQ_OFSDRAW_USE_GPENCIL      = (1 << 2),
+     SEQ_OFSDRAW_USE_SOLID_TEX    = (1 << 2),
+     SEQ_OFSDRAW_USE_CAMERA_DOF   = (1 << 3),
+ };
  typedef struct ImBuf *(*SequencerDrawView)(
-         const struct EvaluationContext *eval_ctx, struct Scene *,
-         struct ViewLayer *view_layer, struct Object *, int, int,
-         unsigned int, int, bool, bool, bool,
-         int, int, bool, const char *,
-         struct GPUFX *, struct GPUOffScreen *, char[256]);
 -        struct Scene *scene, struct Object *camera, int width, int height,
++        const struct EvaluationContext *eval_ctx, struct Scene *scene,
++        struct ViewLayer *view_layer, struct Object *camera, int width, int height,
+         unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
+         int samples, const char *viewname,
+         struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
  extern SequencerDrawView sequencer_view3d_cb;
  
  /* copy/paste */
index a83eba145c93ef83f6c69657627a705629c87ebb,9e8e202c2bc558c44b85c8d11e463d3a803815b8..ced94af26d2df5f706875d47fe751489a85e0ce3
@@@ -3314,15 -3313,11 +3321,13 @@@ static ImBuf *seq_render_scene_strip(co
                        context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
  
                /* opengl offscreen render */
 -              BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
 +              context->eval_ctx->engine = RE_engines_find(scene->view_render.engine_id);
 +              BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
                ibuf = sequencer_view3d_cb(
                        /* set for OpenGL render (NULL when scrubbing) */
 -                      scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type,
 +                      context->eval_ctx, scene, view_layer, camera, width, height, IB_rect,
-                       context->scene->r.seq_prev_type,
-                       (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
-                       use_gpencil, use_background, scene->r.alphamode,
-                       context->gpu_samples, context->gpu_full_samples, viewname,
++                      draw_flags, context->scene->r.seq_prev_type,
+                       scene->r.alphamode, context->gpu_samples, viewname,
                        context->gpu_fx, context->gpu_offscreen, err_out);
                if (ibuf == NULL) {
                        fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
index 12f72bcff3ab6c4f3049ad7c7561b759b6dedcc9,2cc928117c58233c12cc0d1ccd6d55d7bc8f696f..feb3686db9f6ad29cd6b9227e107c0931c13cc11
@@@ -382,20 -364,30 +382,32 @@@ void ED_view3d_draw_offscreen
          struct GPUFX *fx, struct GPUFXSettings *fx_settings,
          struct GPUOffScreen *ofs);
  void ED_view3d_draw_setup_view(
 -        struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
 +        struct wmWindow *win, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
          float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
  
+ enum {
+       V3D_OFSDRAW_NONE             = (0),
+       V3D_OFSDRAW_USE_BACKGROUND   = (1 << 0),
+       V3D_OFSDRAW_USE_FULL_SAMPLE  = (1 << 1),
+       /* Only works with ED_view3d_draw_offscreen_imbuf_simple(). */
+       V3D_OFSDRAW_USE_GPENCIL      = (1 << 2),
+       V3D_OFSDRAW_USE_SOLID_TEX    = (1 << 2),
+       V3D_OFSDRAW_USE_CAMERA_DOF   = (1 << 3),
+ };
  struct ImBuf *ED_view3d_draw_offscreen_imbuf(
 -        struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
 -        unsigned int flag, unsigned int draw_flags,
 +        const struct EvaluationContext *eval_ctx, struct Scene *scene,
 +        struct ViewLayer *view_layer, struct View3D *v3d, struct ARegion *ar,
-         int sizex, int sizey, unsigned int flag, bool draw_background,
-         int alpha_mode, int samples, bool full_samples, const char *viewname,
++        int sizex, int sizey, unsigned int flag, unsigned int draw_flags,
+         int alpha_mode, int samples, const char *viewname,
          struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
  struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
 -        struct Scene *scene, struct Object *camera, int width, int height,
 +        const struct EvaluationContext *eval_ctx, struct Scene *scene,
 +        struct ViewLayer *view_layer, struct Object *camera, int width, int height,
-         unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
-         int alpha_mode, int samples, bool full_samples, const char *viewname,
+         unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
+         int samples, const char *viewname,
          struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
  
  struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
index a445f8dafea28ca4f468e3a4b19f8f4e3d9eaef3,b7a23bafced44c1911c3a5a230fd5aa0d00458da..77535a65e5839be7f8e9761953037d42e94e75d9
@@@ -352,11 -353,15 +352,15 @@@ static void screen_opengl_render_doit(c
                ImBuf *ibuf_view;
                const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
  
+               unsigned int draw_flags = V3D_OFSDRAW_NONE;
+               draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
                if (view_context) {
+                       draw_flags |= (draw_bgpic) ? V3D_OFSDRAW_USE_BACKGROUND : 0;
                        ibuf_view = ED_view3d_draw_offscreen_imbuf(
 -                             scene, v3d, ar, sizex, sizey,
 +                             &eval_ctx, scene, view_layer, v3d, ar, sizex, sizey,
-                              IB_rect, draw_bgpic,
-                              alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
+                              IB_rect, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
                               oglrender->fx, oglrender->ofs, err_out);
  
                        /* for stamp only */
                        }
                }
                else {
+                       draw_flags |= (V3D_OFSDRAW_USE_GPENCIL | V3D_OFSDRAW_USE_BACKGROUND);
                        ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
 -                              scene, scene->camera, oglrender->sizex, oglrender->sizey,
 +                              &eval_ctx, scene, view_layer, scene->camera, oglrender->sizex, oglrender->sizey,
-                               IB_rect, OB_SOLID, false, true, true,
-                               alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
+                               IB_rect, draw_flags, OB_SOLID,
+                               alpha_mode, oglrender->ofs_samples, viewname,
                                oglrender->fx, oglrender->ofs, err_out);
                        camera = scene->camera;
                }
index 89b5107fdfc13de5d2cdc7bc5805e877fd399755,6fa45f1932a30299ced54633a02ddc37db7946ca..900ca844dbffba70e0926551a42d29e60f1f9e03
@@@ -5473,8 -5459,8 +5473,8 @@@ static int texture_paint_image_from_vie
        if (h > maxsize) h = maxsize;
  
        ibuf = ED_view3d_draw_offscreen_imbuf(
 -              scene, CTX_wm_view3d(C), CTX_wm_region(C),
 +              &eval_ctx, scene, view_layer, CTX_wm_view3d(C), CTX_wm_region(C),
-               w, h, IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
+               w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
                NULL, NULL, err_out);
        if (!ibuf) {
                /* Mostly happens when OpenGL offscreen buffer was failed to create, */
index 01b7c8793ba857c5bd68b266e7b21bee24914abb,bb7e2d75482c26ae12639284b497d4d6af5b8e3c..399e76e71b8316b313e48fdd43048c9c16bea873
  #include "IMB_colormanagement.h"
  #include "IMB_imbuf.h"
  
 -#include "BIF_gl.h"
  #include "BIF_glutil.h"
  
 -#include "GPU_basic_shader.h"
+ #include "GPU_compositing.h"
 +#include "GPU_immediate.h"
 +#include "GPU_immediate_util.h"
 +#include "GPU_matrix.h"
  
  #include "ED_anim_api.h"
  #include "ED_gpencil.h"
index 4bc4c373df443ee15449f15e99bfbc0567e48a1d,9e220f4b141f421c1149bf3af133207a7e6089dc..8024a733f40a05a940e09df7a322e140fc2d6460
@@@ -1406,924 -3153,888 +1406,931 @@@ static void drawcursor(Scene *scene, AR
        }
  }
  
 -/* ED_view3d_draw_offscreen_init should be called before this to initialize
 - * stuff like shadow buffers
 - */
 -void ED_view3d_draw_offscreen(
 -        Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
 -        float viewmat[4][4], float winmat[4][4],
 -        bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
 -        GPUFX *fx, GPUFXSettings *fx_settings,
 -        GPUOffScreen *ofs)
 +static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
  {
 -      struct bThemeState theme_state;
 -      int bwinx, bwiny;
 -      rcti brect;
 -      bool do_compositing = false;
 -      RegionView3D *rv3d = ar->regiondata;
 +      const float k = U.rvisize * U.pixelsize;  /* axis size */
 +      const int bright = - 20 * (10 - U.rvibright);  /* axis alpha offset (rvibright has range 0-10) */
  
 -      glPushMatrix();
 +      const float startx = rect->xmin + k + 1.0f;  /* axis center in screen coordinates, x=y */
 +      const float starty = rect->ymin + k + 1.0f;
  
 -      /* set temporary new size */
 -      bwinx = ar->winx;
 -      bwiny = ar->winy;
 -      brect = ar->winrct;
 +      float axis_pos[3][2];
 +      unsigned char axis_col[3][4];
  
 -      ar->winx = winx;
 -      ar->winy = winy;
 -      ar->winrct.xmin = 0;
 -      ar->winrct.ymin = 0;
 -      ar->winrct.xmax = winx;
 -      ar->winrct.ymax = winy;
 +      int axis_order[3] = {0, 1, 2};
 +      axis_sort_v3(rv3d->viewinv[2], axis_order);
  
 -      UI_Theme_Store(&theme_state);
 -      UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
 +      for (int axis_i = 0; axis_i < 3; axis_i++) {
 +              int i = axis_order[axis_i];
  
 -      /* set flags */
 -      G.f |= G_RENDER_OGL;
 +              /* get position of each axis tip on screen */
 +              float vec[3] = { 0.0f };
 +              vec[i] = 1.0f;
 +              mul_qt_v3(rv3d->viewquat, vec);
 +              axis_pos[i][0] = startx + vec[0] * k;
 +              axis_pos[i][1] = starty + vec[1] * k;
  
 -      if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
 -              /* free images which can have changed on frame-change
 -               * warning! can be slow so only free animated images - campbell */
 -              GPU_free_images_anim();
 +              /* get color of each axis */
 +              UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
 +              axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
        }
  
 -      /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
 -      if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
 -              view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
 -      else
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
 +      /* draw axis lines */
 +      glLineWidth(2.0f);
 +      glEnable(GL_LINE_SMOOTH);
 +      glEnable(GL_BLEND);
 +      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
 -      /* framebuffer fx needed, we need to draw offscreen first */
 -      if (v3d->fx_settings.fx_flag && fx) {
 -              GPUSSAOSettings *ssao = NULL;
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
  
 -              if (v3d->drawtype < OB_SOLID) {
 -                      ssao = v3d->fx_settings.ssao;
 -                      v3d->fx_settings.ssao = NULL;
 -              }
 +      immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
 +      immBegin(GWN_PRIM_LINES, 6);
  
 -              do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
 +      for (int axis_i = 0; axis_i < 3; axis_i++) {
 +              int i = axis_order[axis_i];
  
 -              if (ssao)
 -                      v3d->fx_settings.ssao = ssao;
 +              immAttrib4ubv(col, axis_col[i]);
 +              immVertex2f(pos, startx, starty);
 +              immVertex2fv(pos, axis_pos[i]);
        }
  
 -      /* clear opengl buffers */
 -      if (do_sky) {
 -              view3d_main_region_clear(scene, v3d, ar);
 -      }
 -      else {
 -              glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 -              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 -      }
 +      immEnd();
 +      immUnbindProgram();
 +      glDisable(GL_LINE_SMOOTH);
  
 -      /* main drawing call */
 -      view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
 +      /* draw axis names */
 +      for (int axis_i = 0; axis_i < 3; axis_i++) {
 +              int i = axis_order[axis_i];
  
 -      /* post process */
 -      if (do_compositing) {
 -              if (!winmat)
 -                      is_persp = rv3d->is_persp;
 -              GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
 +              const char axis_text[2] = {'x' + i, '\0'};
 +              BLF_color4ubv(BLF_default(), axis_col[i]);
 +              BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
        }
 +}
  
 -      if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
 -              /* draw grease-pencil stuff */
 -              ED_region_pixelspace(ar);
 -
 -
 -              if (v3d->flag2 & V3D_SHOW_GPENCIL) {
 -                      /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
 -                      ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
 -              }
 +#ifdef WITH_INPUT_NDOF
 +/* draw center and axis of rotation for ongoing 3D mouse navigation */
 +static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
 +{
 +      float o[3];    /* center of rotation */
 +      float end[3];  /* endpoints for drawing */
  
 -              /* freeing the images again here could be done after the operator runs, leaving for now */
 -              GPU_free_images_anim();
 -      }
 +      GLubyte color[4] = {0, 108, 255, 255};  /* bright blue so it matches device LEDs */
  
 -      /* restore size */
 -      ar->winx = bwinx;
 -      ar->winy = bwiny;
 -      ar->winrct = brect;
 +      negate_v3_v3(o, rv3d->ofs);
  
 -      glPopMatrix();
 +      glEnable(GL_BLEND);
 +      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      glDepthMask(GL_FALSE);  /* don't overwrite zbuf */
  
 -      UI_Theme_Restore(&theme_state);
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 +      unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
  
 -      G.f &= ~G_RENDER_OGL;
 -}
 +      immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
  
 -/**
 - * Set the correct matrices
 - */
 -void ED_view3d_draw_setup_view(
 -        wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect)
 -{
 -      RegionView3D *rv3d = ar->regiondata;
 +      if (rv3d->rot_angle != 0.0f) {
 +              /* -- draw rotation axis -- */
 +              float scaled_axis[3];
 +              const float scale = rv3d->dist;
 +              mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
  
 -      /* Setup the view matrix. */
 -      if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
 -              view3d_stereo3d_setup(scene, v3d, ar, rect);
 -      }
 -      else {
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect);
 -      }
 -}
  
 -/**
 - * Utility func for ED_view3d_draw_offscreen
 - *
 - * \param ofs: Optional off-screen buffer, can be NULL.
 - * (avoids re-creating when doing multiple GL renders).
 - */
 -ImBuf *ED_view3d_draw_offscreen_imbuf(
 -        Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
 -        unsigned int flag, unsigned int draw_flags,
 -        int alpha_mode, int samples, const char *viewname,
 -        /* output vars */
 -        GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
 -{
 -      RegionView3D *rv3d = ar->regiondata;
 -      ImBuf *ibuf;
 -      const bool draw_sky = (alpha_mode == R_ADDSKY);
 -      const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
 -      const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
 +              immBegin(GWN_PRIM_LINE_STRIP, 3);
 +              color[3] = 0; /* more transparent toward the ends */
 +              immAttrib4ubv(col, color);
 +              add_v3_v3v3(end, o, scaled_axis);
 +              immVertex3fv(pos, end);
  
 -      /* view state */
 -      GPUFXSettings fx_settings = v3d->fx_settings;
 -      bool is_ortho = false;
 -      float winmat[4][4];
 +#if 0
 +              color[3] = 0.2f + fabsf(rv3d->rot_angle);  /* modulate opacity with angle */
 +              /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
 +#endif
  
 -      if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
 -              /* sizes differ, can't reuse */
 -              ofs = NULL;
 -      }
 +              color[3] = 127; /* more opaque toward the center */
 +              immAttrib4ubv(col, color);
 +              immVertex3fv(pos, o);
  
 -      const bool own_ofs = (ofs == NULL);
 +              color[3] = 0;
 +              immAttrib4ubv(col, color);
 +              sub_v3_v3v3(end, o, scaled_axis);
 +              immVertex3fv(pos, end);
 +              immEnd();
 +              
 +              /* -- draw ring around rotation center -- */
 +              {
 +#define     ROT_AXIS_DETAIL 13
  
 -      if (own_ofs) {
 -              /* bind */
 -              ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out);
 -              if (ofs == NULL) {
 -                      return NULL;
 -              }
 -      }
 +                      const float s = 0.05f * scale;
 +                      const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
  
 -      ED_view3d_draw_offscreen_init(scene, v3d);
 +                      float q[4];  /* rotate ring so it's perpendicular to axis */
 +                      const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
 +                      if (!upright) {
 +                              const float up[3] = {0.0f, 0.0f, 1.0f};
 +                              float vis_angle, vis_axis[3];
  
 -      GPU_offscreen_bind(ofs, true);
 +                              cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
 +                              vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
 +                              axis_angle_to_quat(q, vis_axis, vis_angle);
 +                      }
  
 -      /* read in pixels & stamp */
 -      ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
 +                      immBegin(GWN_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
 +                      color[3] = 63; /* somewhat faint */
 +                      immAttrib4ubv(col, color);
 +                      float angle = 0.0f;
 +                      for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) {
 +                              float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
  
 -      /* render 3d view */
 -      if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
 -              CameraParams params;
 -              Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
 +                              if (!upright) {
 +                                      mul_qt_v3(q, p);
 +                              }
  
 -              BKE_camera_params_init(&params);
 -              /* fallback for non camera objects */
 -              params.clipsta = v3d->near;
 -              params.clipend = v3d->far;
 -              BKE_camera_params_from_object(&params, camera);
 -              BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
 -              BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
 -              BKE_camera_params_compute_matrix(&params);
 +                              add_v3_v3(p, o);
 +                              immVertex3fv(pos, p);
 +                      }
 +                      immEnd();
  
 -              BKE_camera_to_gpu_dof(camera, &fx_settings);
 +#undef      ROT_AXIS_DETAIL
 +              }
  
 -              is_ortho = params.is_ortho;
 -              copy_m4_m4(winmat, params.winmat);
 +              color[3] = 255;  /* solid dot */
        }
 -      else {
 -              rctf viewplane;
 -              float clipsta, clipend;
 +      else
 +              color[3] = 127;  /* see-through dot */
  
 -              is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
 -              if (is_ortho) {
 -                      orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
 -              }
 -              else {
 -                      perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
 -              }
 -      }
 +      immUnbindProgram();
  
 -      if ((samples && use_full_sample) == 0) {
 -              /* Single-pass render, common case */
 -              ED_view3d_draw_offscreen(
 -                      scene, v3d, ar, sizex, sizey, NULL, winmat,
 -                      draw_background, draw_sky, !is_ortho, viewname,
 -                      fx, &fx_settings, ofs);
 +      /* -- draw rotation center -- */
 +      immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
 +      glPointSize(5.0f);
 +      immBegin(GWN_PRIM_POINTS, 1);
 +      immAttrib4ubv(col, color);
 +      immVertex3fv(pos, o);
 +      immEnd();
 +      immUnbindProgram();
  
 -              if (ibuf->rect_float) {
 -                      GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
 -              }
 -              else if (ibuf->rect) {
 -                      GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
 -              }
 -      }
 -      else {
 -              /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
 -               * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
 -              static float jit_ofs[32][2];
 -              float winmat_jitter[4][4];
 -              /* use imbuf as temp storage, before writing into it from accumulation buffer */
 -              unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
 -              unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
 -              unsigned int i;
 -              int j;
 +#if 0
 +      /* find screen coordinates for rotation center, then draw pretty icon */
 +      mul_m4_v3(rv3d->persinv, rot_center);
 +      UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
 +      /* ^^ just playing around, does not work */
 +#endif
  
 -              BLI_jitter_init(jit_ofs, samples);
 +      glDisable(GL_BLEND);
 +      glDepthMask(GL_TRUE);
 +}
 +#endif /* WITH_INPUT_NDOF */
  
 -              /* first sample buffer, also initializes 'rv3d->persmat' */
 -              ED_view3d_draw_offscreen(
 -                      scene, v3d, ar, sizex, sizey, NULL, winmat,
 -                      draw_background, draw_sky, !is_ortho, viewname,
 -                      fx, &fx_settings, ofs);
 -              GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
 +/* ******************** info ***************** */
  
 -              i = sizex * sizey * 4;
 -              while (i--) {
 -                      accum_buffer[i] = rect_temp[i];
 -              }
 +/**
 +* Render and camera border
 +*/
 +static void view3d_draw_border(const bContext *C, ARegion *ar)
 +{
 +      Scene *scene = CTX_data_scene(C);
 +      RegionView3D *rv3d = ar->regiondata;
 +      View3D *v3d = CTX_wm_view3d(C);
 +
 +      if (rv3d->persp == RV3D_CAMOB) {
 +              drawviewborder(scene, ar, v3d);
 +      }
 +      else if (v3d->flag2 & V3D_RENDER_BORDER) {
 +              drawrenderborder(ar, v3d);
 +      }
 +}
  
 -              /* skip the first sample */
 -              for (j = 1; j < samples; j++) {
 -                      copy_m4_m4(winmat_jitter, winmat);
 -                      window_translate_m4(
 -                              winmat_jitter, rv3d->persmat,
 -                              (jit_ofs[j][0] * 2.0f) / sizex,
 -                              (jit_ofs[j][1] * 2.0f) / sizey);
 +/**
 +* Grease Pencil
 +*/
 +static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
 +{
 +      /* TODO viewport */
 +}
  
 -                      ED_view3d_draw_offscreen(
 -                              scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
 -                              draw_background, draw_sky, !is_ortho, viewname,
 -                              fx, &fx_settings, ofs);
 -                      GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
 +/**
 +* Viewport Name
 +*/
 +static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
 +{
 +      const char *name = NULL;
  
 -                      i = sizex * sizey * 4;
 -                      while (i--) {
 -                              accum_buffer[i] += rect_temp[i];
 -                      }
 -              }
 +      switch (rv3d->view) {
 +              case RV3D_VIEW_FRONT:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
 +                      else name = IFACE_("Front Persp");
 +                      break;
 +              case RV3D_VIEW_BACK:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
 +                      else name = IFACE_("Back Persp");
 +                      break;
 +              case RV3D_VIEW_TOP:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
 +                      else name = IFACE_("Top Persp");
 +                      break;
 +              case RV3D_VIEW_BOTTOM:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
 +                      else name = IFACE_("Bottom Persp");
 +                      break;
 +              case RV3D_VIEW_RIGHT:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
 +                      else name = IFACE_("Right Persp");
 +                      break;
 +              case RV3D_VIEW_LEFT:
 +                      if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
 +                      else name = IFACE_("Left Persp");
 +                      break;
  
 -              if (ibuf->rect_float) {
 -                      float *rect_float = ibuf->rect_float;
 -                      i = sizex * sizey * 4;
 -                      while (i--) {
 -                              rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
 +              default:
 +                      if (rv3d->persp == RV3D_CAMOB) {
 +                              if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
 +                                      Camera *cam;
 +                                      cam = v3d->camera->data;
 +                                      if (cam->type == CAM_PERSP) {
 +                                              name = IFACE_("Camera Persp");
 +                                      }
 +                                      else if (cam->type == CAM_ORTHO) {
 +                                              name = IFACE_("Camera Ortho");
 +                                      }
 +                                      else {
 +                                              BLI_assert(cam->type == CAM_PANO);
 +                                              name = IFACE_("Camera Pano");
 +                                      }
 +                              }
 +                              else {
 +                                      name = IFACE_("Object as Camera");
 +                              }
                        }
 -              }
 -              else {
 -                      unsigned char *rect_ub = (unsigned char *)ibuf->rect;
 -                      i = sizex * sizey * 4;
 -                      while (i--) {
 -                              rect_ub[i] = accum_buffer[i] / samples;
 +                      else {
 +                              name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
                        }
 -              }
 -
 -              MEM_freeN(accum_buffer);
        }
  
 -      /* unbind */
 -      GPU_offscreen_unbind(ofs, true);
 +      return name;
 +}
  
 -      if (own_ofs) {
 -              GPU_offscreen_free(ofs);
 -      }
 +static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
 +{
 +      RegionView3D *rv3d = ar->regiondata;
 +      const char *name = view3d_get_name(v3d, rv3d);
 +      /* increase size for unicode languages (Chinese in utf-8...) */
 +#ifdef WITH_INTERNATIONAL
 +      char tmpstr[96];
 +#else
 +      char tmpstr[32];
 +#endif
  
 -      if (ibuf->rect_float && ibuf->rect)
 -              IMB_rect_from_float(ibuf);
 +      if (v3d->localvd) {
 +              BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
 +              name = tmpstr;
 +      }
  
 -      return ibuf;
 +      UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
 +#ifdef WITH_INTERNATIONAL
 +      BLF_draw_default(U.widget_unit + rect->xmin,  rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
 +#else
 +      BLF_draw_default_ascii(U.widget_unit + rect->xmin,  rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
 +#endif
  }
  
  /**
 - * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
 - *
 - * \param ofs: Optional off-screen buffer can be NULL.
 - * (avoids re-creating when doing multiple GL renders).
 - *
 - * \note used by the sequencer
 + * draw info beside axes in bottom left-corner:
 + * framenum, object name, bone name (if available), marker name (if available)
   */
 -ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
 -        Scene *scene, Object *camera, int width, int height,
 -        unsigned int flag, unsigned int draw_flags, int drawtype,
 -        int alpha_mode, int samples, const char *viewname,
 -        GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
 -{
 -      View3D v3d = {NULL};
 -      ARegion ar = {NULL};
 -      RegionView3D rv3d = {{{0}}};
  
 -      /* connect data */
 -      v3d.regionbase.first = v3d.regionbase.last = &ar;
 -      ar.regiondata = &rv3d;
 -      ar.regiontype = RGN_TYPE_WINDOW;
 +static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
 +{
 +      const int cfra = CFRA;
 +      const char *msg_pin = " (Pinned)";
 +      const char *msg_sep = " : ";
  
 -      v3d.camera = camera;
 -      v3d.lay = scene->lay;
 -      v3d.drawtype = drawtype;
 -      v3d.flag2 = V3D_RENDER_OVERRIDE;
 +      const int font_id = BLF_default();
  
 -      if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
 -              v3d.flag2 |= V3D_SHOW_GPENCIL;
 -      }
 -      if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) {
 -              v3d.flag2 |= V3D_SOLID_TEX;
 -      }
 -      if (draw_flags & V3D_OFSDRAW_USE_BACKGROUND) {
 -              v3d.flag3 |= V3D_SHOW_WORLD;
 -      }
 -      if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
 -              if (camera->type == OB_CAMERA) {
 -                      v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
 -                      v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF;
 -              }
 -      }
 +      char info[300];
 +      char *s = info;
 +      short offset = 1.5f * UI_UNIT_X + rect->xmin;
  
 -      rv3d.persp = RV3D_CAMOB;
 +      s += sprintf(s, "(%d)", cfra);
  
 -      copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
 -      normalize_m4(rv3d.viewinv);
 -      invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
 +      /*
 +       * info can contain:
 +       * - a frame (7 + 2)
 +       * - 3 object names (MAX_NAME)
 +       * - 2 BREAD_CRUMB_SEPARATORs (6)
 +       * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
 +       * - a marker name (MAX_NAME + 3)
 +       */
  
 -      {
 -              CameraParams params;
 -              Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
 +      /* get name of marker on current frame (if available) */
 +      const char *markern = BKE_scene_find_marker_name(scene, cfra);
  
 -              BKE_camera_params_init(&params);
 -              BKE_camera_params_from_object(&params, view_camera);
 -              BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
 -              BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
 -              BKE_camera_params_compute_matrix(&params);
 +      /* check if there is an object */
 +      if (ob) {
 +              *s++ = ' ';
 +              s += BLI_strcpy_rlen(s, ob->id.name + 2);
  
 -              copy_m4_m4(rv3d.winmat, params.winmat);
 -              v3d.near = params.clipsta;
 -              v3d.far = params.clipend;
 -              v3d.lens = params.lens;
 -      }
 +              /* name(s) to display depends on type of object */
 +              if (ob->type == OB_ARMATURE) {
 +                      bArmature *arm = ob->data;
  
 -      mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
 -      invert_m4_m4(rv3d.persinv, rv3d.viewinv);
 +                      /* show name of active bone too (if possible) */
 +                      if (arm->edbo) {
 +                              if (arm->act_edbone) {
 +                                      s += BLI_strcpy_rlen(s, msg_sep);
 +                                      s += BLI_strcpy_rlen(s, arm->act_edbone->name);
 +                              }
 +                      }
 +                      else if (ob->mode & OB_MODE_POSE) {
 +                              if (arm->act_bone) {
  
 -      return ED_view3d_draw_offscreen_imbuf(
 -              scene, &v3d, &ar, width, height, flag, draw_flags,
 -              alpha_mode, samples, viewname, fx, ofs, err_out);
 -}
 +                                      if (arm->act_bone->layer & arm->layer) {
 +                                              s += BLI_strcpy_rlen(s, msg_sep);
 +                                              s += BLI_strcpy_rlen(s, arm->act_bone->name);
 +                                      }
 +                              }
 +                      }
 +              }
 +              else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
 +                      /* try to display active bone and active shapekey too (if they exist) */
  
 +                      if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
 +                              Object *armobj = BKE_object_pose_armature_get(ob);
 +                              if (armobj  && armobj->mode & OB_MODE_POSE) {
 +                                      bArmature *arm = armobj->data;
 +                                      if (arm->act_bone) {
 +                                              if (arm->act_bone->layer & arm->layer) {
 +                                                      s += BLI_strcpy_rlen(s, msg_sep);
 +                                                      s += BLI_strcpy_rlen(s, arm->act_bone->name);
 +                                              }
 +                                      }
 +                              }
 +                      }
  
 -/**
 - * \note The info that this uses is updated in #ED_refresh_viewport_fps,
 - * which currently gets called during #SCREEN_OT_animation_step.
 - */
 -void ED_scene_draw_fps(Scene *scene, const rcti *rect)
 -{
 -      ScreenFrameRateInfo *fpsi = scene->fps_info;
 -      float fps;
 -      char printable[16];
 -      int i, tot;
 -      
 -      if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
 -              return;
 -      
 -      printable[0] = '\0';
 -      
 -#if 0
 -      /* this is too simple, better do an average */
 -      fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
 -#else
 -      fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
 -      
 -      for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
 -              if (fpsi->redrawtimes_fps[i]) {
 -                      fps += fpsi->redrawtimes_fps[i];
 -                      tot++;
 +                      Key *key = BKE_key_from_object(ob);
 +                      if (key) {
 +                              KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
 +                              if (kb) {
 +                                      s += BLI_strcpy_rlen(s, msg_sep);
 +                                      s += BLI_strcpy_rlen(s, kb->name);
 +                                      if (ob->shapeflag & OB_SHAPE_LOCK) {
 +                                              s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
 +                                      }
 +                              }
 +                      }
                }
 -      }
 -      if (tot) {
 -              fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
 -              
 -              //fpsi->redrawtime_index++;
 -              //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
 -              //      fpsi->redrawtime = 0;
 -              
 -              fps = fps / tot;
 -      }
 -#endif
  
 -      /* is this more than half a frame behind? */
 -      if (fps + 0.5f < (float)(FPS)) {
 -              UI_ThemeColor(TH_REDALERT);
 -              BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
 +              /* color depends on whether there is a keyframe */
 +              if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
 +                      UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
 +              else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
 +                      UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
 +              else
 +                      UI_FontThemeColor(font_id, TH_TEXT_HI);
        }
        else {
 -              UI_ThemeColor(TH_TEXT_HI);
 -              BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
 +              /* no object */
 +              if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
 +                      UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
 +              else
 +                      UI_FontThemeColor(font_id, TH_TEXT_HI);
        }
  
 -#ifdef WITH_INTERNATIONAL
 -      BLF_draw_default(rect->xmin + U.widget_unit,  rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
 -#else
 -      BLF_draw_default_ascii(rect->xmin + U.widget_unit,  rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
 -#endif
 -}
 +      if (markern) {
 +              s += sprintf(s, " <%s>", markern);
 +      }
  
 -static bool view3d_main_region_do_render_draw(Scene *scene)
 -{
 -      RenderEngineType *type = RE_engines_find(scene->r.engine);
 +      if (U.uiflag & USER_SHOW_ROTVIEWICON)
 +              offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
  
 -      return (type && type->view_update && type->view_draw);
 +      BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
  }
  
 -bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
 +/* ******************** view loop ***************** */
 +
 +/**
 +* Information drawn on top of the solid plates and composed data
 +*/
 +void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
  {
        RegionView3D *rv3d = ar->regiondata;
 -      rctf viewborder;
 -      bool use_border;
 +      View3D *v3d = CTX_wm_view3d(C);
 +      Scene *scene = CTX_data_scene(C);
 +      wmWindowManager *wm = CTX_wm_manager(C);
  
 -      /* test if there is a 3d view rendering */
 -      if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
 -              return false;
 +      /* correct projection matrix */
 +      ED_region_pixelspace(ar);
  
 -      /* test if there is a border render */
 -      if (rv3d->persp == RV3D_CAMOB)
 -              use_border = (scene->r.mode & R_BORDER) != 0;
 -      else
 -              use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
 -      
 -      if (!use_border)
 -              return false;
 +      /* local coordinate visible rect inside region, to accomodate overlapping ui */
 +      rcti rect;
 +      ED_region_visible_rect(ar, &rect);
  
 -      /* compute border */
 -      if (rv3d->persp == RV3D_CAMOB) {
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
 +      /* Leave room for previously drawn info. */
 +      rect.ymax -= offset;
  
 -              rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
 -              rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
 -              rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
 -              rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
 +      view3d_draw_border(C, ar);
 +      view3d_draw_grease_pencil(C);
 +
 +      if (U.uiflag & USER_SHOW_ROTVIEWICON) {
 +              draw_view_axis(rv3d, &rect);
        }
 -      else {
 -              rect->xmin = v3d->render_border.xmin * ar->winx;
 -              rect->xmax = v3d->render_border.xmax * ar->winx;
 -              rect->ymin = v3d->render_border.ymin * ar->winy;
 -              rect->ymax = v3d->render_border.ymax * ar->winy;
 +
 +      if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
 +              ED_scene_draw_fps(scene, &rect);
 +      }
 +      else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
 +              draw_viewport_name(ar, v3d, &rect);
        }
  
 -      BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
 -      BLI_rcti_isect(&ar->winrct, rect, rect);
 +      if (U.uiflag & USER_DRAWVIEWINFO) {
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              Object *ob = OBACT(view_layer);
 +              draw_selected_name(scene, ob, &rect);
 +      }
 +#if 0 /* TODO */
 +      if (grid_unit) { /* draw below the viewport name */
 +              char numstr[32] = "";
  
 -      return true;
 +              UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
 +              if (v3d->grid != 1.0f) {
 +                      BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
 +              }
 +
 +              BLF_draw_default_ascii(rect.xmin + U.widget_unit,
 +                                     rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
 +                                     numstr[0] ? numstr : grid_unit, sizeof(numstr));
 +      }
 +#endif
  }
  
 -static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
 -                                         ARegion *ar, View3D *v3d,
 -                                         bool clip_border, const rcti *border_rect)
 +static void view3d_draw_view(const bContext *C, ARegion *ar)
  {
 -      RegionView3D *rv3d = ar->regiondata;
 -      RenderEngineType *type;
 -      GLint scissor[4];
 -
 -      /* create render engine */
 -      if (!rv3d->render_engine) {
 -              RenderEngine *engine;
 -
 -              type = RE_engines_find(scene->r.engine);
 -
 -              if (!(type->view_update && type->view_draw))
 -                      return false;
 +      EvaluationContext eval_ctx;
 +      CTX_data_eval_ctx(C, &eval_ctx);
  
 -              engine = RE_engine_create_ex(type, true);
 +      ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL);
  
 -              engine->tile_x = scene->r.tilex;
 -              engine->tile_y = scene->r.tiley;
 +      /* Only 100% compliant on new spec goes bellow */
 +      DRW_draw_view(C);
 +}
  
 -              type->view_update(engine, C);
 +void view3d_main_region_draw(const bContext *C, ARegion *ar)
 +{
 +      Scene *scene = CTX_data_scene(C);
 +      WorkSpace *workspace = CTX_wm_workspace(C);
 +      View3D *v3d = CTX_wm_view3d(C);
 +      RegionView3D *rv3d = ar->regiondata;
 +      ViewRender *view_render = BKE_viewrender_get(scene, workspace);
 +      RenderEngineType *type = RE_engines_find(view_render->engine_id);
  
 -              rv3d->render_engine = engine;
 +      /* Provisory Blender Internal drawing */
 +      if (type->flag & RE_USE_LEGACY_PIPELINE) {
 +              view3d_main_region_draw_legacy(C, ar);
 +              return;
        }
  
 -      /* setup view matrices */
 -      view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL);
 +      if (!rv3d->viewport) {
 +              rv3d->viewport = GPU_viewport_create();
 +      }
  
 -      /* background draw */
 -      ED_region_pixelspace(ar);
 +      GPU_viewport_bind(rv3d->viewport, &ar->winrct);
 +      view3d_draw_view(C, ar);
 +      GPU_viewport_unbind(rv3d->viewport);
  
 -      if (clip_border) {
 -              /* for border draw, we only need to clear a subset of the 3d view */
 -              if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
 -                      glGetIntegerv(GL_SCISSOR_BOX, scissor);
 -                      glScissor(border_rect->xmin, border_rect->ymin,
 -                                BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
 -              }
 -              else {
 -                      return false;
 -              }
 -      }
 +      v3d->flag |= V3D_INVALID_BACKBUF;
 +}
  
 -      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 -      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  
 -      if (v3d->flag & V3D_DISPBGPICS)
 -              view3d_draw_bgpic_test(scene, ar, v3d, false, true);
 -      else
 -              fdrawcheckerboard(0, 0, ar->winx, ar->winy);
 +/* -------------------------------------------------------------------- */
  
 -      /* render result draw */
 -      type = rv3d->render_engine->type;
 -      type->view_draw(rv3d->render_engine, C);
 +/** \name Offscreen Drawing
 + * \{ */
  
 -      if (v3d->flag & V3D_DISPBGPICS)
 -              view3d_draw_bgpic_test(scene, ar, v3d, true, true);
 +static void view3d_stereo3d_setup_offscreen(
 +        const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar,
 +        float winmat[4][4], const char *viewname)
 +{
 +      /* update the viewport matrices with the new camera */
 +      if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
 +              float viewmat[4][4];
 +              const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
  
 -      if (clip_border) {
 -              /* restore scissor as it was before */
 -              glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
 +              BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
 +              view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
        }
 +      else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
 +              float viewmat[4][4];
 +              Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
  
 -      return true;
 +              BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
 +              view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
 +      }
  }
  
 -static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
 +void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d)
  {
 -      float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
 -
 -      if (!rv3d->render_engine || !rv3d->render_engine->text[0])
 -              return;
 -      
 -      if (render_border) {
 -              /* draw darkened background color. no alpha because border render does
 -               * partial redraw and will not redraw the region behind this info bar */
 -              float alpha = 1.0f - fill_color[3];
 -              Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
 -
 -              if (camera) {
 -                      if (camera->flag & CAM_SHOWPASSEPARTOUT) {
 -                              alpha *= (1.0f - camera->passepartalpha);
 -                      }
 +      RenderEngineType *type = eval_ctx->engine;
 +      if (type->flag & RE_USE_LEGACY_PIPELINE) {
 +              /* shadow buffers, before we setup matrices */
 +              if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype)) {
 +                      VP_deprecated_gpu_update_lamps_shadows_world(eval_ctx, scene, v3d);
                }
 -
 -              UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
 -              mul_v3_fl(fill_color, alpha);
 -              fill_color[3] = 1.0f;
        }
 -
 -      ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
  }
  
 -static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
 +/*
 + * Function to clear the view
 + */
 +static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
  {
 -      if ((scene->r.scemode & R_MULTIVIEW) == 0) {
 -              return false;
 -      }
 +      glClear(GL_DEPTH_BUFFER_BIT);
  
 -      if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
 -              return false;
 +      if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
 +              VP_view3d_draw_background_world(scene, ar->regiondata);
        }
 -
 -      switch (v3d->stereo3d_camera) {
 -              case STEREO_MONO_ID:
 -                      return false;
 -                      break;
 -              case STEREO_3D_ID:
 -                      /* win will be NULL when calling this from the selection or draw loop. */
 -                      if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
 -                              return false;
 -                      }
 -                      if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
 -                          !BKE_scene_multiview_is_stereo3d(&scene->r))
 -                      {
 -                              return false;
 -                      }
 -                      break;
 -              /* We always need the stereo calculation for left and right cameras. */
 -              case STEREO_LEFT_ID:
 -              case STEREO_RIGHT_ID:
 -              default:
 -                      break;
 +      else {
 +              VP_view3d_draw_background_none();
        }
 -      return true;
  }
  
 -/* setup the view and win matrices for the multiview cameras
 - *
 - * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
 - * we have no winmatrix (i.e., projection matrix) defined at that time.
 - * Since the camera and the camera shift are needed for the winmat calculation
 - * we do a small hack to replace it temporarily so we don't need to change the
 - * view3d)main_region_setup_view() code to account for that.
 +/* ED_view3d_draw_offscreen_init should be called before this to initialize
 + * stuff like shadow buffers
   */
 -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
 +void ED_view3d_draw_offscreen(
 +        const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
 +        View3D *v3d, ARegion *ar, int winx, int winy,
 +        float viewmat[4][4], float winmat[4][4],
 +        bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
 +        GPUFX *fx, GPUFXSettings *fx_settings,
 +        GPUOffScreen *ofs)
  {
 -      bool is_left;
 -      const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
 -      const char *viewname;
 +      bool do_compositing = false;
 +      RegionView3D *rv3d = ar->regiondata;
  
 -      /* show only left or right camera */
 -      if (v3d->stereo3d_camera != STEREO_3D_ID)
 -              v3d->multiview_eye = v3d->stereo3d_camera;
 +      /* set temporary new size */
 +      int bwinx = ar->winx;
 +      int bwiny = ar->winy;
 +      rcti brect = ar->winrct;
  
 -      is_left = v3d->multiview_eye == STEREO_LEFT_ID;
 -      viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
 +      ar->winx = winx;
 +      ar->winy = winy;
 +      ar->winrct.xmin = 0;
 +      ar->winrct.ymin = 0;
 +      ar->winrct.xmax = winx;
 +      ar->winrct.ymax = winy;
  
 -      /* update the viewport matrices with the new camera */
 -      if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
 -              Camera *data;
 -              float viewmat[4][4];
 -              float shiftx;
 +      struct bThemeState theme_state;
 +      UI_Theme_Store(&theme_state);
 +      UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
  
 -              data = (Camera *)v3d->camera->data;
 -              shiftx = data->shiftx;
 +      /* set flags */
 +      G.f |= G_RENDER_OGL;
  
 -              BLI_lock_thread(LOCK_VIEW3D);
 -              data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
 +      if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
 +              /* free images which can have changed on frame-change
 +               * warning! can be slow so only free animated images - campbell */
 +              GPU_free_images_anim();
 +      }
  
 -              BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
 +      gpuPushProjectionMatrix();
 +      gpuLoadIdentity();
 +      gpuPushMatrix();
 +      gpuLoadIdentity();
  
 -              data->shiftx = shiftx;
 -              BLI_unlock_thread(LOCK_VIEW3D);
 +      /* clear opengl buffers */
 +      if (do_sky) {
 +              view3d_main_region_clear(scene, v3d, ar);
 +      }
 +      else {
 +              glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 +              glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
 -      else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
 -              float viewmat[4][4];
 -              Object *view_ob = v3d->camera;
 -              Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
  
 -              BLI_lock_thread(LOCK_VIEW3D);
 -              v3d->camera = camera;
 +      if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
 +              view3d_stereo3d_setup_offscreen(eval_ctx, scene, v3d, ar, winmat, viewname);
 +      else
 +              view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
  
 -              BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
 +      /* main drawing call */
 +      RenderEngineType *type = eval_ctx->engine;
 +      if (type->flag & RE_USE_LEGACY_PIPELINE) {
  
 -              v3d->camera = view_ob;
 -              BLI_unlock_thread(LOCK_VIEW3D);
 -      }
 -}
 +              /* framebuffer fx needed, we need to draw offscreen first */
 +              if (v3d->fx_settings.fx_flag && fx) {
 +                      GPUSSAOSettings *ssao = NULL;
  
 -static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
 -                                            float winmat[4][4], const char *viewname)
 -{
 -      /* update the viewport matrices with the new camera */
 -      if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
 -              float viewmat[4][4];
 -              const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
 +                      if (v3d->drawtype < OB_SOLID) {
 +                              ssao = v3d->fx_settings.ssao;
 +                              v3d->fx_settings.ssao = NULL;
 +                      }
  
 -              BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
 -      }
 -      else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
 -              float viewmat[4][4];
 -              Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
 +                      do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
  
 -              BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
 -              view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
 -      }
 -}
 +                      if (ssao)
 +                              v3d->fx_settings.ssao = ssao;
 +              }
  
 -#ifdef WITH_GAMEENGINE
 -static void update_lods(Scene *scene, float camera_pos[3])
 -{
 -      Scene *sce_iter;
 -      Base *base;
 -      Object *ob;
 +              VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
  
 -      for (SETLOOPER(scene, sce_iter, base)) {
 -              ob = base->object;
 -              BKE_object_lod_update(ob, camera_pos);
 +              /* post process */
 +              if (do_compositing) {
 +                      if (!winmat)
 +                              is_persp = rv3d->is_persp;
 +                      GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
 +              }
 +
 +              if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
 +                      /* draw grease-pencil stuff */
 +                      ED_region_pixelspace(ar);
 +
 +                      if (v3d->flag2 & V3D_SHOW_GPENCIL) {
 +                              /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
 +                              ED_gpencil_draw_view3d(NULL, scene, view_layer, v3d, ar, false);
 +                      }
 +
 +                      /* freeing the images again here could be done after the operator runs, leaving for now */
 +                      GPU_free_images_anim();
 +              }
 +      }
 +      else {
 +              /* XXX, should take depsgraph as arg */
 +              Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
 +              BLI_assert(depsgraph != NULL);
 +              DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine, ar, v3d, ofs);
        }
 +
 +      /* restore size */
 +      ar->winx = bwinx;
 +      ar->winy = bwiny;
 +      ar->winrct = brect;
 +
 +      gpuPopProjectionMatrix();
 +      gpuPopMatrix();
 +
 +      UI_Theme_Restore(&theme_state);
 +
 +      G.f &= ~G_RENDER_OGL;
  }
 -#endif
  
 -static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
 -                                          ARegion *ar, const char **grid_unit)
 +/**
 + * Utility func for ED_view3d_draw_offscreen
 + *
 + * \param ofs: Optional off-screen buffer, can be NULL.
 + * (avoids re-creating when doing multiple GL renders).
 + */
 +ImBuf *ED_view3d_draw_offscreen_imbuf(
 +        const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
 +        View3D *v3d, ARegion *ar, int sizex, int sizey,
-         unsigned int flag, bool draw_background,
-         int alpha_mode, int samples, bool full_samples, const char *viewname,
++        unsigned int flag, unsigned int draw_flags,
++        int alpha_mode, int samples, const char *viewname,
 +        /* output vars */
 +        GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
  {
 -      wmWindow *win = CTX_wm_window(C);
        RegionView3D *rv3d = ar->regiondata;
 -      unsigned int lay_used = v3d->lay_used;
 -      
 -      /* post processing */
 -      bool do_compositing = false;
 -      
 -      /* shadow buffers, before we setup matrices */
 -      if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
 -              gpu_update_lamps_shadows_world(scene, v3d);
 -
 -      /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
 -      if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
 -              rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
 -              GPU_default_lights();
 +      const bool draw_sky = (alpha_mode == R_ADDSKY);
++      const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
++      const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
 +
 +      /* view state */
 +      GPUFXSettings fx_settings = v3d->fx_settings;
 +      bool is_ortho = false;
 +      float winmat[4][4];
 +
 +      if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
 +              /* sizes differ, can't reuse */
 +              ofs = NULL;
 +      }
 +
 +      const bool own_ofs = (ofs == NULL);
 +
 +      if (own_ofs) {
 +              /* bind */
-               ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
++              ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out);
 +              if (ofs == NULL) {
 +                      return NULL;
 +              }
        }
  
 -      /* Setup the view matrix. */
 -      ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL);
 +      ED_view3d_draw_offscreen_init(eval_ctx, scene, view_layer, v3d);
  
 -      rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
 -#ifdef WITH_GAMEENGINE
 -      if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
 -              rv3d->rflag |= RV3D_IS_GAME_ENGINE;
 +      GPU_offscreen_bind(ofs, true);
  
 -              /* Make sure LoDs are up to date */
 -              update_lods(scene, rv3d->viewinv[3]);
 -      }
 -#endif
 +      /* read in pixels & stamp */
 +      ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
  
 -      /* framebuffer fx needed, we need to draw offscreen first */
 -      if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
 -              GPUFXSettings fx_settings;
 -              BKE_screen_gpu_fx_validate(&v3d->fx_settings);
 -              fx_settings = v3d->fx_settings;
 -              if (!rv3d->compositor)
 -                      rv3d->compositor = GPU_fx_compositor_create();
 -              
 -              if (rv3d->persp == RV3D_CAMOB && v3d->camera)
 -                      BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
 -              else {
 -                      fx_settings.dof = NULL;
 -              }
 +      /* render 3d view */
 +      if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
 +              CameraParams params;
 +              Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
 +
 +              BKE_camera_params_init(&params);
 +              /* fallback for non camera objects */
 +              params.clipsta = v3d->near;
 +              params.clipend = v3d->far;
 +              BKE_camera_params_from_object(&params, camera);
 +              BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
 +              BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
 +              BKE_camera_params_compute_matrix(&params);
 +
 +              BKE_camera_to_gpu_dof(camera, &fx_settings);
  
 -              do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
 +              is_ortho = params.is_ortho;
 +              copy_m4_m4(winmat, params.winmat);
        }
 -      
 -      /* clear the background */
 -      view3d_main_region_clear(scene, v3d, ar);
 +      else {
 +              rctf viewplane;
 +              float clipsta, clipend;
  
 -      /* enables anti-aliasing for 3D view drawing */
 -      if (win->multisamples != USER_MULTISAMPLE_NONE) {
 -              glEnable(GL_MULTISAMPLE);
 +              is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
 +              if (is_ortho) {
 +                      orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
 +              }
 +              else {
 +                      perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
 +              }
        }
  
-       if ((samples && full_samples) == 0) {
 -      /* main drawing call */
 -      view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
++      if ((samples && use_full_sample) == 0) {
 +              /* Single-pass render, common case */
 +              ED_view3d_draw_offscreen(
 +                      eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
 +                      draw_background, draw_sky, !is_ortho, viewname,
 +                      fx, &fx_settings, ofs);
  
 -      /* post process */
 -      if (do_compositing) {
 -              GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
 +              if (ibuf->rect_float) {
 +                      GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
 +              }
 +              else if (ibuf->rect) {
 +                      GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
 +              }
        }
 +      else {
 +              /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
 +               * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
 +              static float jit_ofs[32][2];
 +              float winmat_jitter[4][4];
 +              /* use imbuf as temp storage, before writing into it from accumulation buffer */
 +              unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
 +              unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
  
 -      /* Disable back anti-aliasing */
 -      if (win->multisamples != USER_MULTISAMPLE_NONE) {
 -              glDisable(GL_MULTISAMPLE);
 -      }
 +              BLI_jitter_init(jit_ofs, samples);
  
 -      if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
 -              /* find header and force tag redraw */
 -              ScrArea *sa = CTX_wm_area(C);
 -              ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
 -              ED_region_tag_redraw(ar_header); /* can be NULL */
 -      }
 +              /* first sample buffer, also initializes 'rv3d->persmat' */
 +              ED_view3d_draw_offscreen(
 +                      eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
 +                      draw_background, draw_sky, !is_ortho, viewname,
 +                      fx, &fx_settings, ofs);
 +              GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
  
 -      if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
 -              BDR_drawSketch(C);
 -      }
 +              unsigned i = sizex * sizey * 4;
 +              while (i--) {
 +                      accum_buffer[i] = rect_temp[i];
 +              }
  
 -#ifdef WITH_INPUT_NDOF
 -      if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB))
 -              /* TODO: draw something else (but not this) during fly mode */
 -              draw_rotation_guide(rv3d);
 -#endif
 -}
 +              /* skip the first sample */
 +              for (int j = 1; j < samples; j++) {
 +                      copy_m4_m4(winmat_jitter, winmat);
 +                      window_translate_m4(
 +                              winmat_jitter, rv3d->persmat,
 +                              (jit_ofs[j][0] * 2.0f) / sizex,
 +                              (jit_ofs[j][1] * 2.0f) / sizey);
  
 -static bool is_cursor_visible(Scene *scene)
 -{
 -      Object *ob = OBACT;
 +                      ED_view3d_draw_offscreen(
 +                              eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter,
 +                              draw_background, draw_sky, !is_ortho, viewname,
 +                              fx, &fx_settings, ofs);
 +                      GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
  
 -      /* don't draw cursor in paint modes, but with a few exceptions */
 -      if (ob && ob->mode & OB_MODE_ALL_PAINT) {
 -              /* exception: object is in weight paint and has deforming armature in pose mode */
 -              if (ob->mode & OB_MODE_WEIGHT_PAINT) {
 -                      if (BKE_object_pose_armature_get(ob) != NULL) {
 -                              return true;
 +                      i = sizex * sizey * 4;
 +                      while (i--) {
 +                              accum_buffer[i] += rect_temp[i];
                        }
                }
 -              /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
 -              else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
 -                      const Paint *p = BKE_paint_get_active(scene);
  
 -                      if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
 -                              if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
 -                                      return true;
 -                              }
 +              if (ibuf->rect_float) {
 +                      float *rect_float = ibuf->rect_float;
 +                      i = sizex * sizey * 4;
 +                      while (i--) {
 +                              rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
 +                      }
 +              }
 +              else {
 +                      unsigned char *rect_ub = (unsigned char *)ibuf->rect;
 +                      i = sizex * sizey * 4;
 +                      while (i--) {
 +                              rect_ub[i] = accum_buffer[i] / samples;
                        }
                }
  
 -              /* no exception met? then don't draw cursor! */
 -              return false;
 +              MEM_freeN(accum_buffer);
        }
  
 -      return true;
 +      /* unbind */
 +      GPU_offscreen_unbind(ofs, true);
 +
 +      if (own_ofs) {
 +              GPU_offscreen_free(ofs);
 +      }
 +
 +      if (ibuf->rect_float && ibuf->rect)
 +              IMB_rect_from_float(ibuf);
 +
 +      return ibuf;
  }
  
 -static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
 -                                       ARegion *ar, View3D *v3d,
 -                                       const char *grid_unit, bool render_border)
 +/**
 + * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
 + *
 + * \param ofs: Optional off-screen buffer can be NULL.
 + * (avoids re-creating when doing multiple GL renders).
 + *
 + * \note used by the sequencer
 + */
 +ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
 +        const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
 +        Object *camera, int width, int height,
-         unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
-         int alpha_mode, int samples, bool full_samples, const char *viewname,
++        unsigned int flag, unsigned int draw_flags, int drawtype,
++        int alpha_mode, int samples, const char *viewname,
 +        GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
  {
 -      wmWindowManager *wm = CTX_wm_manager(C);
 -      RegionView3D *rv3d = ar->regiondata;
 -      rcti rect;
 -      
 -      /* local coordinate visible rect inside region, to accomodate overlapping ui */
 -      ED_region_visible_rect(ar, &rect);
 +      View3D v3d = {NULL};
 +      ARegion ar = {NULL};
 +      RegionView3D rv3d = {{{0}}};
  
 -      if (rv3d->persp == RV3D_CAMOB) {
 -              drawviewborder(scene, ar, v3d);
 -      }
 -      else if (v3d->flag2 & V3D_RENDER_BORDER) {
 -              glLineWidth(1.0f);
 -              setlinestyle(3);
 -              cpack(0x4040FF);
 +      /* connect data */
 +      v3d.regionbase.first = v3d.regionbase.last = &ar;
 +      ar.regiondata = &rv3d;
 +      ar.regiontype = RGN_TYPE_WINDOW;
  
 -              sdrawbox(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
 -                       v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
 +      v3d.camera = camera;
 +      v3d.lay = scene->lay;
 +      v3d.drawtype = drawtype;
 +      v3d.flag2 = V3D_RENDER_OVERRIDE;
  
-       if (use_gpencil)
 -              setlinestyle(0);
++      if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) {
 +              v3d.flag2 |= V3D_SHOW_GPENCIL;
-       if (use_solid_tex)
+       }
 -
 -      if (v3d->flag2 & V3D_SHOW_GPENCIL) {
 -              /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
 -              ED_gpencil_draw_view3d(wm, scene, v3d, ar, false);
++      if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) {
 +              v3d.flag2 |= V3D_SOLID_TEX;
-       if (draw_background)
++      }
++      if (draw_flags & V3D_OFSDRAW_USE_BACKGROUND) {
 +              v3d.flag3 |= V3D_SHOW_WORLD;
++      }
++      if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) {
++              if (camera->type == OB_CAMERA) {
++                      v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof;
++                      v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF;
++              }
+       }
  
 -      if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
 -              Object *ob;
 +      rv3d.persp = RV3D_CAMOB;
  
 -              /* 3d cursor */
 -              if (is_cursor_visible(scene)) {
 -                      drawcursor(scene, ar, v3d);
 -              }
 +      copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
 +      normalize_m4(rv3d.viewinv);
 +      invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
  
 -              if (U.uiflag & USER_SHOW_ROTVIEWICON)
 -                      draw_view_axis(rv3d, &rect);
 -              else
 -                      draw_view_icon(rv3d, &rect);
 +      {
 +              CameraParams params;
 +              Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
  
 -              ob = OBACT;
 -              if (U.uiflag & USER_DRAWVIEWINFO)
 -                      draw_selected_name(scene, ob, &rect);
 -      }
 +              BKE_camera_params_init(&params);
 +              BKE_camera_params_from_object(&params, view_camera);
 +              BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
 +              BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
 +              BKE_camera_params_compute_matrix(&params);
  
 -      if (rv3d->render_engine) {
 -              view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
 -              return;
 +              copy_m4_m4(rv3d.winmat, params.winmat);
 +              v3d.near = params.clipsta;
 +              v3d.far = params.clipend;
 +              v3d.lens = params.lens;
        }
  
 -      if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
 -              if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
 -                      ED_scene_draw_fps(scene, &rect);
 -              }
 -              else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
 -                      draw_viewport_name(ar, v3d, &rect);
 -              }
 +      mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
 +      invert_m4_m4(rv3d.persinv, rv3d.viewinv);
  
 -              if (grid_unit) { /* draw below the viewport name */
 -                      char numstr[32] = "";
 +      return ED_view3d_draw_offscreen_imbuf(
 +              eval_ctx, scene, view_layer, &v3d, &ar, width, height, flag,
-               draw_background, alpha_mode, samples, full_samples, viewname,
-               fx, ofs, err_out);
++              draw_flags, alpha_mode, samples, viewname, fx, ofs, err_out);
 +}
  
 -                      UI_ThemeColor(TH_TEXT_HI);
 -                      if (v3d->grid != 1.0f) {
 -                              BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
 -                      }
 +/** \} */
  
 -                      BLF_draw_default_ascii(rect.xmin + U.widget_unit,
 -                                             rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
 -                                             numstr[0] ? numstr : grid_unit, sizeof(numstr));
 -              }
 +
 +/* -------------------------------------------------------------------- */
 +
 +/** \name Legacy Interface
 + *
 + * This will be removed once the viewport gets replaced
 + * meanwhile it should keep the old viewport working.
 + *
 + * \{ */
 +
 +void VP_legacy_drawcursor(Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d)
 +{
 +      if (is_cursor_visible(scene, view_layer)) {
 +              drawcursor(scene, ar, v3d);
        }
  }
  
index 777585d3386ddf3d878470c883a3648d6441bb81,981ae75e7c5c059b9a6f983cb892c64d901968fe..146a8e2738db4c0c42dcafa37089b89e7e270522
  #ifdef RNA_RUNTIME
  
  #include "BKE_camera.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_object.h"
+ #include "BKE_sequencer.h"
  
 -#include "WM_api.h"
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
  
  static float rna_Camera_angle_get(PointerRNA *ptr)
  {
@@@ -94,196 -93,20 +95,204 @@@ static void rna_Camera_update(Main *UNU
  static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
  {
        Camera *camera = (Camera *)ptr->id.data;
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&camera->id, 0);
 +      DEG_relations_tag_update(bmain);
 +      DEG_id_tag_update(&camera->id, 0);
 +}
 +
 +static CameraBGImage *rna_Camera_background_images_new(Camera *cam)
 +{
 +      CameraBGImage *bgpic = BKE_camera_background_image_new(cam);
 +
 +      WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
 +
 +      return bgpic;
 +}
 +
 +static void rna_Camera_background_images_remove(Camera *cam, ReportList *reports, PointerRNA *bgpic_ptr)
 +{
 +      CameraBGImage *bgpic = bgpic_ptr->data;
 +      if (BLI_findindex(&cam->bg_images, bgpic) == -1) {
 +              BKE_report(reports, RPT_ERROR, "Background image cannot be removed");
 +      }
 +
 +      BKE_camera_background_image_remove(cam, bgpic);
 +      RNA_POINTER_INVALIDATE(bgpic_ptr);
 +
 +      WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
 +}
 +
 +static void rna_Camera_background_images_clear(Camera *cam)
 +{
 +      BKE_camera_background_image_clear(cam);
 +
 +      WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
  }
  
+ static void rna_Camera_dof_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+ {
+       /* TODO(sergey): Can be more selective here. */
+       BKE_sequencer_cache_cleanup();
+       BKE_sequencer_preprocessed_cache_cleanup();
+       WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
+ }
  #else
  
 +static void rna_def_camera_background_image(BlenderRNA *brna)
 +{
 +      StructRNA *srna;
 +      PropertyRNA *prop;
 +
 +      static const EnumPropertyItem bgpic_source_items[] = {
 +              {CAM_BGIMG_SOURCE_IMAGE, "IMAGE", 0, "Image", ""},
 +              {CAM_BGIMG_SOURCE_MOVIE, "MOVIE_CLIP", 0, "Movie Clip", ""},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +
 +      static const EnumPropertyItem bgpic_camera_frame_items[] = {
 +              {0, "STRETCH", 0, "Stretch", ""},
 +              {CAM_BGIMG_FLAG_CAMERA_ASPECT, "FIT", 0, "Fit", ""},
 +              {CAM_BGIMG_FLAG_CAMERA_ASPECT | CAM_BGIMG_FLAG_CAMERA_CROP, "CROP", 0, "Crop", ""},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +
 +      static const EnumPropertyItem bgpic_draw_depth_items[] = {
 +              {0, "BACK", 0, "Back", ""},
 +              {CAM_BGIMG_FLAG_FOREGROUND, "FRONT", 0, "Front", ""},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +
 +      srna = RNA_def_struct(brna, "CameraBackgroundImage", NULL);
 +      RNA_def_struct_sdna(srna, "CameraBGImage");
 +      RNA_def_struct_ui_text(srna, "Background Image", "Image and settings for display in the 3D View background");
 +
 +      prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_sdna(prop, NULL, "source");
 +      RNA_def_property_enum_items(prop, bgpic_source_items);
 +      RNA_def_property_ui_text(prop, "Background Source", "Data source used for background");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
 +      RNA_def_property_pointer_sdna(prop, NULL, "ima");
 +      RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space");
 +      RNA_def_property_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
 +      RNA_def_property_pointer_sdna(prop, NULL, "clip");
 +      RNA_def_property_ui_text(prop, "MovieClip", "Movie clip displayed and edited in this space");
 +      RNA_def_property_flag(prop, PROP_EDITABLE);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
 +      RNA_def_property_flag(prop, PROP_NEVER_NULL);
 +      RNA_def_property_pointer_sdna(prop, NULL, "iuser");
 +      RNA_def_property_ui_text(prop, "Image User",
 +                               "Parameters defining which layer, pass and frame of the image is displayed");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "clip_user", PROP_POINTER, PROP_NONE);
 +      RNA_def_property_flag(prop, PROP_NEVER_NULL);
 +      RNA_def_property_struct_type(prop, "MovieClipUser");
 +      RNA_def_property_pointer_sdna(prop, NULL, "cuser");
 +      RNA_def_property_ui_text(prop, "Clip User", "Parameters defining which frame of the movie clip is displayed");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_XYZ);
 +      RNA_def_property_float_sdna(prop, NULL, "offset");
 +      RNA_def_property_ui_text(prop, "Offset", "");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_FACTOR);
 +      RNA_def_property_float_sdna(prop, NULL, "scale");
 +      RNA_def_property_ui_text(prop, "Scale", "Scale the background image");
 +      RNA_def_property_range(prop, 0.0, FLT_MAX);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
 +      RNA_def_property_float_sdna(prop, NULL, "rotation");
 +      RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FLIP_X);
 +      RNA_def_property_ui_text(prop, "Flip Horizontally", "Flip the background image horizontally");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FLIP_Y);
 +      RNA_def_property_ui_text(prop, "Flip Vertically", "Flip the background image vertically");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_float_sdna(prop, NULL, "alpha");
 +      RNA_def_property_ui_text(prop, "Alpha", "Image opacity to blend the image against the background color");
 +      RNA_def_property_range(prop, 0.0, 1.0);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_EXPANDED);
 +      RNA_def_property_ui_text(prop, "Show Expanded", "Show the expanded in the user interface");
 +      RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
 +
 +      prop = RNA_def_property(srna, "use_camera_clip", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_CAMERACLIP);
 +      RNA_def_property_ui_text(prop, "Camera Clip", "Use movie clip from active scene camera");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "show_background_image", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_DISABLED);
 +      RNA_def_property_ui_text(prop, "Show Background Image", "Show this image as background");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "show_on_foreground", PROP_BOOLEAN, PROP_NONE);
 +      RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FOREGROUND);
 +      RNA_def_property_ui_text(prop, "Show On Foreground", "Show this image in front of objects in viewport");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      /* expose 1 flag as a enum of 2 items */
 +      prop = RNA_def_property(srna, "draw_depth", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
 +      RNA_def_property_enum_items(prop, bgpic_draw_depth_items);
 +      RNA_def_property_ui_text(prop, "Depth", "Draw under or over everything");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      /* expose 2 flags as a enum of 3 items */
 +      prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
 +      RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
 +      RNA_def_property_enum_items(prop, bgpic_camera_frame_items);
 +      RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +}
 +
 +
 +static void rna_def_camera_background_images(BlenderRNA *brna, PropertyRNA *cprop)
 +{
 +      StructRNA *srna;
 +      FunctionRNA *func;
 +      PropertyRNA *parm;
 +
 +      RNA_def_property_srna(cprop, "CameraBackgroundImages");
 +      srna = RNA_def_struct(brna, "CameraBackgroundImages", NULL);
 +      RNA_def_struct_sdna(srna, "Camera");
 +      RNA_def_struct_ui_text(srna, "Background Images", "Collection of background images");
 +
 +      func = RNA_def_function(srna, "new", "rna_Camera_background_images_new");
 +      RNA_def_function_ui_description(func, "Add new background image");
 +      parm = RNA_def_pointer(func, "image", "CameraBackgroundImage", "", "Image displayed as viewport background");
 +      RNA_def_function_return(func, parm);
 +
 +      func = RNA_def_function(srna, "remove", "rna_Camera_background_images_remove");
 +      RNA_def_function_ui_description(func, "Remove background image");
 +      RNA_def_function_flag(func, FUNC_USE_REPORTS);
 +      parm = RNA_def_pointer(func, "image", "CameraBackgroundImage", "", "Image displayed as viewport background");
 +      RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
 +      RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
 +
 +      func = RNA_def_function(srna, "clear", "rna_Camera_background_images_clear");
 +      RNA_def_function_ui_description(func, "Remove all background images");
 +}
 +
  static void rna_def_camera_stereo_data(BlenderRNA *brna)
  {
        StructRNA *srna;
index 682e0ff34040e137f66aeb54974bf7fc64e3b670,fda92ff7c0dfefb070bd69b63243b6be69acd457..5600935c56749e41b296ed5d3bebd4c35f9db10a
@@@ -4745,25 -4942,13 +4753,25 @@@ static void rna_def_gpu_dof_fx(BlenderR
        RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect");
        RNA_def_property_range(prop, 0, 16);
        RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL);
-       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
  
 +      prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
 +      RNA_def_property_ui_text(prop, "Rotation", "Rotation of blades in apperture");
 +      RNA_def_property_range(prop, -M_PI, M_PI);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
 +      prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE);
 +      RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh");
 +      RNA_def_property_range(prop, 0.0000001f, FLT_MAX);
 +      RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
 +      RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 +
        prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1);
        RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
-       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
  
 +      /* NOTE: high quality is always supported */
        prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@@ -6253,6 -6474,19 +6261,11 @@@ static void rna_def_scene_render_data(B
        RNA_def_property_ui_text(prop, "Textured Solid", "Draw face-assigned textures in solid draw method");
        RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
  
 -      /* layers */
 -      prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
 -      RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
 -      RNA_def_property_struct_type(prop, "SceneRenderLayer");
 -      RNA_def_property_ui_text(prop, "Render Layers", "");
 -      rna_def_render_layers(brna, prop);
 -
 -
+       prop = RNA_def_property(srna, "use_sequencer_gl_dof", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_CAMERA_DOF);
+       RNA_def_property_ui_text(prop, "Depth of Field", "Use depth of field using the values from scene strip active camera");
+       RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
        prop = RNA_def_property(srna, "use_single_layer", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_SINGLE_LAYER);
        RNA_def_property_ui_text(prop, "Single Layer", "Only render the active layer");
index 372b34f9df2afe42af9ceb2de321aa402e82d4d8,57f4219f23f027ff48a1fab2920b4b23f9816bdc..c3ae4af1964cbed8fd042009b23cfc3802234144
@@@ -1036,16 -1027,16 +1036,16 @@@ static ImBuf *blend_file_thumb(const bC
        /* gets scaled to BLEN_THUMB_SIZE */
        if (scene->camera) {
                ibuf = ED_view3d_draw_offscreen_imbuf_simple(
 -                      scene, scene->camera,
 +                      &eval_ctx, scene, view_layer, scene->camera,
                        BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
-                       IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, 0, false, NULL,
+                       IB_rect, OB_SOLID, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
                        NULL, NULL, err_out);
        }
        else {
                ibuf = ED_view3d_draw_offscreen_imbuf(
 -                      scene, v3d, ar,
 +                      &eval_ctx, scene, view_layer, v3d, ar,
                        BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
-                       IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
+                       IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
                        NULL, NULL, err_out);
        }