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