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