Edit Mode overlay: Optimisation
[blender.git] / source / blender / editors / space_view3d / view3d_draw_legacy.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/view3d_draw_legacy.c
28  *  \ingroup spview3d
29  */
30
31 #include <string.h>
32 #include <stdio.h>
33 #include <math.h>
34
35 #include "DNA_armature_types.h"
36 #include "DNA_camera_types.h"
37 #include "DNA_customdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_group_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_key_types.h"
42 #include "DNA_lamp_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_world_types.h"
45 #include "DNA_brush_types.h"
46
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_math.h"
51 #include "BLI_jitter.h"
52 #include "BLI_utildefines.h"
53 #include "BLI_endian_switch.h"
54 #include "BLI_threads.h"
55
56 #include "BKE_anim.h"
57 #include "BKE_camera.h"
58 #include "BKE_context.h"
59 #include "BKE_customdata.h"
60 #include "BKE_DerivedMesh.h"
61 #include "BKE_image.h"
62 #include "BKE_key.h"
63 #include "BKE_layer.h"
64 #include "BKE_main.h"
65 #include "BKE_object.h"
66 #include "BKE_global.h"
67 #include "BKE_paint.h"
68 #include "BKE_scene.h"
69 #include "BKE_screen.h"
70 #include "BKE_unit.h"
71 #include "BKE_movieclip.h"
72
73 #include "RE_engine.h"
74
75 #include "IMB_imbuf_types.h"
76 #include "IMB_imbuf.h"
77 #include "IMB_colormanagement.h"
78
79 #include "BIF_gl.h"
80 #include "BIF_glutil.h"
81
82 #include "WM_api.h"
83
84 #include "BLF_api.h"
85 #include "BLT_translation.h"
86
87 #include "ED_armature.h"
88 #include "ED_keyframing.h"
89 #include "ED_gpencil.h"
90 #include "ED_screen.h"
91 #include "ED_space_api.h"
92 #include "ED_screen_types.h"
93 #include "ED_transform.h"
94
95 #include "UI_interface.h"
96 #include "UI_interface_icons.h"
97 #include "UI_resources.h"
98
99 #include "GPU_draw.h"
100 #include "GPU_framebuffer.h"
101 #include "GPU_material.h"
102 #include "GPU_compositing.h"
103 #include "GPU_extensions.h"
104 #include "GPU_immediate.h"
105
106 #include "view3d_intern.h"  /* own include */
107
108 /* prototypes */
109 static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
110                                             float winmat[4][4], const char *viewname);
111
112 void circ(float x, float y, float rad)
113 {
114         glBegin(GL_LINE_LOOP);
115         const int segments = 32;
116         for (int i = 0; i < segments; ++i) {
117                 float angle = 2 * M_PI * ((float)i / (float)segments);
118                 glVertex2f(x + rad * cosf(angle),
119                            y + rad * sinf(angle));
120         }
121         glEnd();
122 }
123
124
125 /* ********* custom clipping *********** */
126
127 static void view3d_draw_clipping(RegionView3D *rv3d)
128 {
129         BoundBox *bb = rv3d->clipbb;
130
131         if (bb) {
132                 const unsigned int clipping_index[6][4] = {
133                         {0, 1, 2, 3},
134                         {0, 4, 5, 1},
135                         {4, 7, 6, 5},
136                         {7, 3, 2, 6},
137                         {1, 5, 6, 2},
138                         {7, 4, 0, 3}
139                 };
140
141                 /* fill in zero alpha for rendering & re-projection [#31530] */
142                 unsigned char col[4];
143                 UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
144                 glColor4ubv(col);
145
146                 glEnable(GL_BLEND);
147                 glEnableClientState(GL_VERTEX_ARRAY);
148                 glVertexPointer(3, GL_FLOAT, 0, bb->vec);
149                 glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
150                 glDisableClientState(GL_VERTEX_ARRAY);
151                 glDisable(GL_BLEND);
152         }
153 }
154
155 void ED_view3d_clipping_set(RegionView3D *rv3d)
156 {
157         double plane[4];
158         const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
159
160         for (unsigned a = 0; a < tot; a++) {
161                 copy_v4db_v4fl(plane, rv3d->clip[a]);
162                 glClipPlane(GL_CLIP_PLANE0 + a, plane);
163                 glEnable(GL_CLIP_PLANE0 + a);
164         }
165 }
166
167 /* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
168 void ED_view3d_clipping_disable(void)
169 {
170         for (unsigned a = 0; a < 6; a++) {
171                 glDisable(GL_CLIP_PLANE0 + a);
172         }
173 }
174 void ED_view3d_clipping_enable(void)
175 {
176         for (unsigned a = 0; a < 6; a++) {
177                 glEnable(GL_CLIP_PLANE0 + a);
178         }
179 }
180
181 static bool view3d_clipping_test(const float co[3], const float clip[6][4])
182 {
183         if (plane_point_side_v3(clip[0], co) > 0.0f)
184                 if (plane_point_side_v3(clip[1], co) > 0.0f)
185                         if (plane_point_side_v3(clip[2], co) > 0.0f)
186                                 if (plane_point_side_v3(clip[3], co) > 0.0f)
187                                         return false;
188
189         return true;
190 }
191
192 /* for 'local' ED_view3d_clipping_local must run first
193  * then all comparisons can be done in localspace */
194 bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
195 {
196         return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
197 }
198
199 /* ********* end custom clipping *********** */
200
201 static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
202 {
203         BIFIconID icon;
204         
205         if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
206                 icon = ICON_AXIS_TOP;
207         else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
208                 icon = ICON_AXIS_FRONT;
209         else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
210                 icon = ICON_AXIS_SIDE;
211         else return;
212         
213         glEnable(GL_BLEND);
214         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
215         
216         UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
217         
218         glDisable(GL_BLEND);
219 }
220
221 /* *********************** backdraw for selection *************** */
222
223 static void backdrawview3d(Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d)
224 {
225         RegionView3D *rv3d = ar->regiondata;
226         struct Base *base = sl->basact;
227         int multisample_enabled;
228
229         BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
230
231         if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
232                      BKE_paint_select_face_test(base->object)))
233         {
234                 /* do nothing */
235         }
236         /* texture paint mode sampling */
237         else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
238                  (v3d->drawtype > OB_WIRE))
239         {
240                 /* do nothing */
241         }
242         else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
243                  V3D_IS_ZBUF(v3d))
244         {
245                 /* do nothing */
246         }
247         else if (scene->obedit &&
248                  V3D_IS_ZBUF(v3d))
249         {
250                 /* do nothing */
251         }
252         else {
253                 v3d->flag &= ~V3D_INVALID_BACKBUF;
254                 return;
255         }
256
257         if (!(v3d->flag & V3D_INVALID_BACKBUF))
258                 return;
259
260 #if 0
261         if (test) {
262                 if (qtest()) {
263                         addafterqueue(ar->win, BACKBUFDRAW, 1);
264                         return;
265                 }
266         }
267 #endif
268
269         if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
270         
271         /* dithering and AA break color coding, so disable */
272         glDisable(GL_DITHER);
273
274         multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
275         if (multisample_enabled)
276                 glDisable(GL_MULTISAMPLE);
277
278         if (win->multisamples != USER_MULTISAMPLE_NONE) {
279                 /* for multisample we use an offscreen FBO. multisample drawing can fail
280                  * with color coded selection drawing, and reading back depths from such
281                  * a buffer can also cause a few seconds freeze on OS X / NVidia. */
282                 int w = BLI_rcti_size_x(&ar->winrct);
283                 int h = BLI_rcti_size_y(&ar->winrct);
284                 char error[256];
285
286                 if (rv3d->gpuoffscreen) {
287                         if (GPU_offscreen_width(rv3d->gpuoffscreen)  != w ||
288                             GPU_offscreen_height(rv3d->gpuoffscreen) != h)
289                         {
290                                 GPU_offscreen_free(rv3d->gpuoffscreen);
291                                 rv3d->gpuoffscreen = NULL;
292                         }
293                 }
294
295                 if (!rv3d->gpuoffscreen) {
296                         rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
297
298                         if (!rv3d->gpuoffscreen)
299                                 fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
300                 }
301         }
302
303         if (rv3d->gpuoffscreen)
304                 GPU_offscreen_bind(rv3d->gpuoffscreen, true);
305         else
306                 glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
307
308         glClearColor(0.0, 0.0, 0.0, 0.0);
309         if (v3d->zbuf) {
310                 glEnable(GL_DEPTH_TEST);
311                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
312         }
313         else {
314                 glClear(GL_COLOR_BUFFER_BIT);
315                 glDisable(GL_DEPTH_TEST);
316         }
317         
318         if (rv3d->rflag & RV3D_CLIPPING)
319                 ED_view3d_clipping_set(rv3d);
320         
321         G.f |= G_BACKBUFSEL;
322         
323         if (base && ((base->flag & BASE_VISIBLED) != 0))
324                 draw_object_backbufsel(scene, v3d, rv3d, base->object);
325         
326         if (rv3d->gpuoffscreen)
327                 GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
328         else
329                 ar->swap = 0; /* mark invalid backbuf for wm draw */
330
331         v3d->flag &= ~V3D_INVALID_BACKBUF;
332
333         G.f &= ~G_BACKBUFSEL;
334         v3d->zbuf = false;
335         glDisable(GL_DEPTH_TEST);
336         glEnable(GL_DITHER);
337         if (multisample_enabled)
338                 glEnable(GL_MULTISAMPLE);
339
340         if (rv3d->rflag & RV3D_CLIPPING)
341                 ED_view3d_clipping_disable();
342 }
343
344 void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
345 {
346         RegionView3D *rv3d = ar->regiondata;
347
348         if (rv3d->gpuoffscreen) {
349                 GPU_offscreen_bind(rv3d->gpuoffscreen, true);
350                 glReadBuffer(GL_COLOR_ATTACHMENT0);
351                 glReadPixels(x, y, w, h, format, type, data);
352                 GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
353         }
354         else {
355                 glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
356         }
357 }
358
359 /* XXX depth reading exception, for code not using gpu offscreen */
360 static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
361 {
362         glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
363 }
364
365 void ED_view3d_backbuf_validate(ViewContext *vc)
366 {
367         if (vc->v3d->flag & V3D_INVALID_BACKBUF)
368                 backdrawview3d(vc->scene, vc->sl, vc->win, vc->ar, vc->v3d);
369 }
370
371 /**
372  * allow for small values [0.5 - 2.5],
373  * and large values, FLT_MAX by clamping by the area size
374  */
375 int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
376 {
377         return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
378 }
379
380 /* samples a single pixel (copied from vpaint) */
381 unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
382 {
383         if (x >= vc->ar->winx || y >= vc->ar->winy) {
384                 return 0;
385         }
386
387         ED_view3d_backbuf_validate(vc);
388
389         unsigned int col;
390         view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
391         glReadBuffer(GL_BACK);
392
393         if (ENDIAN_ORDER == B_ENDIAN) {
394                 BLI_endian_switch_uint32(&col);
395         }
396
397         return GPU_select_to_index(col);
398 }
399
400 /* reads full rect, converts indices */
401 ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
402 {
403         /* clip */
404         const rcti clip = {
405             max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
406             max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
407         const int size_clip[2] = {
408             BLI_rcti_size_x(&clip) + 1,
409             BLI_rcti_size_y(&clip) + 1};
410
411         if (UNLIKELY((clip.xmin > clip.xmax) ||
412                      (clip.ymin > clip.ymax)))
413         {
414                 return NULL;
415         }
416
417         ImBuf *ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
418
419         ED_view3d_backbuf_validate(vc);
420
421         view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
422
423         glReadBuffer(GL_BACK);
424
425         if (ENDIAN_ORDER == B_ENDIAN) {
426                 IMB_convert_rgba_to_abgr(ibuf_clip);
427         }
428
429         GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
430         
431         if ((clip.xmin == xmin) &&
432             (clip.xmax == xmax) &&
433             (clip.ymin == ymin) &&
434             (clip.ymax == ymax))
435         {
436                 return ibuf_clip;
437         }
438         else {
439                 /* put clipped result into a non-clipped buffer */
440                 const int size[2] = {
441                     (xmax - xmin + 1),
442                     (ymax - ymin + 1)};
443
444                 ImBuf *ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
445
446                 IMB_rectcpy(
447                         ibuf_full, ibuf_clip,
448                         clip.xmin - xmin, clip.ymin - ymin,
449                         0, 0,
450                         size_clip[0], size_clip[1]);
451                 IMB_freeImBuf(ibuf_clip);
452                 return ibuf_full;
453         }
454 }
455
456 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
457 unsigned int ED_view3d_backbuf_sample_rect(
458         ViewContext *vc, const int mval[2], int size,
459         unsigned int min, unsigned int max, float *r_dist)
460 {
461         int dirvec[4][2];
462
463         const int amount = (size - 1) / 2;
464
465         const int minx = mval[0] - (amount + 1);
466         const int miny = mval[1] - (amount + 1);
467         ImBuf *buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
468         if (!buf) return 0;
469
470         unsigned index = 0;
471         int rc = 0;
472         
473         dirvec[0][0] = 1; dirvec[0][1] = 0;
474         dirvec[1][0] = 0; dirvec[1][1] = -size;
475         dirvec[2][0] = -1; dirvec[2][1] = 0;
476         dirvec[3][0] = 0; dirvec[3][1] = size;
477         
478         const unsigned *bufmin = buf->rect;
479         const unsigned *tbuf = buf->rect;
480         const unsigned *bufmax = buf->rect + size * size;
481         tbuf += amount * size + amount;
482         
483         for (int nr = 1; nr <= size; nr++) {
484                 for (int a = 0; a < 2; a++) {
485                         for (int b = 0; b < nr; b++) {
486                                 if (*tbuf && *tbuf >= min && *tbuf < max) {
487                                         /* we got a hit */
488
489                                         /* get x,y pixel coords from the offset
490                                          * (manhatten distance in keeping with other screen-based selection) */
491                                         *r_dist = (float)(
492                                                 abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
493                                                 abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
494
495                                         /* indices start at 1 here */
496                                         index = (*tbuf - min) + 1;
497                                         goto exit;
498                                 }
499                                 
500                                 tbuf += (dirvec[rc][0] + dirvec[rc][1]);
501                                 
502                                 if (tbuf < bufmin || tbuf >= bufmax) {
503                                         goto exit;
504                                 }
505                         }
506                         rc++;
507                         rc &= 3;
508                 }
509         }
510
511 exit:
512         IMB_freeImBuf(buf);
513         return index;
514 }
515
516
517 /* ************************************************************* */
518
519 static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
520 {
521         if (BKE_image_is_stereo(ima)) {
522                 iuser->flag |= IMA_SHOW_STEREO;
523
524                 if ((scene->r.scemode & R_MULTIVIEW) == 0) {
525                         iuser->multiview_eye = STEREO_LEFT_ID;
526                 }
527                 else if (v3d->stereo3d_camera != STEREO_3D_ID) {
528                         /* show only left or right camera */
529                         iuser->multiview_eye = v3d->stereo3d_camera;
530                 }
531
532                 BKE_image_multiview_index(ima, iuser);
533         }
534         else {
535                 iuser->flag &= ~IMA_SHOW_STEREO;
536         }
537 }
538
539 static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
540                               const bool do_foreground, const bool do_camera_frame)
541 {
542         RegionView3D *rv3d = ar->regiondata;
543         int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
544
545         for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
546                 bgpic->iuser.scene = scene;  /* Needed for render results. */
547
548                 if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
549                         continue;
550
551                 if ((bgpic->view == 0) || /* zero for any */
552                     (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
553                     (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
554                 {
555                         float image_aspect[2];
556                         float x1, y1, x2, y2, centx, centy;
557
558                         void *lock;
559
560                         Image *ima = NULL;
561
562                         /* disable individual images */
563                         if ((bgpic->flag & V3D_BGPIC_DISABLED))
564                                 continue;
565
566                         ImBuf *ibuf = NULL;
567                         ImBuf *freeibuf = NULL;
568                         ImBuf *releaseibuf = NULL;
569                         if (bgpic->source == V3D_BGPIC_IMAGE) {
570                                 ima = bgpic->ima;
571                                 if (ima == NULL)
572                                         continue;
573                                 BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0);
574                                 if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
575                                         ibuf = NULL; /* frame is out of range, dont show */
576                                 }
577                                 else {
578                                         view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
579                                         ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
580                                         releaseibuf = ibuf;
581                                 }
582
583                                 image_aspect[0] = ima->aspx;
584                                 image_aspect[1] = ima->aspy;
585                         }
586                         else if (bgpic->source == V3D_BGPIC_MOVIE) {
587                                 /* TODO: skip drawing when out of frame range (as image sequences do above) */
588                                 MovieClip *clip = NULL;
589
590                                 if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
591                                         if (scene->camera)
592                                                 clip = BKE_object_movieclip_get(scene, scene->camera, true);
593                                 }
594                                 else {
595                                         clip = bgpic->clip;
596                                 }
597
598                                 if (clip == NULL)
599                                         continue;
600
601                                 BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
602                                 ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
603
604                                 image_aspect[0] = clip->aspx;
605                                 image_aspect[1] = clip->aspy;
606
607                                 /* working with ibuf from image and clip has got different workflow now.
608                                  * ibuf acquired from clip is referenced by cache system and should
609                                  * be dereferenced after usage. */
610                                 freeibuf = ibuf;
611                         }
612                         else {
613                                 /* perhaps when loading future files... */
614                                 BLI_assert(0);
615                                 copy_v2_fl(image_aspect, 1.0f);
616                         }
617
618                         if (ibuf == NULL)
619                                 continue;
620
621                         if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
622                                 if (freeibuf)
623                                         IMB_freeImBuf(freeibuf);
624                                 if (releaseibuf)
625                                         BKE_image_release_ibuf(ima, releaseibuf, lock);
626
627                                 continue;
628                         }
629
630                         if (ibuf->rect == NULL)
631                                 IMB_rect_from_float(ibuf);
632
633                         if (rv3d->persp == RV3D_CAMOB) {
634
635                                 if (do_camera_frame) {
636                                         rctf vb;
637                                         ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
638                                         x1 = vb.xmin;
639                                         y1 = vb.ymin;
640                                         x2 = vb.xmax;
641                                         y2 = vb.ymax;
642                                 }
643                                 else {
644                                         x1 = ar->winrct.xmin;
645                                         y1 = ar->winrct.ymin;
646                                         x2 = ar->winrct.xmax;
647                                         y2 = ar->winrct.ymax;
648                                 }
649
650                                 /* apply offset last - camera offset is different to offset in blender units */
651                                 /* so this has some sane way of working - this matches camera's shift _exactly_ */
652                                 {
653                                         const float max_dim = max_ff(x2 - x1, y2 - y1);
654                                         const float xof_scale = bgpic->xof * max_dim;
655                                         const float yof_scale = bgpic->yof * max_dim;
656
657                                         x1 += xof_scale;
658                                         y1 += yof_scale;
659                                         x2 += xof_scale;
660                                         y2 += yof_scale;
661                                 }
662
663                                 centx = (x1 + x2) * 0.5f;
664                                 centy = (y1 + y2) * 0.5f;
665
666                                 /* aspect correction */
667                                 if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
668                                         /* apply aspect from clip */
669                                         const float w_src = ibuf->x * image_aspect[0];
670                                         const float h_src = ibuf->y * image_aspect[1];
671
672                                         /* destination aspect is already applied from the camera frame */
673                                         const float w_dst = x1 - x2;
674                                         const float h_dst = y1 - y2;
675
676                                         const float asp_src = w_src / h_src;
677                                         const float asp_dst = w_dst / h_dst;
678
679                                         if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
680                                                 if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
681                                                         /* fit X */
682                                                         const float div = asp_src / asp_dst;
683                                                         x1 = ((x1 - centx) * div) + centx;
684                                                         x2 = ((x2 - centx) * div) + centx;
685                                                 }
686                                                 else {
687                                                         /* fit Y */
688                                                         const float div = asp_dst / asp_src;
689                                                         y1 = ((y1 - centy) * div) + centy;
690                                                         y2 = ((y2 - centy) * div) + centy;
691                                                 }
692                                         }
693                                 }
694                         }
695                         else {
696                                 float tvec[3];
697                                 float sco[2];
698                                 const float mval_f[2] = {1.0f, 0.0f};
699                                 const float co_zero[3] = {0};
700
701                                 /* calc window coord */
702                                 float zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
703                                 ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
704                                 float fac = 1.0f / max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
705                                 float asp = (float)ibuf->y / (float)ibuf->x;
706
707                                 zero_v3(tvec);
708                                 ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat);
709
710                                 x1 =  sco[0] + fac * (bgpic->xof - bgpic->size);
711                                 y1 =  sco[1] + asp * fac * (bgpic->yof - bgpic->size);
712                                 x2 =  sco[0] + fac * (bgpic->xof + bgpic->size);
713                                 y2 =  sco[1] + asp * fac * (bgpic->yof + bgpic->size);
714
715                                 centx = (x1 + x2) / 2.0f;
716                                 centy = (y1 + y2) / 2.0f;
717                         }
718
719                         /* complete clip? */
720                         rctf clip_rect;
721                         BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
722                         if (bgpic->rotation) {
723                                 BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
724                         }
725
726                         if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
727                                 if (freeibuf)
728                                         IMB_freeImBuf(freeibuf);
729                                 if (releaseibuf)
730                                         BKE_image_release_ibuf(ima, releaseibuf, lock);
731
732                                 continue;
733                         }
734
735                         float zoomx = (x2 - x1) / ibuf->x;
736                         float zoomy = (y2 - y1) / ibuf->y;
737
738                         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
739                         if (zoomx < 1.0f || zoomy < 1.0f) {
740                                 float tzoom = min_ff(zoomx, zoomy);
741                                 int mip = 0;
742
743                                 if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
744                                         IMB_remakemipmap(ibuf, 0);
745                                         ibuf->userflags &= ~IB_MIPMAP_INVALID;
746                                 }
747                                 else if (ibuf->mipmap[0] == NULL)
748                                         IMB_makemipmap(ibuf, 0);
749
750                                 while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
751                                         tzoom *= 2.0f;
752                                         zoomx *= 2.0f;
753                                         zoomy *= 2.0f;
754                                         mip++;
755                                 }
756                                 if (mip > 0)
757                                         ibuf = ibuf->mipmap[mip - 1];
758                         }
759
760                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
761                         glDepthMask(GL_FALSE);
762
763                         glEnable(GL_BLEND);
764                         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
765
766                         glMatrixMode(GL_PROJECTION);
767                         glPushMatrix();
768                         glMatrixMode(GL_MODELVIEW);
769                         glPushMatrix();
770                         ED_region_pixelspace(ar);
771
772                         glTranslatef(centx, centy, 0.0);
773                         glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
774
775                         if (bgpic->flag & V3D_BGPIC_FLIP_X) {
776                                 zoomx *= -1.0f;
777                                 x1 = x2;
778                         }
779                         if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
780                                 zoomy *= -1.0f;
781                                 y1 = y2;
782                         }
783
784                         float col[4] = {1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend};
785                         immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
786                         immDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect,
787                                          zoomx, zoomy, col);
788
789                         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
790
791                         glMatrixMode(GL_PROJECTION);
792                         glPopMatrix();
793                         glMatrixMode(GL_MODELVIEW);
794                         glPopMatrix();
795
796                         glDisable(GL_BLEND);
797
798                         glDepthMask(GL_TRUE);
799                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
800
801                         if (freeibuf)
802                                 IMB_freeImBuf(freeibuf);
803                         if (releaseibuf)
804                                 BKE_image_release_ibuf(ima, releaseibuf, lock);
805                 }
806         }
807 }
808
809 static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
810                                    const bool do_foreground, const bool do_camera_frame)
811 {
812         RegionView3D *rv3d = ar->regiondata;
813
814         if ((v3d->flag & V3D_DISPBGPICS) == 0)
815                 return;
816
817         /* disabled - mango request, since footage /w only render is quite useful
818          * and this option is easy to disable all background images at once */
819 #if 0
820         if (v3d->flag2 & V3D_RENDER_OVERRIDE)
821                 return;
822 #endif
823
824         if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
825                 if (rv3d->persp == RV3D_CAMOB) {
826                         view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
827                 }
828         }
829         else {
830                 view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
831         }
832 }
833
834 /* ****************** View3d afterdraw *************** */
835
836 typedef struct View3DAfter {
837         struct View3DAfter *next, *prev;
838         struct BaseLegacy *base;
839         short dflag;
840 } View3DAfter;
841
842 /* temp storage of Objects that need to be drawn as last */
843 void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag)
844 {
845         View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
846         BLI_assert((base->flag_legacy & OB_FROMDUPLI) == 0);
847         BLI_addtail(lb, v3da);
848         v3da->base = base;
849         v3da->dflag = dflag;
850 }
851
852 /* disables write in zbuffer and draws it over */
853 static void view3d_draw_transp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d)
854 {
855         View3DAfter *v3da;
856         
857         glDepthMask(GL_FALSE);
858         v3d->transp = true;
859         
860         while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
861                 draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
862                 MEM_freeN(v3da);
863         }
864         v3d->transp = false;
865         
866         glDepthMask(GL_TRUE);
867         
868 }
869
870 /* clears zbuffer and draws it over */
871 static void view3d_draw_xray(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear)
872 {
873         if (*clear && v3d->zbuf) {
874                 glClear(GL_DEPTH_BUFFER_BIT);
875                 *clear = false;
876         }
877
878         v3d->xray = true;
879         View3DAfter *v3da;
880         while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
881                 draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
882                 MEM_freeN(v3da);
883         }
884         v3d->xray = false;
885 }
886
887
888 /* clears zbuffer and draws it over */
889 static void view3d_draw_xraytransp(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, const bool clear)
890 {
891         if (clear && v3d->zbuf)
892                 glClear(GL_DEPTH_BUFFER_BIT);
893
894         v3d->xray = true;
895         v3d->transp = true;
896         
897         glDepthMask(GL_FALSE);
898
899         View3DAfter *v3da;
900         while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
901                 draw_object(scene, sl, ar, v3d, v3da->base, v3da->dflag);
902                 MEM_freeN(v3da);
903         }
904
905         v3d->transp = false;
906         v3d->xray = false;
907
908         glDepthMask(GL_TRUE);
909 }
910
911 /* *********************** */
912
913 /*
914  * In most cases call draw_dupli_objects,
915  * draw_dupli_objects_color was added because when drawing set dupli's
916  * we need to force the color
917  */
918
919 #if 0
920 int dupli_ob_sort(void *arg1, void *arg2)
921 {
922         void *p1 = ((DupliObject *)arg1)->ob;
923         void *p2 = ((DupliObject *)arg2)->ob;
924         int val = 0;
925         if (p1 < p2) val = -1;
926         else if (p1 > p2) val = 1;
927         return val;
928 }
929 #endif
930
931
932 static DupliObject *dupli_step(DupliObject *dob)
933 {
934         while (dob && dob->no_draw)
935                 dob = dob->next;
936         return dob;
937 }
938
939 static void draw_dupli_objects_color(
940         Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base,
941         const short dflag, const int color)
942 {
943         RegionView3D *rv3d = ar->regiondata;
944         ListBase *lb;
945         LodLevel *savedlod;
946         Base tbase = {NULL};
947         BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
948         unsigned char color_rgb[3];
949         const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
950         short transflag;
951         char dt;
952         short dtx;
953         DupliApplyData *apply_data;
954
955         if ((base->flag & BASE_VISIBLED) == 0) return;
956         if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
957
958         if (dflag & DRAW_CONSTCOLOR) {
959                 BLI_assert(color == TH_UNDEFINED);
960         }
961         else {
962                 UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
963         }
964
965         tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy;
966         tbase.flag = base->flag;
967         lb = object_duplilist(G.main->eval_ctx, scene, base->object);
968         // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
969
970         apply_data = duplilist_apply(base->object, scene, lb);
971
972         DupliObject *dob_next = NULL;
973         DupliObject *dob = dupli_step(lb->first);
974         if (dob) dob_next = dupli_step(dob->next);
975
976         for (; dob; dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
977                 bool testbb = false;
978
979                 tbase.object = dob->ob;
980
981                 /* Make sure lod is updated from dupli's position */
982                 savedlod = dob->ob->currentlod;
983
984 #ifdef WITH_GAMEENGINE
985                 if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
986                         BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
987                 }
988 #endif
989
990                 /* extra service: draw the duplicator in drawtype of parent, minimum taken
991                  * to allow e.g. boundbox box objects in groups for LOD */
992                 dt = tbase.object->dt;
993                 tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
994
995                 /* inherit draw extra, but not if a boundbox under the assumption that this
996                  * is intended to speed up drawing, and drawing extra (especially wire) can
997                  * slow it down too much */
998                 dtx = tbase.object->dtx;
999                 if (tbase.object->dt != OB_BOUNDBOX)
1000                         tbase.object->dtx = base->object->dtx;
1001
1002                 /* negative scale flag has to propagate */
1003                 transflag = tbase.object->transflag;
1004
1005                 if (is_negative_m4(dob->mat))
1006                         tbase.object->transflag |= OB_NEG_SCALE;
1007                 else
1008                         tbase.object->transflag &= ~OB_NEG_SCALE;
1009                 
1010                 /* should move outside the loop but possible color is set in draw_object still */
1011                 if ((dflag & DRAW_CONSTCOLOR) == 0) {
1012                         glColor3ubv(color_rgb);
1013                 }
1014                 
1015                 if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
1016                         bb = *bb_tmp; /* must make a copy  */
1017                         testbb = true;
1018                 }
1019
1020                 if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
1021                         copy_m4_m4(dob->ob->obmat, dob->mat);
1022                         GPU_begin_dupli_object(dob);
1023                         draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
1024                         GPU_end_dupli_object();
1025                 }
1026                 
1027                 tbase.object->dt = dt;
1028                 tbase.object->dtx = dtx;
1029                 tbase.object->transflag = transflag;
1030                 tbase.object->currentlod = savedlod;
1031         }
1032
1033         if (apply_data) {
1034                 duplilist_restore(lb, apply_data);
1035                 duplilist_free_apply_data(apply_data);
1036         }
1037
1038         free_object_duplilist(lb);
1039 }
1040
1041 void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base)
1042 {
1043         /* define the color here so draw_dupli_objects_color can be called
1044          * from the set loop */
1045         
1046         int color = (base->flag & BASE_SELECTED) ? TH_SELECT : TH_WIRE;
1047         /* debug */
1048         if (base->object->dup_group && base->object->dup_group->id.us < 1)
1049                 color = TH_REDALERT;
1050         
1051         draw_dupli_objects_color(scene, sl, ar, v3d, base, 0, color);
1052 }
1053
1054 /* XXX warning, not using gpu offscreen here */
1055 void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
1056 {
1057         /* clamp rect by region */
1058         rcti r = {
1059                 .xmin = 0,
1060                 .xmax = ar->winx - 1,
1061                 .ymin = 0,
1062                 .ymax = ar->winy - 1
1063         };
1064
1065         /* Constrain rect to depth bounds */
1066         BLI_rcti_isect(&r, rect, rect);
1067
1068         /* assign values to compare with the ViewDepths */
1069         int x = rect->xmin;
1070         int y = rect->ymin;
1071
1072         int w = BLI_rcti_size_x(rect);
1073         int h = BLI_rcti_size_y(rect);
1074
1075         if (w <= 0 || h <= 0) {
1076                 if (d->depths)
1077                         MEM_freeN(d->depths);
1078                 d->depths = NULL;
1079
1080                 d->damaged = false;
1081         }
1082         else if (d->w != w ||
1083                  d->h != h ||
1084                  d->x != x ||
1085                  d->y != y ||
1086                  d->depths == NULL
1087                  )
1088         {
1089                 d->x = x;
1090                 d->y = y;
1091                 d->w = w;
1092                 d->h = h;
1093
1094                 if (d->depths)
1095                         MEM_freeN(d->depths);
1096
1097                 d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
1098                 
1099                 d->damaged = true;
1100         }
1101
1102         if (d->damaged) {
1103                 /* XXX using special function here, it doesn't use the gpu offscreen system */
1104                 view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
1105                 glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
1106                 d->damaged = false;
1107         }
1108 }
1109
1110 /* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
1111 void ED_view3d_depth_update(ARegion *ar)
1112 {
1113         RegionView3D *rv3d = ar->regiondata;
1114         
1115         /* Create storage for, and, if necessary, copy depth buffer */
1116         if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
1117         if (rv3d->depths) {
1118                 ViewDepths *d = rv3d->depths;
1119                 if (d->w != ar->winx ||
1120                     d->h != ar->winy ||
1121                     !d->depths)
1122                 {
1123                         d->w = ar->winx;
1124                         d->h = ar->winy;
1125                         if (d->depths)
1126                                 MEM_freeN(d->depths);
1127                         d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
1128                         d->damaged = true;
1129                 }
1130                 
1131                 if (d->damaged) {
1132                         view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
1133                         glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
1134                         
1135                         d->damaged = false;
1136                 }
1137         }
1138 }
1139
1140 /* utility function to find the closest Z value, use for autodepth */
1141 float view3d_depth_near(ViewDepths *d)
1142 {
1143         /* convert to float for comparisons */
1144         const float near = (float)d->depth_range[0];
1145         const float far_real = (float)d->depth_range[1];
1146         float far = far_real;
1147
1148         const float *depths = d->depths;
1149         float depth = FLT_MAX;
1150         int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
1151
1152         /* far is both the starting 'far' value
1153          * and the closest value found. */
1154         while (i--) {
1155                 depth = *depths++;
1156                 if ((depth < far) && (depth > near)) {
1157                         far = depth;
1158                 }
1159         }
1160
1161         return far == far_real ? FLT_MAX : far;
1162 }
1163
1164 void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
1165 {
1166         short zbuf = v3d->zbuf;
1167         RegionView3D *rv3d = ar->regiondata;
1168
1169         view3d_winmatrix_set(ar, v3d, NULL);
1170         view3d_viewmatrix_set(scene, v3d, rv3d);  /* note: calls BKE_object_where_is_calc for camera... */
1171
1172         mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
1173         invert_m4_m4(rv3d->persinv, rv3d->persmat);
1174         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
1175
1176         glClear(GL_DEPTH_BUFFER_BIT);
1177
1178         glLoadMatrixf(rv3d->viewmat);
1179
1180         v3d->zbuf = true;
1181         glEnable(GL_DEPTH_TEST);
1182
1183         if (v3d->flag2 & V3D_SHOW_GPENCIL) {
1184                 ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
1185         }
1186         
1187         v3d->zbuf = zbuf;
1188 }
1189
1190 void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
1191 {
1192         RegionView3D *rv3d = ar->regiondata;
1193         Base *base;
1194         short zbuf = v3d->zbuf;
1195         short flag = v3d->flag;
1196         float glalphaclip = U.glalphaclip;
1197         int obcenter_dia = U.obcenter_dia;
1198         SceneLayer *sl = BKE_scene_layer_context_active(scene);
1199         /* no need for color when drawing depth buffer */
1200         const short dflag_depth = DRAW_CONSTCOLOR;
1201         /* temp set drawtype to solid */
1202         /* Setting these temporarily is not nice */
1203         v3d->flag &= ~V3D_SELECT_OUTLINE;
1204         U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
1205         U.obcenter_dia = 0;
1206         
1207         view3d_winmatrix_set(ar, v3d, NULL);
1208         view3d_viewmatrix_set(scene, v3d, rv3d);  /* note: calls BKE_object_where_is_calc for camera... */
1209         
1210         mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
1211         invert_m4_m4(rv3d->persinv, rv3d->persmat);
1212         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
1213         
1214         glClear(GL_DEPTH_BUFFER_BIT);
1215         
1216         glLoadMatrixf(rv3d->viewmat);
1217         
1218         if (rv3d->rflag & RV3D_CLIPPING) {
1219                 ED_view3d_clipping_set(rv3d);
1220         }
1221         /* get surface depth without bias */
1222         rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
1223
1224         v3d->zbuf = true;
1225         glEnable(GL_DEPTH_TEST);
1226         
1227         /* draw set first */
1228         if (scene->set) {
1229                 Scene *sce_iter;
1230                 for (SETLOOPER(scene->set, sce_iter, base)) {
1231                         if ((base->flag & BASE_VISIBLED) != 0) {
1232                                 draw_object(scene, sl, ar, v3d, base, 0);
1233                                 if (base->object->transflag & OB_DUPLI) {
1234                                         draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED);
1235                                 }
1236                         }
1237                 }
1238         }
1239         
1240         for (base = sl->object_bases.first; base; base = base->next) {
1241                 if ((base->flag & BASE_VISIBLED) != 0) {
1242                         /* dupli drawing */
1243                         if (base->object->transflag & OB_DUPLI) {
1244                                 draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED);
1245                         }
1246                         draw_object(scene, sl, ar, v3d, base, dflag_depth);
1247                 }
1248         }
1249         
1250         /* this isn't that nice, draw xray objects as if they are normal */
1251         if (v3d->afterdraw_transp.first ||
1252             v3d->afterdraw_xray.first ||
1253             v3d->afterdraw_xraytransp.first)
1254         {
1255                 View3DAfter *v3da;
1256                 int mask_orig;
1257
1258                 v3d->xray = true;
1259                 
1260                 /* transp materials can change the depth mask, see #21388 */
1261                 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
1262
1263
1264                 if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
1265                         glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
1266                         for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
1267                                 draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
1268                         }
1269                         glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
1270                 }
1271
1272                 /* draw 3 passes, transp/xray/xraytransp */
1273                 v3d->xray = false;
1274                 v3d->transp = true;
1275                 while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
1276                         draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
1277                         MEM_freeN(v3da);
1278                 }
1279
1280                 v3d->xray = true;
1281                 v3d->transp = false;
1282                 while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
1283                         draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
1284                         MEM_freeN(v3da);
1285                 }
1286
1287                 v3d->xray = true;
1288                 v3d->transp = true;
1289                 while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
1290                         draw_object(scene, sl, ar, v3d, v3da->base, dflag_depth);
1291                         MEM_freeN(v3da);
1292                 }
1293
1294                 
1295                 v3d->xray = false;
1296                 v3d->transp = false;
1297
1298                 glDepthMask(mask_orig);
1299         }
1300         
1301         if (rv3d->rflag & RV3D_CLIPPING) {
1302                 ED_view3d_clipping_disable();
1303         }
1304         rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
1305         
1306         v3d->zbuf = zbuf;
1307         if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
1308
1309         U.glalphaclip = glalphaclip;
1310         v3d->flag = flag;
1311         U.obcenter_dia = obcenter_dia;
1312 }
1313
1314 typedef struct View3DShadow {
1315         struct View3DShadow *next, *prev;
1316         GPULamp *lamp;
1317 } View3DShadow;
1318
1319 static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
1320                                    Object *ob, Object *par,
1321                                    float obmat[4][4], unsigned int lay,
1322                                    ListBase *shadows, SceneRenderLayer *srl)
1323 {
1324         GPULamp *lamp = GPU_lamp_from_blender(scene, ob, par);
1325         
1326         if (lamp) {
1327                 Lamp *la = (Lamp *)ob->data;
1328
1329                 GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
1330                 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
1331                 
1332                 unsigned int layers = lay & v3d->lay;
1333                 if (srl)
1334                         layers &= srl->lay;
1335
1336                 if (layers &&
1337                     GPU_lamp_has_shadow_buffer(lamp) &&
1338                     /* keep last, may do string lookup */
1339                     GPU_lamp_override_visible(lamp, srl, NULL))
1340                 {
1341                         View3DShadow *shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
1342                         shadow->lamp = lamp;
1343                         BLI_addtail(shadows, shadow);
1344                 }
1345         }
1346 }
1347
1348 static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
1349 {
1350         ListBase shadows;
1351         Scene *sce_iter;
1352         Base *base;
1353         World *world = scene->world;
1354         SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
1355         
1356         BLI_listbase_clear(&shadows);
1357         
1358         /* update lamp transform and gather shadow lamps */
1359         for (SETLOOPER(scene, sce_iter, base)) {
1360                 Object *ob = base->object;
1361                 
1362                 if (ob->type == OB_LAMP)
1363                         gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl);
1364                 
1365                 if (ob->transflag & OB_DUPLI) {
1366                         DupliObject *dob;
1367                         ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
1368                         
1369                         for (dob = lb->first; dob; dob = dob->next)
1370                                 if (dob->ob->type == OB_LAMP)
1371                                         gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl);
1372                         
1373                         free_object_duplilist(lb);
1374                 }
1375         }
1376         
1377         /* render shadows after updating all lamps, nested object_duplilist
1378          * don't work correct since it's replacing object matrices */
1379         for (View3DShadow *shadow = shadows.first; shadow; shadow = shadow->next) {
1380                 /* this needs to be done better .. */
1381                 float viewmat[4][4], winmat[4][4];
1382                 ARegion ar = {NULL};
1383                 RegionView3D rv3d = {{{0}}};
1384
1385                 int drawtype = v3d->drawtype;
1386                 int lay = v3d->lay;
1387                 int flag2 = v3d->flag2;
1388
1389                 v3d->drawtype = OB_SOLID;
1390                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
1391                 v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
1392                 v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
1393                 
1394                 int winsize;
1395                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
1396
1397                 ar.regiondata = &rv3d;
1398                 ar.regiontype = RGN_TYPE_WINDOW;
1399                 rv3d.persp = RV3D_CAMOB;
1400                 copy_m4_m4(rv3d.winmat, winmat);
1401                 copy_m4_m4(rv3d.viewmat, viewmat);
1402                 invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
1403                 mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
1404                 invert_m4_m4(rv3d.persinv, rv3d.viewinv);
1405
1406                 /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
1407                 ED_view3d_draw_offscreen(
1408                             scene, v3d, &ar, winsize, winsize, viewmat, winmat,
1409                             false, false, true,
1410                             NULL, NULL, NULL, NULL);
1411                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
1412                 
1413                 v3d->drawtype = drawtype;
1414                 v3d->lay = lay;
1415                 v3d->flag2 = flag2;
1416         }
1417
1418         BLI_freelistN(&shadows);
1419
1420         /* update world values */
1421         if (world) {
1422                 GPU_mist_update_enable(world->mode & WO_MIST);
1423                 GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
1424                 GPU_horizon_update_color(&world->horr);
1425                 GPU_ambient_update_color(&world->ambr);
1426                 GPU_zenith_update_color(&world->zenr);
1427         }
1428 }
1429
1430 /* *********************** customdata **************** */
1431
1432 CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
1433 {
1434         CustomDataMask mask = 0;
1435         const int drawtype = view3d_effective_drawtype(v3d);
1436
1437         if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) ||
1438             ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
1439         {
1440                 mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
1441
1442                 if (BKE_scene_use_new_shading_nodes(scene)) {
1443                         if (drawtype == OB_MATERIAL)
1444                                 mask |= CD_MASK_ORCO;
1445                 }
1446                 else {
1447                         if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) || 
1448                             (drawtype == OB_MATERIAL))
1449                         {
1450                                 mask |= CD_MASK_ORCO;
1451                         }
1452                 }
1453         }
1454
1455         return mask;
1456 }
1457
1458 /* goes over all modes and view3d settings */
1459 CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
1460 {
1461         const Scene *scene = screen->scene;
1462         CustomDataMask mask = CD_MASK_BAREMESH;
1463         
1464         /* check if we need tfaces & mcols due to view mode */
1465         for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
1466                 if (sa->spacetype == SPACE_VIEW3D) {
1467                         mask |= ED_view3d_datamask(scene, sa->spacedata.first);
1468                 }
1469         }
1470
1471         return mask;
1472 }
1473
1474 /**
1475  * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
1476  *
1477  * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
1478  * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
1479  */
1480 static void view3d_draw_objects(
1481         const bContext *C,
1482         Scene *scene, View3D *v3d, ARegion *ar,
1483         const char **grid_unit,
1484         const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
1485 {
1486         SceneLayer *sl = C ? CTX_data_scene_layer(C) : BKE_scene_layer_render_active(scene);
1487         RegionView3D *rv3d = ar->regiondata;
1488         Base *base;
1489         const bool do_camera_frame = !draw_offscreen;
1490         const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
1491         const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
1492         /* only draw grids after in solid modes, else it hovers over mesh wires */
1493         const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
1494         bool do_composite_xray = false;
1495         bool xrayclear = true;
1496
1497         if (!draw_offscreen) {
1498                 ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
1499         }
1500
1501         if (rv3d->rflag & RV3D_CLIPPING)
1502                 view3d_draw_clipping(rv3d);
1503
1504         /* set zbuffer after we draw clipping region */
1505         v3d->zbuf = VP_legacy_use_depth(scene, v3d);
1506
1507         if (v3d->zbuf) {
1508                 glEnable(GL_DEPTH_TEST);
1509         }
1510
1511         /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
1512          * objects if done last */
1513         if (draw_grids) {
1514                 /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
1515                 rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
1516
1517                 if (!draw_floor) {
1518                         ED_region_pixelspace(ar);
1519                         *grid_unit = NULL;  /* drawgrid need this to detect/affect smallest valid unit... */
1520                         VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit);
1521                         /* XXX make function? replaces persp(1) */
1522                         glMatrixMode(GL_PROJECTION);
1523                         glLoadMatrixf(rv3d->winmat);
1524                         glMatrixMode(GL_MODELVIEW);
1525                         glLoadMatrixf(rv3d->viewmat);
1526                 }
1527                 else if (!draw_grids_after) {
1528                         VP_legacy_drawfloor(scene, v3d, grid_unit, true);
1529                 }
1530         }
1531
1532         /* important to do before clipping */
1533         if (do_bgpic) {
1534                 view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
1535         }
1536
1537         if (rv3d->rflag & RV3D_CLIPPING) {
1538                 ED_view3d_clipping_set(rv3d);
1539         }
1540
1541         /* draw set first */
1542         if (scene->set) {
1543                 const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
1544                 Scene *sce_iter;
1545                 for (SETLOOPER(scene->set, sce_iter, base)) {
1546                         if ((base->flag & BASE_VISIBLED) != 0) {
1547                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
1548                                 draw_object(scene, sl, ar, v3d, base, dflag);
1549
1550                                 if (base->object->transflag & OB_DUPLI) {
1551                                         draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag, TH_UNDEFINED);
1552                                 }
1553                         }
1554                 }
1555
1556                 /* Transp and X-ray afterdraw stuff for sets is done later */
1557         }
1558
1559         if (draw_offscreen) {
1560                 for (base = sl->object_bases.first; base; base = base->next) {
1561                         if ((base->flag & BASE_VISIBLED) != 0) {
1562                                 /* dupli drawing */
1563                                 if (base->object->transflag & OB_DUPLI)
1564                                         draw_dupli_objects(scene, sl, ar, v3d, base);
1565
1566                                 draw_object(scene, sl, ar, v3d, base, 0);
1567                         }
1568                 }
1569         }
1570         else {
1571                 unsigned int lay_used = 0;
1572
1573                 /* then draw not selected and the duplis, but skip editmode object */
1574                 for (base = sl->object_bases.first; base; base = base->next) {
1575                         lay_used |= base->lay;
1576
1577                         if ((base->flag & BASE_VISIBLED) != 0) {
1578
1579                                 /* dupli drawing */
1580                                 if (base->object->transflag & OB_DUPLI) {
1581                                         draw_dupli_objects(scene, sl, ar, v3d, base);
1582                                 }
1583                                 if ((base->flag & BASE_SELECTED) == 0) {
1584                                         if (base->object != scene->obedit)
1585                                                 draw_object(scene, sl, ar, v3d, base, 0);
1586                                 }
1587                         }
1588                 }
1589
1590                 /* mask out localview */
1591                 v3d->lay_used = lay_used & ((1 << 20) - 1);
1592
1593                 /* draw selected and editmode */
1594                 for (base = sl->object_bases.first; base; base = base->next) {
1595                         if ((base->flag & BASE_VISIBLED) != 0) {
1596                                 if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) {
1597                                         draw_object(scene, sl, ar, v3d, base, 0);
1598                                 }
1599                         }
1600                 }
1601         }
1602
1603         /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
1604         if (draw_grids_after) {
1605                 VP_legacy_drawfloor(scene, v3d, grid_unit, false);
1606         }
1607
1608         /* must be before xray draw which clears the depth buffer */
1609         if (v3d->flag2 & V3D_SHOW_GPENCIL) {
1610                 wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL;
1611                 
1612                 /* must be before xray draw which clears the depth buffer */
1613                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1614                 ED_gpencil_draw_view3d(wm, scene, v3d, ar, true);
1615                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1616         }
1617
1618         /* transp and X-ray afterdraw stuff */
1619         if (v3d->afterdraw_transp.first)     view3d_draw_transp(scene, sl, ar, v3d);
1620
1621         /* always do that here to cleanup depth buffers if none needed */
1622         if (fx) {
1623                 do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
1624                 GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
1625         }
1626
1627         if (v3d->afterdraw_xray.first)       view3d_draw_xray(scene, sl, ar, v3d, &xrayclear);
1628         if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, sl, ar, v3d, xrayclear);
1629
1630         if (fx && do_composite_xray) {
1631                 GPU_fx_compositor_XRay_resolve(fx);
1632         }
1633
1634         if (!draw_offscreen) {
1635                 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
1636         }
1637
1638         if (rv3d->rflag & RV3D_CLIPPING)
1639                 ED_view3d_clipping_disable();
1640
1641         /* important to do after clipping */
1642         if (do_bgpic) {
1643                 view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
1644         }
1645
1646         if (!draw_offscreen) {
1647                 BIF_draw_manipulator(C);
1648         }
1649
1650         /* cleanup */
1651         if (v3d->zbuf) {
1652                 v3d->zbuf = false;
1653                 glDisable(GL_DEPTH_TEST);
1654         }
1655
1656         if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
1657                 GPU_free_images_old();
1658         }
1659 }
1660
1661 /**
1662  * Store values from #RegionView3D, set when drawing.
1663  * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example).
1664  *
1665  * Values set by #ED_view3d_update_viewmat should be handled here.
1666  */
1667 struct RV3DMatrixStore {
1668         float winmat[4][4];
1669         float viewmat[4][4];
1670         float viewinv[4][4];
1671         float persmat[4][4];
1672         float persinv[4][4];
1673         float viewcamtexcofac[4];
1674         float pixsize;
1675 };
1676
1677 void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
1678 {
1679         struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
1680         copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
1681         copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
1682         copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
1683         copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
1684         copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
1685         copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
1686         rv3dmat->pixsize = rv3d->pixsize;
1687         return (void *)rv3dmat;
1688 }
1689
1690 void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt)
1691 {
1692         struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
1693         copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
1694         copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
1695         copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
1696         copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
1697         copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
1698         copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
1699         rv3d->pixsize = rv3dmat->pixsize;
1700 }
1701
1702 void ED_view3d_draw_offscreen_init(Scene *scene, SceneLayer *sl, View3D *v3d)
1703 {
1704         /* shadow buffers, before we setup matrices */
1705         if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype))
1706                 gpu_update_lamps_shadows_world(scene, v3d);
1707 }
1708
1709 /*
1710  * Function to clear the view
1711  */
1712 static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
1713 {
1714         if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
1715                 VP_view3d_draw_background_world(scene, v3d, ar->regiondata);
1716         }
1717         else {
1718                 VP_view3d_draw_background_none();
1719         }
1720 }
1721
1722 /* ED_view3d_draw_offscreen_init should be called before this to initialize
1723  * stuff like shadow buffers
1724  */
1725 void ED_view3d_draw_offscreen(
1726         Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
1727         float viewmat[4][4], float winmat[4][4],
1728         bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
1729         GPUFX *fx, GPUFXSettings *fx_settings,
1730         GPUOffScreen *ofs)
1731 {
1732         bool do_compositing = false;
1733         RegionView3D *rv3d = ar->regiondata;
1734
1735         glPushMatrix();
1736
1737         /* set temporary new size */
1738         int bwinx = ar->winx;
1739         int bwiny = ar->winy;
1740         rcti brect = ar->winrct;
1741
1742         ar->winx = winx;
1743         ar->winy = winy;
1744         ar->winrct.xmin = 0;
1745         ar->winrct.ymin = 0;
1746         ar->winrct.xmax = winx;
1747         ar->winrct.ymax = winy;
1748
1749         struct bThemeState theme_state;
1750         UI_Theme_Store(&theme_state);
1751         UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
1752
1753         /* set flags */
1754         G.f |= G_RENDER_OGL;
1755
1756         if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
1757                 /* free images which can have changed on frame-change
1758                  * warning! can be slow so only free animated images - campbell */
1759                 GPU_free_images_anim();
1760         }
1761
1762         /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
1763         if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
1764                 view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
1765         else
1766                 VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
1767
1768         /* framebuffer fx needed, we need to draw offscreen first */
1769         if (v3d->fx_settings.fx_flag && fx) {
1770                 GPUSSAOSettings *ssao = NULL;
1771
1772                 if (v3d->drawtype < OB_SOLID) {
1773                         ssao = v3d->fx_settings.ssao;
1774                         v3d->fx_settings.ssao = NULL;
1775                 }
1776
1777                 do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
1778
1779                 if (ssao)
1780                         v3d->fx_settings.ssao = ssao;
1781         }
1782
1783         /* clear opengl buffers */
1784         if (do_sky) {
1785                 view3d_main_region_clear(scene, v3d, ar);
1786         }
1787         else {
1788                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1789                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1790         }
1791
1792         /* main drawing call */
1793         view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
1794
1795         /* post process */
1796         if (do_compositing) {
1797                 if (!winmat)
1798                         is_persp = rv3d->is_persp;
1799                 GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
1800         }
1801
1802         if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
1803                 /* draw grease-pencil stuff */
1804                 ED_region_pixelspace(ar);
1805
1806
1807                 if (v3d->flag2 & V3D_SHOW_GPENCIL) {
1808                         /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
1809                         ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
1810                 }
1811
1812                 /* freeing the images again here could be done after the operator runs, leaving for now */
1813                 GPU_free_images_anim();
1814         }
1815
1816         /* restore size */
1817         ar->winx = bwinx;
1818         ar->winy = bwiny;
1819         ar->winrct = brect;
1820
1821         glPopMatrix();
1822
1823         UI_Theme_Restore(&theme_state);
1824
1825         G.f &= ~G_RENDER_OGL;
1826 }
1827
1828 /**
1829  * Utility func for ED_view3d_draw_offscreen
1830  *
1831  * \param ofs: Optional off-screen buffer, can be NULL.
1832  * (avoids re-creating when doing multiple GL renders).
1833  */
1834 ImBuf *ED_view3d_draw_offscreen_imbuf(
1835         Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, int sizex, int sizey,
1836         unsigned int flag, bool draw_background,
1837         int alpha_mode, int samples, bool full_samples, const char *viewname,
1838         /* output vars */
1839         GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
1840 {
1841         RegionView3D *rv3d = ar->regiondata;
1842         const bool draw_sky = (alpha_mode == R_ADDSKY);
1843
1844         /* view state */
1845         GPUFXSettings fx_settings = v3d->fx_settings;
1846         bool is_ortho = false;
1847         float winmat[4][4];
1848
1849         if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
1850                 /* sizes differ, can't reuse */
1851                 ofs = NULL;
1852         }
1853
1854         const bool own_ofs = (ofs == NULL);
1855
1856         if (own_ofs) {
1857                 /* bind */
1858                 ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
1859                 if (ofs == NULL) {
1860                         return NULL;
1861                 }
1862         }
1863
1864         ED_view3d_draw_offscreen_init(scene, sl, v3d);
1865
1866         GPU_offscreen_bind(ofs, true);
1867
1868         /* read in pixels & stamp */
1869         ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
1870
1871         /* render 3d view */
1872         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
1873                 CameraParams params;
1874                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
1875
1876                 BKE_camera_params_init(&params);
1877                 /* fallback for non camera objects */
1878                 params.clipsta = v3d->near;
1879                 params.clipend = v3d->far;
1880                 BKE_camera_params_from_object(&params, camera);
1881                 BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
1882                 BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
1883                 BKE_camera_params_compute_matrix(&params);
1884
1885                 BKE_camera_to_gpu_dof(camera, &fx_settings);
1886
1887                 is_ortho = params.is_ortho;
1888                 copy_m4_m4(winmat, params.winmat);
1889         }
1890         else {
1891                 rctf viewplane;
1892                 float clipsta, clipend;
1893
1894                 is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
1895                 if (is_ortho) {
1896                         orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
1897                 }
1898                 else {
1899                         perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
1900                 }
1901         }
1902
1903         if ((samples && full_samples) == 0) {
1904                 /* Single-pass render, common case */
1905                 ED_view3d_draw_offscreen(
1906                         scene, v3d, ar, sizex, sizey, NULL, winmat,
1907                         draw_background, draw_sky, !is_ortho, viewname,
1908                         fx, &fx_settings, ofs);
1909
1910                 if (ibuf->rect_float) {
1911                         GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
1912                 }
1913                 else if (ibuf->rect) {
1914                         GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
1915                 }
1916         }
1917         else {
1918                 /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
1919                  * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
1920                 static float jit_ofs[32][2];
1921                 float winmat_jitter[4][4];
1922                 /* use imbuf as temp storage, before writing into it from accumulation buffer */
1923                 unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
1924                 unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
1925
1926                 BLI_jitter_init(jit_ofs, samples);
1927
1928                 /* first sample buffer, also initializes 'rv3d->persmat' */
1929                 ED_view3d_draw_offscreen(
1930                         scene, v3d, ar, sizex, sizey, NULL, winmat,
1931                         draw_background, draw_sky, !is_ortho, viewname,
1932                         fx, &fx_settings, ofs);
1933                 GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
1934
1935                 unsigned i = sizex * sizey * 4;
1936                 while (i--) {
1937                         accum_buffer[i] = rect_temp[i];
1938                 }
1939
1940                 /* skip the first sample */
1941                 for (int j = 1; j < samples; j++) {
1942                         copy_m4_m4(winmat_jitter, winmat);
1943                         window_translate_m4(
1944                                 winmat_jitter, rv3d->persmat,
1945                                 (jit_ofs[j][0] * 2.0f) / sizex,
1946                                 (jit_ofs[j][1] * 2.0f) / sizey);
1947
1948                         ED_view3d_draw_offscreen(
1949                                 scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
1950                                 draw_background, draw_sky, !is_ortho, viewname,
1951                                 fx, &fx_settings, ofs);
1952                         GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
1953
1954                         i = sizex * sizey * 4;
1955                         while (i--) {
1956                                 accum_buffer[i] += rect_temp[i];
1957                         }
1958                 }
1959
1960                 if (ibuf->rect_float) {
1961                         float *rect_float = ibuf->rect_float;
1962                         i = sizex * sizey * 4;
1963                         while (i--) {
1964                                 rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
1965                         }
1966                 }
1967                 else {
1968                         unsigned char *rect_ub = (unsigned char *)ibuf->rect;
1969                         i = sizex * sizey * 4;
1970                         while (i--) {
1971                                 rect_ub[i] = accum_buffer[i] / samples;
1972                         }
1973                 }
1974
1975                 MEM_freeN(accum_buffer);
1976         }
1977
1978         /* unbind */
1979         GPU_offscreen_unbind(ofs, true);
1980
1981         if (own_ofs) {
1982                 GPU_offscreen_free(ofs);
1983         }
1984
1985         if (ibuf->rect_float && ibuf->rect)
1986                 IMB_rect_from_float(ibuf);
1987
1988         return ibuf;
1989 }
1990
1991 /**
1992  * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
1993  *
1994  * \param ofs: Optional off-screen buffer can be NULL.
1995  * (avoids re-creating when doing multiple GL renders).
1996  *
1997  * \note used by the sequencer
1998  */
1999 ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
2000         Scene *scene, SceneLayer *sl, Object *camera, int width, int height,
2001         unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
2002         int alpha_mode, int samples, bool full_samples, const char *viewname,
2003         GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
2004 {
2005         View3D v3d = {NULL};
2006         ARegion ar = {NULL};
2007         RegionView3D rv3d = {{{0}}};
2008
2009         /* connect data */
2010         v3d.regionbase.first = v3d.regionbase.last = &ar;
2011         ar.regiondata = &rv3d;
2012         ar.regiontype = RGN_TYPE_WINDOW;
2013
2014         v3d.camera = camera;
2015         v3d.lay = scene->lay;
2016         v3d.drawtype = drawtype;
2017         v3d.flag2 = V3D_RENDER_OVERRIDE;
2018         
2019         if (use_gpencil)
2020                 v3d.flag2 |= V3D_SHOW_GPENCIL;
2021
2022         if (use_solid_tex)
2023                 v3d.flag2 |= V3D_SOLID_TEX;
2024                 
2025         if (draw_background)
2026                 v3d.flag3 |= V3D_SHOW_WORLD;
2027
2028         rv3d.persp = RV3D_CAMOB;
2029
2030         copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
2031         normalize_m4(rv3d.viewinv);
2032         invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
2033
2034         {
2035                 CameraParams params;
2036                 Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
2037
2038                 BKE_camera_params_init(&params);
2039                 BKE_camera_params_from_object(&params, view_camera);
2040                 BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
2041                 BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
2042                 BKE_camera_params_compute_matrix(&params);
2043
2044                 copy_m4_m4(rv3d.winmat, params.winmat);
2045                 v3d.near = params.clipsta;
2046                 v3d.far = params.clipend;
2047                 v3d.lens = params.lens;
2048         }
2049
2050         mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
2051         invert_m4_m4(rv3d.persinv, rv3d.viewinv);
2052
2053         return ED_view3d_draw_offscreen_imbuf(
2054                 scene, sl, &v3d, &ar, width, height, flag,
2055                 draw_background, alpha_mode, samples, full_samples, viewname,
2056                 fx, ofs, err_out);
2057 }
2058
2059
2060 /**
2061  * \note The info that this uses is updated in #ED_refresh_viewport_fps,
2062  * which currently gets called during #SCREEN_OT_animation_step.
2063  */
2064 void ED_scene_draw_fps(Scene *scene, const rcti *rect)
2065 {
2066         ScreenFrameRateInfo *fpsi = scene->fps_info;
2067         char printable[16];
2068         
2069         if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
2070                 return;
2071         
2072         printable[0] = '\0';
2073         
2074 #if 0
2075         /* this is too simple, better do an average */
2076         fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
2077 #else
2078         fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
2079         
2080         float fps = 0.0f;
2081         int tot = 0;
2082         for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
2083                 if (fpsi->redrawtimes_fps[i]) {
2084                         fps += fpsi->redrawtimes_fps[i];
2085                         tot++;
2086                 }
2087         }
2088         if (tot) {
2089                 fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
2090                 
2091                 //fpsi->redrawtime_index++;
2092                 //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
2093                 //      fpsi->redrawtime = 0;
2094                 
2095                 fps = fps / tot;
2096         }
2097 #endif
2098
2099         const int font_id = BLF_default();
2100
2101         /* is this more than half a frame behind? */
2102         if (fps + 0.5f < (float)(FPS)) {
2103                 UI_FontThemeColor(font_id, TH_REDALERT);
2104                 BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
2105         }
2106         else {
2107                 UI_FontThemeColor(font_id, TH_TEXT_HI);
2108                 BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
2109         }
2110
2111 #ifdef WITH_INTERNATIONAL
2112         BLF_draw_default(rect->xmin + U.widget_unit,  rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
2113 #else
2114         BLF_draw_default_ascii(rect->xmin + U.widget_unit,  rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
2115 #endif
2116 }
2117
2118 static bool view3d_main_region_do_render_draw(Scene *scene)
2119 {
2120         RenderEngineType *type = RE_engines_find(scene->r.engine);
2121
2122         return (type && type->view_update && type->view_draw);
2123 }
2124
2125 bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
2126 {
2127         RegionView3D *rv3d = ar->regiondata;
2128         bool use_border;
2129
2130         /* test if there is a 3d view rendering */
2131         if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
2132                 return false;
2133
2134         /* test if there is a border render */
2135         if (rv3d->persp == RV3D_CAMOB)
2136                 use_border = (scene->r.mode & R_BORDER) != 0;
2137         else
2138                 use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
2139         
2140         if (!use_border)
2141                 return false;
2142
2143         /* compute border */
2144         if (rv3d->persp == RV3D_CAMOB) {
2145                 rctf viewborder;
2146                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
2147
2148                 rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
2149                 rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
2150                 rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
2151                 rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
2152         }
2153         else {
2154                 rect->xmin = v3d->render_border.xmin * ar->winx;
2155                 rect->xmax = v3d->render_border.xmax * ar->winx;
2156                 rect->ymin = v3d->render_border.ymin * ar->winy;
2157                 rect->ymax = v3d->render_border.ymax * ar->winy;
2158         }
2159
2160         BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
2161         BLI_rcti_isect(&ar->winrct, rect, rect);
2162
2163         return true;
2164 }
2165
2166 /**
2167   * IMPORTANT: this is deprecated, any changes made in this function should
2168   * be mirrored in view3d_draw_render_draw() in view3d_draw.c
2169   */
2170 static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
2171                                          ARegion *ar, View3D *v3d,
2172                                          bool clip_border, const rcti *border_rect)
2173 {
2174         RegionView3D *rv3d = ar->regiondata;
2175         RenderEngineType *type;
2176         GLint scissor[4];
2177
2178         /* create render engine */
2179         if (!rv3d->render_engine) {
2180                 RenderEngine *engine;
2181
2182                 type = RE_engines_find(scene->r.engine);
2183
2184                 if (!(type->view_update && type->view_draw))
2185                         return false;
2186
2187                 engine = RE_engine_create_ex(type, true);
2188
2189                 engine->tile_x = scene->r.tilex;
2190                 engine->tile_y = scene->r.tiley;
2191
2192                 type->view_update(engine, C);
2193
2194                 rv3d->render_engine = engine;
2195         }
2196
2197         /* setup view matrices */
2198         VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
2199
2200         /* background draw */
2201         ED_region_pixelspace(ar);
2202
2203         if (clip_border) {
2204                 /* for border draw, we only need to clear a subset of the 3d view */
2205                 if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
2206                         glGetIntegerv(GL_SCISSOR_BOX, scissor);
2207                         glScissor(border_rect->xmin, border_rect->ymin,
2208                                   BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
2209                 }
2210                 else {
2211                         return false;
2212                 }
2213         }
2214
2215         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2216         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2217
2218         if (v3d->flag & V3D_DISPBGPICS)
2219                 view3d_draw_bgpic_test(scene, ar, v3d, false, true);
2220         else
2221                 imm_draw_checker_box(0, 0, ar->winx, ar->winy);
2222
2223         /* render result draw */
2224         type = rv3d->render_engine->type;
2225         type->view_draw(rv3d->render_engine, C);
2226
2227         if (v3d->flag & V3D_DISPBGPICS)
2228                 view3d_draw_bgpic_test(scene, ar, v3d, true, true);
2229
2230         if (clip_border) {
2231                 /* restore scissor as it was before */
2232                 glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
2233         }
2234
2235         return true;
2236 }
2237
2238 static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
2239 {
2240         float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
2241
2242         if (!rv3d->render_engine || !rv3d->render_engine->text[0])
2243                 return;
2244         
2245         if (render_border) {
2246                 /* draw darkened background color. no alpha because border render does
2247                  * partial redraw and will not redraw the region behind this info bar */
2248                 float alpha = 1.0f - fill_color[3];
2249                 Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
2250
2251                 if (camera) {
2252                         if (camera->flag & CAM_SHOWPASSEPARTOUT) {
2253                                 alpha *= (1.0f - camera->passepartalpha);
2254                         }
2255                 }
2256
2257                 UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
2258                 mul_v3_fl(fill_color, alpha);
2259                 fill_color[3] = 1.0f;
2260         }
2261
2262         ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
2263 }
2264
2265 static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
2266                                             float winmat[4][4], const char *viewname)
2267 {
2268         /* update the viewport matrices with the new camera */
2269         if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
2270                 float viewmat[4][4];
2271                 const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
2272
2273                 BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
2274                 VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2275         }
2276         else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
2277                 float viewmat[4][4];
2278                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
2279
2280                 BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
2281                 VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
2282         }
2283 }
2284
2285 #ifdef WITH_GAMEENGINE
2286 static void update_lods(Scene *scene, float camera_pos[3])
2287 {
2288         Scene *sce_iter;
2289         Base *base;
2290
2291         for (SETLOOPER(scene, sce_iter, base)) {
2292                 Object *ob = base->object;
2293                 BKE_object_lod_update(ob, camera_pos);
2294         }
2295 }
2296 #endif
2297
2298 static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d,
2299                                           ARegion *ar, const char **grid_unit)
2300 {
2301         wmWindow *win = CTX_wm_window(C);
2302         RegionView3D *rv3d = ar->regiondata;
2303         unsigned int lay_used = v3d->lay_used;
2304         
2305         /* post processing */
2306         bool do_compositing = false;
2307         
2308         /* shadow buffers, before we setup matrices */
2309         if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype))
2310                 gpu_update_lamps_shadows_world(scene, v3d);
2311
2312         /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
2313         if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
2314                 rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
2315                 GPU_default_lights();
2316         }
2317
2318         /* setup the view matrix */
2319         if (VP_legacy_view3d_stereo3d_active(C, scene, v3d, rv3d))
2320                 VP_legacy_view3d_stereo3d_setup(scene, v3d, ar);
2321         else
2322                 VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
2323
2324         rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
2325 #ifdef WITH_GAMEENGINE
2326         if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
2327                 rv3d->rflag |= RV3D_IS_GAME_ENGINE;
2328
2329                 /* Make sure LoDs are up to date */
2330                 update_lods(scene, rv3d->viewinv[3]);
2331         }
2332 #endif
2333
2334         /* framebuffer fx needed, we need to draw offscreen first */
2335         if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
2336                 BKE_screen_gpu_fx_validate(&v3d->fx_settings);
2337                 GPUFXSettings fx_settings = v3d->fx_settings;
2338                 if (!rv3d->compositor)
2339                         rv3d->compositor = GPU_fx_compositor_create();
2340                 
2341                 if (rv3d->persp == RV3D_CAMOB && v3d->camera)
2342                         BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
2343                 else {
2344                         fx_settings.dof = NULL;
2345                 }
2346
2347                 do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
2348         }
2349         
2350         /* clear the background */
2351         view3d_main_region_clear(scene, v3d, ar);
2352
2353         /* enables anti-aliasing for 3D view drawing */
2354         if (win->multisamples != USER_MULTISAMPLE_NONE) {
2355                 glEnable(GL_MULTISAMPLE);
2356         }
2357
2358         /* main drawing call */
2359         view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
2360
2361         /* post process */
2362         if (do_compositing) {
2363                 GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
2364         }
2365
2366         /* Disable back anti-aliasing */
2367         if (win->multisamples != USER_MULTISAMPLE_NONE) {
2368                 glDisable(GL_MULTISAMPLE);
2369         }
2370
2371         if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
2372                 /* find header and force tag redraw */
2373                 ScrArea *sa = CTX_wm_area(C);
2374                 ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
2375                 ED_region_tag_redraw(ar_header); /* can be NULL */
2376         }
2377
2378         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2379                 BDR_drawSketch(C);
2380         }
2381 }
2382
2383 static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
2384                                        ARegion *ar, View3D *v3d,
2385                                        const char *grid_unit, bool render_border)
2386 {
2387         SceneLayer *sl = CTX_data_scene_layer(C);
2388         wmWindowManager *wm = CTX_wm_manager(C);
2389         RegionView3D *rv3d = ar->regiondata;
2390         rcti rect;
2391         
2392         /* local coordinate visible rect inside region, to accomodate overlapping ui */
2393         ED_region_visible_rect(ar, &rect);
2394
2395         if (rv3d->persp == RV3D_CAMOB) {
2396                 VP_drawviewborder(scene, ar, v3d);
2397         }
2398         else if (v3d->flag2 & V3D_RENDER_BORDER) {
2399                 VP_drawrenderborder(ar, v3d);
2400         }
2401
2402         if (v3d->flag2 & V3D_SHOW_GPENCIL) {
2403                 /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
2404                 ED_gpencil_draw_view3d(wm, scene, v3d, ar, false);
2405         }
2406
2407         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2408                 VP_legacy_drawcursor(scene, sl, ar, v3d); /* 3D cursor */
2409
2410                 if (U.uiflag & USER_SHOW_ROTVIEWICON)
2411                         VP_legacy_draw_view_axis(rv3d, &rect);
2412                 else
2413                         draw_view_icon(rv3d, &rect);
2414
2415                 if (U.uiflag & USER_DRAWVIEWINFO) {
2416                         Object *ob = OBACT_NEW;
2417                         VP_legacy_draw_selected_name(scene, ob, &rect);
2418                 }
2419         }
2420
2421         if (rv3d->render_engine) {
2422                 view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
2423                 return;
2424         }
2425
2426         if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
2427                 if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
2428                         ED_scene_draw_fps(scene, &rect);
2429                 }
2430                 else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
2431                         VP_legacy_draw_viewport_name(ar, v3d, &rect);
2432                 }
2433
2434                 if (grid_unit) { /* draw below the viewport name */
2435                         char numstr[32] = "";
2436
2437                         UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
2438                         if (v3d->grid != 1.0f) {
2439                                 BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
2440                         }
2441
2442                         BLF_draw_default_ascii(rect.xmin + U.widget_unit,
2443                                                rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
2444                                                numstr[0] ? numstr : grid_unit, sizeof(numstr));
2445                 }
2446         }
2447 }
2448
2449 void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
2450 {
2451         Scene *scene = CTX_data_scene(C);
2452         SceneLayer *sl = CTX_data_scene_layer(C);
2453         View3D *v3d = CTX_wm_view3d(C);
2454         const char *grid_unit = NULL;
2455         rcti border_rect;
2456
2457         /* if we only redraw render border area, skip opengl draw and also
2458          * don't do scissor because it's already set */
2459         bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
2460         bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
2461
2462         /* draw viewport using opengl */
2463         if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
2464                 view3d_main_region_draw_objects(C, scene, sl, v3d, ar, &grid_unit);
2465
2466                 if (G.debug & G_DEBUG_SIMDATA)
2467                         draw_sim_debug_data(scene, v3d, ar);
2468                 
2469                 ED_region_pixelspace(ar);
2470         }
2471
2472         /* draw viewport using external renderer */
2473         if (v3d->drawtype == OB_RENDER)
2474                 view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
2475         
2476         view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
2477
2478         v3d->flag |= V3D_INVALID_BACKBUF;
2479
2480         BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
2481         BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
2482         BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
2483 }