start using COMP_* instead of GL_* in viewport
[blender.git] / source / blender / editors / space_view3d / view3d_draw.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 <math.h>
32
33 #include "BIF_gl.h"
34 #include "BIF_glutil.h"
35
36 #include "BKE_camera.h"
37 #include "BKE_context.h"
38 #include "BKE_scene.h"
39 #include "BKE_unit.h"
40
41 #include "BLF_api.h"
42
43 #include "BLI_math.h"
44 #include "BLI_rect.h"
45 #include "BLI_threads.h"
46
47 #include "DNA_camera_types.h"
48 #include "DNA_mesh_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_view3d_types.h"
51 #include "DNA_windowmanager_types.h"
52
53 #include "ED_screen.h"
54 #include "ED_transform.h"
55
56 #include "GPU_matrix.h"
57 #include "GPU_immediate.h"
58 #include "GPU_material.h"
59 #include "GPU_viewport.h"
60
61 #include "MEM_guardedalloc.h"
62
63 #include "UI_interface.h"
64 #include "UI_resources.h"
65
66 #include "RE_engine.h"
67
68 #include "WM_api.h"
69
70 #include "view3d_intern.h"  /* own include */
71
72 /* prototypes */
73 static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth);
74
75 typedef struct DrawData {
76         rcti border_rect;
77         bool render_border;
78         bool clip_border;
79         bool is_render;
80         GPUViewport *viewport;
81 } DrawData;
82
83 static void view3d_draw_data_init(const bContext *C, ARegion *ar, RegionView3D *rv3d, DrawData *draw_data)
84 {
85         Scene *scene = CTX_data_scene(C);
86         View3D *v3d = CTX_wm_view3d(C);
87
88         draw_data->is_render = (v3d->drawtype == OB_RENDER);
89
90         draw_data->render_border = ED_view3d_calc_render_border(scene, v3d, ar, &draw_data->border_rect);
91         draw_data->clip_border = (draw_data->render_border && !BLI_rcti_compare(&ar->drawrct, &draw_data->border_rect));
92
93         draw_data->viewport = rv3d->viewport;
94 }
95
96 /* ******************** general functions ***************** */
97
98 static bool use_depth_doit(Scene *scene, View3D *v3d)
99 {
100         if (v3d->drawtype > OB_WIRE)
101                 return true;
102
103         /* special case (depth for wire color) */
104         if (v3d->drawtype <= OB_WIRE) {
105                 if (scene->obedit && scene->obedit->type == OB_MESH) {
106                         Mesh *me = scene->obedit->data;
107                         if (me->drawflag & ME_DRAWEIGHT) {
108                                 return true;
109                         }
110                 }
111         }
112         return false;
113 }
114
115 static bool use_depth(const bContext *C)
116 {
117         View3D *v3d = CTX_wm_view3d(C);
118         Scene *scene = CTX_data_scene(C);
119         return use_depth_doit(scene, v3d);
120 }
121
122 /**
123  * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
124  */
125 void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
126 {
127         RegionView3D *rv3d = ar->regiondata;
128         rctf cameraborder;
129
130         /* setup window matrices */
131         if (winmat)
132                 copy_m4_m4(rv3d->winmat, winmat);
133         else
134                 view3d_winmatrix_set(ar, v3d, NULL);
135
136         /* setup view matrix */
137         if (viewmat)
138                 copy_m4_m4(rv3d->viewmat, viewmat);
139         else
140                 view3d_viewmatrix_set(scene, v3d, rv3d);  /* note: calls BKE_object_where_is_calc for camera... */
141
142         /* update utilitity matrices */
143         mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
144         invert_m4_m4(rv3d->persinv, rv3d->persmat);
145         invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
146
147         /* calculate GLSL view dependent values */
148
149         /* store window coordinates scaling/offset */
150         if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
151                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
152                 rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
153                 rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
154
155                 rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
156                 rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
157         }
158         else {
159                 rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
160                 rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
161         }
162
163         /* calculate pixelsize factor once, is used for lamps and obcenters */
164         {
165                 /* note:  '1.0f / len_v3(v1)'  replaced  'len_v3(rv3d->viewmat[0])'
166                 * because of float point precision problems at large values [#23908] */
167                 float v1[3], v2[3];
168                 float len_px, len_sc;
169
170                 v1[0] = rv3d->persmat[0][0];
171                 v1[1] = rv3d->persmat[1][0];
172                 v1[2] = rv3d->persmat[2][0];
173
174                 v2[0] = rv3d->persmat[0][1];
175                 v2[1] = rv3d->persmat[1][1];
176                 v2[2] = rv3d->persmat[2][1];
177
178                 len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
179                 len_sc = (float)MAX2(ar->winx, ar->winy);
180
181                 rv3d->pixsize = len_px / len_sc;
182         }
183 }
184
185 static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
186 {
187         RegionView3D *rv3d = ar->regiondata;
188
189         ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
190
191         /* set for opengl */
192         glMatrixMode(GL_PROJECTION);
193         glLoadMatrixf(rv3d->winmat);
194         glMatrixMode(GL_MODELVIEW);
195         glLoadMatrixf(rv3d->viewmat);
196 }
197
198 static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
199 {
200         wmWindow *win = CTX_wm_window(C);
201
202         if ((scene->r.scemode & R_MULTIVIEW) == 0)
203                 return false;
204
205         if (WM_stereo3d_enabled(win, true) == false)
206                 return false;
207
208         if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB)
209                 return false;
210
211         if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) {
212                 if (v3d->stereo3d_camera == STEREO_MONO_ID)
213                         return false;
214
215                 return BKE_scene_multiview_is_stereo3d(&scene->r);
216         }
217
218         return true;
219 }
220
221 /* setup the view and win matrices for the multiview cameras
222  *
223  * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
224  * we have no winmatrix (i.e., projection matrix) defined at that time.
225  * Since the camera and the camera shift are needed for the winmat calculation
226  * we do a small hack to replace it temporarily so we don't need to change the
227  * view3d)main_region_setup_view() code to account for that.
228  */
229 static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
230 {
231         bool is_left;
232         const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
233         const char *viewname;
234
235         /* show only left or right camera */
236         if (v3d->stereo3d_camera != STEREO_3D_ID)
237                 v3d->multiview_eye = v3d->stereo3d_camera;
238
239         is_left = v3d->multiview_eye == STEREO_LEFT_ID;
240         viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
241
242         /* update the viewport matrices with the new camera */
243         if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
244                 Camera *data;
245                 float viewmat[4][4];
246                 float shiftx;
247
248                 data = (Camera *)v3d->camera->data;
249                 shiftx = data->shiftx;
250
251                 BLI_lock_thread(LOCK_VIEW3D);
252                 data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
253
254                 BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
255                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
256
257                 data->shiftx = shiftx;
258                 BLI_unlock_thread(LOCK_VIEW3D);
259         }
260         else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
261                 float viewmat[4][4];
262                 Object *view_ob = v3d->camera;
263                 Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
264
265                 BLI_lock_thread(LOCK_VIEW3D);
266                 v3d->camera = camera;
267
268                 BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
269                 view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
270
271                 v3d->camera = view_ob;
272                 BLI_unlock_thread(LOCK_VIEW3D);
273         }
274 }
275
276 /* ******************** debug ***************** */
277
278 #define VIEW3D_DRAW_DEBUG 1
279 /* TODO: expand scope of this flag so UI reflects the underlying code */
280
281 #if VIEW3D_DRAW_DEBUG
282
283 static void view3d_draw_debug_store_depth(ARegion *ar, DrawData *draw_data)
284 {
285         GPUViewport *viewport = draw_data->viewport;
286         GLint viewport_size[4];
287         glGetIntegerv(GL_VIEWPORT, viewport_size);
288
289         const int x = viewport_size[0];
290         const int y = viewport_size[1];
291         const int w = viewport_size[2];
292         const int h = viewport_size[3];
293
294         if (GPU_viewport_debug_depth_is_valid(viewport)) {
295                 if ((GPU_viewport_debug_depth_width(viewport) != w) ||
296                         (GPU_viewport_debug_depth_height(viewport) != h))
297                 {
298                         GPU_viewport_debug_depth_free(viewport);
299                 }
300         }
301
302         if (!GPU_viewport_debug_depth_is_valid(viewport)) {
303                 char error[256];
304                 if (!GPU_viewport_debug_depth_create(viewport, w, h, 0, error)) {
305                         fprintf(stderr, "Failed to create depth buffer for debug: %s\n", error);
306                         return;
307                 }
308         }
309
310         GPU_viewport_debug_depth_store(viewport, x, y);
311 }
312
313 static void view3d_draw_debug_post_solid(const bContext *C, ARegion *ar, DrawData *draw_data)
314 {
315         View3D *v3d = CTX_wm_view3d(C);
316
317         if ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_SCENE_DEPTH) != 0) {
318                 view3d_draw_debug_store_depth(ar, draw_data);
319         }
320 }
321
322 static void view3d_draw_debug(const bContext *C, ARegion *ar, DrawData *draw_data)
323 {
324         View3D *v3d = CTX_wm_view3d(C);
325
326         if ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0) {
327                 /* store */
328                 view3d_draw_debug_store_depth(ar, draw_data);
329         }
330
331         if (((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_SCENE_DEPTH) != 0) ||
332                 ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0))
333         {
334                 /* draw */
335                 if (GPU_viewport_debug_depth_is_valid(draw_data->viewport)) {
336                         GPU_viewport_debug_depth_draw(draw_data->viewport, v3d->debug.znear, v3d->debug.zfar);
337                 }
338         }
339         else {
340                 /* cleanup */
341                 GPU_viewport_debug_depth_free(draw_data->viewport);
342         }
343 }
344
345 #endif /* VIEW3D_DRAW_DEBUG */
346
347 /* ******************** view border ***************** */
348
349 static void view3d_camera_border(
350         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
351         rctf *r_viewborder, const bool no_shift, const bool no_zoom)
352 {
353         CameraParams params;
354         rctf rect_view, rect_camera;
355
356         /* get viewport viewplane */
357         BKE_camera_params_init(&params);
358         BKE_camera_params_from_view3d(&params, v3d, rv3d);
359         if (no_zoom)
360                 params.zoom = 1.0f;
361         BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
362         rect_view = params.viewplane;
363
364         /* get camera viewplane */
365         BKE_camera_params_init(&params);
366         /* fallback for non camera objects */
367         params.clipsta = v3d->near;
368         params.clipend = v3d->far;
369         BKE_camera_params_from_object(&params, v3d->camera);
370         if (no_shift) {
371                 params.shiftx = 0.0f;
372                 params.shifty = 0.0f;
373         }
374         BKE_camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
375         rect_camera = params.viewplane;
376
377         /* get camera border within viewport */
378         r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
379         r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
380         r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
381         r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
382 }
383
384 void ED_view3d_calc_camera_border_size(
385         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
386         float r_size[2])
387 {
388         rctf viewborder;
389
390         view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true);
391         r_size[0] = BLI_rctf_size_x(&viewborder);
392         r_size[1] = BLI_rctf_size_y(&viewborder);
393 }
394
395 void ED_view3d_calc_camera_border(
396         const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
397         rctf *r_viewborder, const bool no_shift)
398 {
399         view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
400 }
401
402 static void drawviewborder_grid3(unsigned pos, float x1, float x2, float y1, float y2, float fac)
403 {
404         float x3, y3, x4, y4;
405
406         x3 = x1 + fac * (x2 - x1);
407         y3 = y1 + fac * (y2 - y1);
408         x4 = x1 + (1.0f - fac) * (x2 - x1);
409         y4 = y1 + (1.0f - fac) * (y2 - y1);
410
411         immBegin(GL_LINES, 8);
412         immVertex2f(pos, x1, y3);
413         immVertex2f(pos, x2, y3);
414
415         immVertex2f(pos, x1, y4);
416         immVertex2f(pos, x2, y4);
417
418         immVertex2f(pos, x3, y1);
419         immVertex2f(pos, x3, y2);
420
421         immVertex2f(pos, x4, y1);
422         immVertex2f(pos, x4, y2);
423         immEnd();
424 }
425
426 /* harmonious triangle */
427 static void drawviewborder_triangle(unsigned pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
428 {
429         float ofs;
430         float w = x2 - x1;
431         float h = y2 - y1;
432
433         immBegin(GL_LINES, 6);
434         if (w > h) {
435                 if (golden) {
436                         ofs = w * (1.0f - (1.0f / 1.61803399f));
437                 }
438                 else {
439                         ofs = h * (h / w);
440                 }
441                 if (dir == 'B') SWAP(float, y1, y2);
442
443                 immVertex2f(pos, x1, y1);
444                 immVertex2f(pos, x2, y2);
445
446                 immVertex2f(pos, x2, y1);
447                 immVertex2f(pos, x1 + (w - ofs), y2);
448
449                 immVertex2f(pos, x1, y2);
450                 immVertex2f(pos, x1 + ofs, y1);
451         }
452         else {
453                 if (golden) {
454                         ofs = h * (1.0f - (1.0f / 1.61803399f));
455                 }
456                 else {
457                         ofs = w * (w / h);
458                 }
459                 if (dir == 'B') SWAP(float, x1, x2);
460
461                 immVertex2f(pos, x1, y1);
462                 immVertex2f(pos, x2, y2);
463
464                 immVertex2f(pos, x2, y1);
465                 immVertex2f(pos, x1, y1 + ofs);
466
467                 immVertex2f(pos, x1, y2);
468                 immVertex2f(pos, x2, y1 + (h - ofs));
469         }
470         immEnd();
471 }
472
473 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
474 {
475         float x1, x2, y1, y2;
476         float x1i, x2i, y1i, y2i;
477
478         rctf viewborder;
479         Camera *ca = NULL;
480         RegionView3D *rv3d = ar->regiondata;
481
482         if (v3d->camera == NULL)
483                 return;
484         if (v3d->camera->type == OB_CAMERA)
485                 ca = v3d->camera->data;
486
487         ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
488         /* the offsets */
489         x1 = viewborder.xmin;
490         y1 = viewborder.ymin;
491         x2 = viewborder.xmax;
492         y2 = viewborder.ymax;
493
494         glLineWidth(1.0f);
495
496         /* apply offsets so the real 3D camera shows through */
497
498         /* note: quite un-scientific but without this bit extra
499          * 0.0001 on the lower left the 2D border sometimes
500          * obscures the 3D camera border */
501         /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable
502          * but keep it here in case we need to remove the workaround */
503         x1i = (int)(x1 - 1.0001f);
504         y1i = (int)(y1 - 1.0001f);
505         x2i = (int)(x2 + (1.0f - 0.0001f));
506         y2i = (int)(y2 + (1.0f - 0.0001f));
507
508         /* use the same program for everything */
509         unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
510         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
511
512         /* passepartout, specified in camera edit buttons */
513         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
514                 const float winx = (ar->winx + 1);
515                 const float winy = (ar->winy + 1);
516
517                 float alpha = 1.0f;
518
519                 if (ca->passepartalpha != 1.0f) {
520                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
521                         glEnable(GL_BLEND);
522                         alpha = ca->passepartalpha;
523                 }
524
525                 immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
526
527                 if (x1i > 0.0f)
528                         immRectf(pos, 0.0f, winy, x1i, 0.0f);
529                 if (x2i < winx)
530                         immRectf(pos, x2i, winy, winx, 0.0f);
531                 if (y2i < winy)
532                         immRectf(pos, x1i, winy, x2i, y2i);
533                 if (y2i > 0.0f)
534                         immRectf(pos, x1i, y1i, x2i, 0.0f);
535
536                 glDisable(GL_BLEND);
537         }
538
539         setlinestyle(0);
540
541         immUniformThemeColor(TH_BACK);
542         imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
543
544 #ifdef VIEW3D_CAMERA_BORDER_HACK
545         if (view3d_camera_border_hack_test == true) {
546                 immUniformColor3ubv(view3d_camera_border_hack_col);
547                 imm_draw_line_box(pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
548                 view3d_camera_border_hack_test = false;
549         }
550 #endif
551
552         setlinestyle(3);
553
554         /* outer line not to confuse with object selecton */
555         if (v3d->flag2 & V3D_LOCK_CAMERA) {
556                 immUniformThemeColor(TH_REDALERT);
557                 imm_draw_line_box(pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
558         }
559
560         immUniformThemeColor(TH_VIEW_OVERLAY);
561         imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
562
563         /* border */
564         if (scene->r.mode & R_BORDER) {
565                 float x3, y3, x4, y4;
566
567                 x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
568                 y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
569                 x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
570                 y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
571
572                 imm_cpack(0x4040FF);
573                 imm_draw_line_box(pos, x3, y3, x4, y4);
574         }
575
576         /* safety border */
577         if (ca) {
578                 if (ca->dtx & CAM_DTX_CENTER) {
579                         float x3, y3;
580
581                         x3 = x1 + 0.5f * (x2 - x1);
582                         y3 = y1 + 0.5f * (y2 - y1);
583
584                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
585                         immBegin(GL_LINES, 4);
586
587                         immVertex2f(pos, x1, y3);
588                         immVertex2f(pos, x2, y3);
589
590                         immVertex2f(pos, x3, y1);
591                         immVertex2f(pos, x3, y2);
592
593                         immEnd();
594                 }
595
596                 if (ca->dtx & CAM_DTX_CENTER_DIAG) {
597
598                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
599                         immBegin(GL_LINES, 4);
600
601                         immVertex2f(pos, x1, y1);
602                         immVertex2f(pos, x2, y2);
603
604                         immVertex2f(pos, x1, y2);
605                         immVertex2f(pos, x2, y1);
606
607                         immEnd();
608                 }
609
610                 if (ca->dtx & CAM_DTX_THIRDS) {
611                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
612                         drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f / 3.0f);
613                 }
614
615                 if (ca->dtx & CAM_DTX_GOLDEN) {
616                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
617                         drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
618                 }
619
620                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
621                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
622                         drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'A');
623                 }
624
625                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
626                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
627                         drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'B');
628                 }
629
630                 if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
631                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
632                         drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'A');
633                 }
634
635                 if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
636                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
637                         drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'B');
638                 }
639
640                 if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
641                         UI_draw_safe_areas(
642                                 pos, x1, x2, y1, y2,
643                                 scene->safe_areas.title,
644                                 scene->safe_areas.action);
645
646                         if (ca->flag & CAM_SHOW_SAFE_CENTER) {
647                                 UI_draw_safe_areas(
648                                         pos, x1, x2, y1, y2,
649                                         scene->safe_areas.title_center,
650                                         scene->safe_areas.action_center);
651                         }
652                 }
653
654                 if (ca->flag & CAM_SHOWSENSOR) {
655                         /* determine sensor fit, and get sensor x/y, for auto fit we
656                          * assume and square sensor and only use sensor_x */
657                         float sizex = scene->r.xsch * scene->r.xasp;
658                         float sizey = scene->r.ysch * scene->r.yasp;
659                         int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey);
660                         float sensor_x = ca->sensor_x;
661                         float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
662
663                         /* determine sensor plane */
664                         rctf rect;
665
666                         if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
667                                 float sensor_scale = (x2i - x1i) / sensor_x;
668                                 float sensor_height = sensor_scale * sensor_y;
669
670                                 rect.xmin = x1i;
671                                 rect.xmax = x2i;
672                                 rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
673                                 rect.ymax = rect.ymin + sensor_height;
674                         }
675                         else {
676                                 float sensor_scale = (y2i - y1i) / sensor_y;
677                                 float sensor_width = sensor_scale * sensor_x;
678
679                                 rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
680                                 rect.xmax = rect.xmin + sensor_width;
681                                 rect.ymin = y1i;
682                                 rect.ymax = y2i;
683                         }
684
685                         /* draw */
686                         float color[4];
687                         UI_GetThemeColorShade4fv(TH_VIEW_OVERLAY, 100, color);
688                         UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);
689                 }
690         }
691
692         setlinestyle(0);
693
694         /* camera name - draw in highlighted text color */
695         if (ca && (ca->flag & CAM_SHOWNAME)) {
696                 UI_ThemeColor(TH_TEXT_HI);
697                 BLF_draw_default(
698                         x1i, y1i - (0.7f * U.widget_unit), 0.0f,
699                         v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
700         }
701
702         immUnbindProgram();
703 }
704
705 static void drawrenderborder(ARegion *ar, View3D *v3d)
706 {
707         /* use the same program for everything */
708         unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
709         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
710
711         glLineWidth(1.0f);
712         setlinestyle(3);
713         imm_cpack(0x4040FF);
714
715         imm_draw_line_box(
716             pos, v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
717             v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
718
719         setlinestyle(0);
720
721         immUnbindProgram();
722 }
723
724 /* ******************** offline engine ***************** */
725
726 static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
727         ARegion *ar, View3D *v3d,
728         bool clip_border, const rcti *border_rect)
729 {
730         RegionView3D *rv3d = ar->regiondata;
731         RenderEngineType *type;
732         GLint scissor[4];
733
734         /* create render engine */
735         if (!rv3d->render_engine) {
736                 RenderEngine *engine;
737
738                 type = RE_engines_find(scene->r.engine);
739
740                 if (!(type->view_update && type->view_draw))
741                         return false;
742
743                 engine = RE_engine_create_ex(type, true);
744
745                 engine->tile_x = scene->r.tilex;
746                 engine->tile_y = scene->r.tiley;
747
748                 type->view_update(engine, C);
749
750                 rv3d->render_engine = engine;
751         }
752
753         /* background draw */
754         glMatrixMode(GL_PROJECTION);
755         glPushMatrix();
756         glMatrixMode(GL_MODELVIEW);
757         glPushMatrix();
758         ED_region_pixelspace(ar);
759
760         if (clip_border) {
761                 /* for border draw, we only need to clear a subset of the 3d view */
762                 if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
763                         glGetIntegerv(GL_SCISSOR_BOX, scissor);
764                         glScissor(border_rect->xmin, border_rect->ymin,
765                                 BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
766                 }
767                 else {
768                         return false;
769                 }
770         }
771
772         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
773         /* don't change depth buffer */
774         glClear(GL_COLOR_BUFFER_BIT); /* is this necessary? -- merwin */
775
776         /* render result draw */
777         type = rv3d->render_engine->type;
778         type->view_draw(rv3d->render_engine, C);
779
780         if (clip_border) {
781                 /* restore scissor as it was before */
782                 glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
783         }
784
785         glMatrixMode(GL_PROJECTION);
786         glPopMatrix();
787         glMatrixMode(GL_MODELVIEW);
788         glPopMatrix();
789
790         return true;
791 }
792
793 /* ******************** background plates ***************** */
794
795 static void view3d_draw_background_gradient()
796 {
797         gpuMatrixBegin3D(); /* TODO: finish 2D API */
798
799         glClear(GL_DEPTH_BUFFER_BIT);
800
801         VertexFormat *format = immVertexFormat();
802         unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
803         unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
804         unsigned char col_hi[3], col_lo[3];
805
806         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
807
808         UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
809         UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
810
811         immBegin(GL_QUADS, 4);
812         immAttrib3ubv(color, col_lo);
813         immVertex2f(pos, -1.0f, -1.0f);
814         immVertex2f(pos, 1.0f, -1.0f);
815
816         immAttrib3ubv(color, col_hi);
817         immVertex2f(pos, 1.0f, 1.0f);
818         immVertex2f(pos, -1.0f, 1.0f);
819         immEnd();
820
821         immUnbindProgram();
822
823         gpuMatrixEnd();
824 }
825
826 static void view3d_draw_background_none()
827 {
828         if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
829                 view3d_draw_background_gradient();
830         }
831         else {
832                 UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
833                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
834         }
835 }
836
837 static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
838 {
839         if (scene->world) {
840                 GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
841
842                 /* calculate full shader for background */
843                 GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
844
845                 if (GPU_material_bound(gpumat)) {
846
847                         glClear(GL_DEPTH_BUFFER_BIT);
848
849                         /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode,
850                         * we can't get rid of the following code without a bigger refactor
851                         * or we dropping this functionality. */
852
853                         glBegin(GL_TRIANGLE_STRIP);
854                         glVertex2f(-1.0f, -1.0f);
855                         glVertex2f(1.0f, -1.0f);
856                         glVertex2f(-1.0f, 1.0f);
857                         glVertex2f(1.0f, 1.0f);
858                         glEnd();
859
860                         GPU_material_unbind(gpumat);
861                 }
862                 else {
863                         view3d_draw_background_none();
864                 }
865         }
866         else {
867                 view3d_draw_background_none();
868         }
869 }
870
871 /* ******************** solid plates ***************** */
872
873 /**
874  * Clear the buffer and draw the proper shader
875  */
876 static void view3d_draw_background(const bContext *C)
877 {
878         Scene *scene = CTX_data_scene(C);
879         View3D *v3d = CTX_wm_view3d(C);
880         RegionView3D *rv3d = CTX_wm_region_view3d(C);
881
882         glDisable(GL_DEPTH_TEST);
883         glDepthMask(GL_TRUE);
884         /* Background functions do not read or write depth, but they do clear or completely
885          * overwrite color buffer. It's more efficient to clear color & depth in once call, so
886          * background functions do this even though they don't use depth.
887          */
888
889         switch (v3d->debug.background) {
890                 case V3D_DEBUG_BACKGROUND_WORLD:
891                         view3d_draw_background_world(scene, v3d, rv3d);
892                         break;
893                 case V3D_DEBUG_BACKGROUND_GRADIENT:
894                         view3d_draw_background_gradient();
895                         break;
896                 case V3D_DEBUG_BACKGROUND_NONE:
897                 default:
898                         view3d_draw_background_none();
899                         break;
900         }
901 }
902
903 /**
904  *
905  */
906 static void view3d_draw_render_solid_surfaces(const bContext *C, ARegion *ar, const bool run_screen_shaders)
907 {
908         /* TODO viewport */
909         draw_all_objects(C, ar, false, use_depth(C));
910 }
911
912 /**
913  *
914  */
915 static void view3d_draw_render_transparent_surfaces(const bContext *C)
916 {
917         /* TODO viewport */
918 }
919
920 /**
921  *
922  */
923 static void view3d_draw_post_draw(const bContext *C)
924 {
925         /* TODO viewport */
926 }
927
928 /* ******************** geometry overlay ***************** */
929
930 /**
931  * Front/back wire frames
932  */
933 static void view3d_draw_wire_plates(const bContext *C)
934 {
935         /* TODO viewport */
936 }
937
938 /**
939  * Special treatment for selected objects
940  */
941 static void view3d_draw_outline_plates(const bContext *C)
942 {
943         /* TODO viewport */
944 }
945
946 /* ******************** other elements ***************** */
947
948
949 #define DEBUG_GRID 0
950
951 static void gridline_range(double x0, double dx, double max, int* first_out, int* count_out)
952 {
953         /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
954         * x0 is gridline 0, the axis in screen space
955         * Area covers [0 .. max) pixels */
956
957         int first = (int)ceil(-x0 / dx);
958         int last = (int)floor((max - x0) / dx);
959
960         if (first <= last) {
961                 *first_out = first;
962                 *count_out = last - first + 1;
963         }
964         else {
965                 *first_out = 0;
966                 *count_out = 0;
967         }
968
969 #if DEBUG_GRID
970         printf("   first %d * dx = %f\n", first, x0 + first * dx);
971         printf("   last %d * dx = %f\n", last, x0 + last * dx);
972         printf("   count = %d\n", *count_out);
973 #endif
974 }
975
976 static int gridline_count(ARegion *ar, double x0, double y0, double dx)
977 {
978         /* x0 & y0 establish the "phase" of the grid within this 2D region
979         * dx is the frequency, shared by x & y directions
980         * pass in dx of smallest (highest precision) grid we want to draw */
981
982 #if DEBUG_GRID
983         printf("  %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx);
984 #endif
985
986         int first, x_ct, y_ct;
987
988         gridline_range(x0, dx, ar->winx, &first, &x_ct);
989         gridline_range(y0, dx, ar->winy, &first, &y_ct);
990
991         int total_ct = x_ct + y_ct;
992
993 #if DEBUG_GRID
994         printf("   %d + %d = %d gridlines\n", x_ct, y_ct, total_ct);
995 #endif
996
997         return total_ct;
998 }
999
1000 static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
1001 {
1002         /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
1003         * always skip exact x0 & y0 axes; they will be drawn later in color
1004         *
1005         * set grid color once, just before the first line is drawn
1006         * it's harmless to set same color for every line, or every vertex
1007         * but if no lines are drawn, color must not be set! */
1008
1009 #if DEBUG_GRID
1010         printf("  %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod);
1011 #endif
1012
1013         const float x_max = (float)ar->winx;
1014         const float y_max = (float)ar->winy;
1015
1016         int first, ct;
1017         int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
1018         int lines_skipped_for_next_unit = 0;
1019
1020         /* draw vertical lines */
1021         gridline_range(x0, dx, x_max, &first, &ct);
1022
1023         for (int i = first; i < first + ct; ++i) {
1024                 if (i == 0)
1025                         continue;
1026                 else if (skip_mod && (i % skip_mod) == 0) {
1027                         ++lines_skipped_for_next_unit;
1028                         continue;
1029                 }
1030
1031                 if (x_ct == 0)
1032                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1033
1034                 float x = (float)(x0 + i * dx);
1035                 immVertex2f(pos, x, 0.0f);
1036                 immVertex2f(pos, x, y_max);
1037                 ++x_ct;
1038         }
1039
1040         /* draw horizontal lines */
1041         gridline_range(y0, dx, y_max, &first, &ct);
1042
1043         for (int i = first; i < first + ct; ++i) {
1044                 if (i == 0)
1045                         continue;
1046                 else if (skip_mod && (i % skip_mod) == 0) {
1047                         ++lines_skipped_for_next_unit;
1048                         continue;
1049                 }
1050
1051                 if (x_ct + y_ct == 0)
1052                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1053
1054                 float y = (float)(y0 + i * dx);
1055                 immVertex2f(pos, 0.0f, y);
1056                 immVertex2f(pos, x_max, y);
1057                 ++y_ct;
1058         }
1059
1060 #if DEBUG_GRID
1061         int total_ct = x_ct + y_ct;
1062         printf("    %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit);
1063 #endif
1064
1065         return lines_skipped_for_next_unit > 0;
1066 }
1067
1068 #define GRID_MIN_PX_D 6.0
1069 #define GRID_MIN_PX_F 6.0f
1070
1071 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
1072 {
1073         RegionView3D *rv3d = ar->regiondata;
1074
1075 #if DEBUG_GRID
1076         printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy);
1077 #endif
1078
1079         double fx = rv3d->persmat[3][0];
1080         double fy = rv3d->persmat[3][1];
1081         double fw = rv3d->persmat[3][3];
1082
1083         const double wx = 0.5 * ar->winx;  /* use double precision to avoid rounding errors */
1084         const double wy = 0.5 * ar->winy;
1085
1086         double x = wx * fx / fw;
1087         double y = wy * fy / fw;
1088
1089         double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
1090         mul_m4_v4d(rv3d->persmat, vec4);
1091         fx = vec4[0];
1092         fy = vec4[1];
1093         fw = vec4[3];
1094
1095         double dx = fabs(x - wx * fx / fw);
1096         if (dx == 0) dx = fabs(y - wy * fy / fw);
1097
1098         x += wx;
1099         y += wy;
1100
1101         /* now x, y, and dx have their final values
1102         * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
1103         * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
1104
1105         glLineWidth(1.0f);
1106
1107 #if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
1108         glDepthMask(GL_FALSE);  /* disable write in zbuffer */
1109 #endif
1110
1111         VertexFormat* format = immVertexFormat();
1112         unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1113         unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1114
1115         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1116
1117         unsigned char col[3], col2[3];
1118         UI_GetThemeColor3ubv(TH_GRID, col);
1119
1120         if (unit->system) {
1121                 const void *usys;
1122                 int len;
1123
1124                 bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
1125
1126                 bool first = true;
1127
1128                 if (usys) {
1129                         int i = len;
1130                         while (i--) {
1131                                 double scalar = bUnit_GetScaler(usys, i);
1132
1133                                 double dx_scalar = dx * scalar / (double)unit->scale_length;
1134                                 if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
1135                                         /* very very small grid items are less useful when dealing with units */
1136                                         continue;
1137                                 }
1138
1139                                 if (first) {
1140                                         first = false;
1141
1142                                         /* Store the smallest drawn grid size units name so users know how big each grid cell is */
1143                                         *grid_unit = bUnit_GetNameDisplay(usys, i);
1144                                         rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
1145
1146                                         int gridline_ct = gridline_count(ar, x, y, dx_scalar);
1147                                         if (gridline_ct == 0)
1148                                                 goto drawgrid_cleanup; /* nothing to draw */
1149
1150                                         immBegin(GL_LINES, gridline_ct * 2);
1151                                 }
1152
1153                                 float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
1154                                 /* tweak to have the fade a bit nicer */
1155                                 blend_fac = (blend_fac * blend_fac) * 2.0f;
1156                                 CLAMP(blend_fac, 0.3f, 1.0f);
1157
1158                                 UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
1159
1160                                 const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
1161 #if DEBUG_GRID
1162                                 printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar);
1163                                 if (i > 0)
1164                                         printf("next unit is %d times larger\n", skip_mod);
1165                                 else
1166                                         printf("largest unit\n");
1167 #endif
1168                                 if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
1169                                         break;
1170                         }
1171                 }
1172         }
1173         else {
1174                 const double sublines = v3d->gridsubdiv;
1175                 const float  sublines_fl = v3d->gridsubdiv;
1176
1177                 int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
1178
1179                 if (dx < GRID_MIN_PX_D) {
1180                         rv3d->gridview *= sublines_fl;
1181                         dx *= sublines;
1182                         if (dx < GRID_MIN_PX_D) {
1183                                 rv3d->gridview *= sublines_fl;
1184                                 dx *= sublines;
1185                                 if (dx < GRID_MIN_PX_D) {
1186                                         rv3d->gridview *= sublines_fl;
1187                                         dx *= sublines;
1188                                         grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
1189                                 }
1190                         }
1191                 }
1192                 else {
1193                         if (dx >(GRID_MIN_PX_D * 10.0)) {  /* start blending in */
1194                                 rv3d->gridview /= sublines_fl;
1195                                 dx /= sublines;
1196                                 if (dx > (GRID_MIN_PX_D * 10.0)) {  /* start blending in */
1197                                         rv3d->gridview /= sublines_fl;
1198                                         dx /= sublines;
1199                                         if (dx > (GRID_MIN_PX_D * 10.0)) {
1200                                                 grids_to_draw = 1;
1201                                         }
1202                                 }
1203                         }
1204                 }
1205
1206                 int gridline_ct = gridline_count(ar, x, y, dx);
1207                 if (gridline_ct == 0)
1208                         goto drawgrid_cleanup; /* nothing to draw */
1209
1210                 immBegin(GL_LINES, gridline_ct * 2);
1211
1212                 if (grids_to_draw == 2) {
1213                         UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
1214                         if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
1215                                 drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
1216                 }
1217                 else if (grids_to_draw == 1) {
1218                         drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
1219                 }
1220         }
1221
1222         /* draw visible axes */
1223         /* horizontal line */
1224         if (0 <= y && y < ar->winy) {
1225                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
1226                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1227                 immVertex2f(pos, 0.0f, y);
1228                 immVertex2f(pos, (float)ar->winx, y);
1229         }
1230
1231         /* vertical line */
1232         if (0 <= x && x < ar->winx) {
1233                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
1234                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1235                 immVertex2f(pos, x, 0.0f);
1236                 immVertex2f(pos, x, (float)ar->winy);
1237         }
1238
1239         immEnd();
1240
1241 drawgrid_cleanup:
1242         immUnbindProgram();
1243
1244 #if 0 /* depth write is left enabled above */
1245         glDepthMask(GL_TRUE);  /* enable write in zbuffer */
1246 #endif
1247 }
1248
1249 #undef DEBUG_GRID
1250 #undef GRID_MIN_PX_D
1251 #undef GRID_MIN_PX_F
1252
1253 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
1254 {
1255         /* draw only if there is something to draw */
1256         if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
1257                 /* draw how many lines?
1258                 * trunc(v3d->gridlines / 2) * 4
1259                 * + 2 for xy axes (possibly with special colors)
1260                 * + 1 for z axis (the only line not in xy plane)
1261                 * even v3d->gridlines are honored, odd rounded down */
1262                 const int gridlines = v3d->gridlines / 2;
1263                 const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
1264                 const float grid = gridlines * grid_scale;
1265
1266                 const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
1267
1268                 bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
1269                 bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
1270                 bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
1271
1272                 unsigned char col_grid[3], col_axis[3];
1273
1274                 glLineWidth(1.0f);
1275
1276                 UI_GetThemeColor3ubv(TH_GRID, col_grid);
1277
1278                 if (!write_depth)
1279                         glDepthMask(GL_FALSE);
1280
1281                 if (show_floor) {
1282                         const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
1283                         const int sublines = v3d->gridsubdiv;
1284
1285                         unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
1286
1287                         VertexFormat* format = immVertexFormat();
1288                         unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
1289                         unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1290
1291                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1292
1293                         immBegin(GL_LINES, vertex_ct);
1294
1295                         /* draw normal grid lines */
1296                         UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
1297
1298                         for (int a = 1; a <= gridlines; a++) {
1299                                 /* skip emphasised divider lines */
1300                                 if (a % sublines != 0) {
1301                                         const float line = a * grid_scale;
1302
1303                                         immAttrib3ubv(color, col_grid_light);
1304
1305                                         immVertex2f(pos, -grid, -line);
1306                                         immVertex2f(pos, +grid, -line);
1307                                         immVertex2f(pos, -grid, +line);
1308                                         immVertex2f(pos, +grid, +line);
1309
1310                                         immVertex2f(pos, -line, -grid);
1311                                         immVertex2f(pos, -line, +grid);
1312                                         immVertex2f(pos, +line, -grid);
1313                                         immVertex2f(pos, +line, +grid);
1314                                 }
1315                         }
1316
1317                         /* draw emphasised grid lines */
1318                         UI_GetThemeColor3ubv(TH_BACK, col_bg);
1319                         /* emphasise division lines lighter instead of darker, if background is darker than grid */
1320                         UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
1321                                 (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
1322                                 col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
1323
1324                         if (sublines <= gridlines) {
1325                                 immAttrib3ubv(color, col_grid_emphasise);
1326
1327                                 for (int a = sublines; a <= gridlines; a += sublines) {
1328                                         const float line = a * grid_scale;
1329
1330                                         immVertex2f(pos, -grid, -line);
1331                                         immVertex2f(pos, +grid, -line);
1332                                         immVertex2f(pos, -grid, +line);
1333                                         immVertex2f(pos, +grid, +line);
1334
1335                                         immVertex2f(pos, -line, -grid);
1336                                         immVertex2f(pos, -line, +grid);
1337                                         immVertex2f(pos, +line, -grid);
1338                                         immVertex2f(pos, +line, +grid);
1339                                 }
1340                         }
1341
1342                         /* draw X axis */
1343                         if (show_axis_x) {
1344                                 show_axis_x = false; /* drawing now, won't need to draw later */
1345                                 UI_make_axis_color(col_grid, col_axis, 'X');
1346                                 immAttrib3ubv(color, col_axis);
1347                         }
1348                         else
1349                                 immAttrib3ubv(color, col_grid_emphasise);
1350
1351                         immVertex2f(pos, -grid, 0.0f);
1352                         immVertex2f(pos, +grid, 0.0f);
1353
1354                         /* draw Y axis */
1355                         if (show_axis_y) {
1356                                 show_axis_y = false; /* drawing now, won't need to draw later */
1357                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1358                                 immAttrib3ubv(color, col_axis);
1359                         }
1360                         else
1361                                 immAttrib3ubv(color, col_grid_emphasise);
1362
1363                         immVertex2f(pos, 0.0f, -grid);
1364                         immVertex2f(pos, 0.0f, +grid);
1365
1366                         immEnd();
1367                         immUnbindProgram();
1368
1369                         /* done with XY plane */
1370                 }
1371
1372                 if (show_axis_x || show_axis_y || show_axis_z) {
1373                         /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
1374
1375                         VertexFormat* format = immVertexFormat();
1376                         unsigned pos = add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
1377                         unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
1378
1379                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1380                         immBegin(GL_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
1381
1382                         if (show_axis_x) {
1383                                 UI_make_axis_color(col_grid, col_axis, 'X');
1384                                 immAttrib3ubv(color, col_axis);
1385                                 immVertex3f(pos, -grid, 0.0f, 0.0f);
1386                                 immVertex3f(pos, +grid, 0.0f, 0.0f);
1387                         }
1388
1389                         if (show_axis_y) {
1390                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1391                                 immAttrib3ubv(color, col_axis);
1392                                 immVertex3f(pos, 0.0f, -grid, 0.0f);
1393                                 immVertex3f(pos, 0.0f, +grid, 0.0f);
1394                         }
1395
1396                         if (show_axis_z) {
1397                                 UI_make_axis_color(col_grid, col_axis, 'Z');
1398                                 immAttrib3ubv(color, col_axis);
1399                                 immVertex3f(pos, 0.0f, 0.0f, -grid);
1400                                 immVertex3f(pos, 0.0f, 0.0f, +grid);
1401                         }
1402
1403                         immEnd();
1404                         immUnbindProgram();
1405                 }
1406
1407                 if (!write_depth)
1408                         glDepthMask(GL_TRUE);
1409         }
1410 }
1411
1412 /** could move this elsewhere, but tied into #ED_view3d_grid_scale */
1413 float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
1414 {
1415         /* apply units */
1416         if (scene->unit.system) {
1417                 const void *usys;
1418                 int len;
1419
1420                 bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
1421
1422                 if (usys) {
1423                         int i = bUnit_GetBaseUnit(usys);
1424                         if (grid_unit)
1425                                 *grid_unit = bUnit_GetNameDisplay(usys, i);
1426                         return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
1427                 }
1428         }
1429
1430         return 1.0f;
1431 }
1432
1433 float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
1434 {
1435         return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
1436 }
1437
1438 /**
1439  *
1440  */
1441 static void view3d_draw_grid(const bContext *C, ARegion *ar)
1442 {
1443         /* TODO viewport
1444          * Missing is the flags to check whether to draw it
1445          * for now now we are using the flags in v3d itself.
1446          *
1447          * Also for now always assume depth is there, so we
1448          * draw on top of it.
1449          */
1450         Scene *scene = CTX_data_scene(C);
1451         View3D *v3d = CTX_wm_view3d(C);
1452         RegionView3D *rv3d = ar->regiondata;
1453
1454         const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
1455         const char *grid_unit = NULL;
1456
1457         /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
1458          * objects if done last
1459          * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
1460          */
1461         rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
1462
1463         glEnable(GL_DEPTH_TEST);
1464         glDepthMask(GL_FALSE); /* read & test depth, but don't alter it. TODO: separate UI depth buffer */
1465
1466         if (!draw_floor) {
1467                 ED_region_pixelspace(ar);
1468                 *(&grid_unit) = NULL;  /* drawgrid need this to detect/affect smallest valid unit... */
1469                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
1470
1471                 glMatrixMode(GL_PROJECTION);
1472                 glLoadMatrixf(rv3d->winmat);
1473                 glMatrixMode(GL_MODELVIEW);
1474                 glLoadMatrixf(rv3d->viewmat);
1475         }
1476         else {
1477                 drawfloor(scene, v3d, &grid_unit, false);
1478         }
1479
1480         glDisable(GL_DEPTH_TEST);
1481 }
1482
1483 /* ******************** non-meshes ***************** */
1484
1485 static void view3d_draw_non_mesh(
1486 Scene *scene, Object *ob, Base *base, View3D *v3d,
1487 RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
1488 {
1489         glMatrixMode(GL_PROJECTION);
1490         glPushMatrix();
1491         glMatrixMode(GL_MODELVIEW);
1492         glPushMatrix();
1493
1494         /* multiply view with object matrix.
1495         * local viewmat and persmat, to calculate projections */
1496         ED_view3d_init_mats_rv3d_gl(ob, rv3d);
1497
1498         switch (ob->type) {
1499                 case OB_MESH:
1500                 case OB_FONT:
1501                 case OB_CURVE:
1502                 case OB_SURF:
1503                 case OB_MBALL:
1504                         if (is_boundingbox) {
1505                                 draw_bounding_volume(ob, ob->boundtype);
1506                         }
1507                         break;
1508                 case OB_EMPTY:
1509                         drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
1510                         break;
1511                 case OB_LAMP:
1512                         drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT);
1513                         break;
1514                 case OB_CAMERA:
1515                         drawcamera(scene, v3d, rv3d, base, DRAW_CONSTCOLOR, color);
1516                         break;
1517                 case OB_SPEAKER:
1518                         drawspeaker(color);
1519                         break;
1520                 case OB_LATTICE:
1521                         /* TODO */
1522                         break;
1523                 case OB_ARMATURE:
1524                         /* TODO */
1525                         break;
1526                 default:
1527                 /* TODO Viewport: handle the other cases*/
1528                         break;
1529         }
1530
1531         if (ob->rigidbody_object) {
1532                 draw_rigidbody_shape(ob);
1533         }
1534
1535         ED_view3d_clear_mats_rv3d(rv3d);
1536
1537         glMatrixMode(GL_PROJECTION);
1538         glPopMatrix();
1539         glMatrixMode(GL_MODELVIEW);
1540         glPopMatrix();
1541 }
1542
1543 /* ******************** info ***************** */
1544
1545 /**
1546 * Render and camera border
1547 */
1548 static void view3d_draw_border(const bContext *C, ARegion *ar)
1549 {
1550         Scene *scene = CTX_data_scene(C);
1551         RegionView3D *rv3d = ar->regiondata;
1552         View3D *v3d = CTX_wm_view3d(C);
1553
1554         if (rv3d->persp == RV3D_CAMOB) {
1555                 drawviewborder(scene, ar, v3d);
1556         }
1557         else if (v3d->flag2 & V3D_RENDER_BORDER) {
1558                 drawrenderborder(ar, v3d);
1559         }
1560 }
1561
1562 /**
1563 * Grease Pencil
1564 */
1565 static void view3d_draw_grease_pencil(const bContext *C)
1566 {
1567         /* TODO viewport */
1568 }
1569
1570 /* ******************** view loop ***************** */
1571
1572 /**
1573  * Set the correct matrices
1574  */
1575 static void view3d_draw_setup_view(const bContext *C, ARegion *ar)
1576 {
1577         Scene *scene = CTX_data_scene(C);
1578         View3D *v3d = CTX_wm_view3d(C);
1579         RegionView3D *rv3d = ar->regiondata;
1580
1581         /* setup the view matrix */
1582         if (view3d_stereo3d_active(C, scene, v3d, rv3d))
1583                 view3d_stereo3d_setup(scene, v3d, ar);
1584         else
1585                 view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
1586 }
1587
1588 static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth)
1589 {
1590         Scene *scene = CTX_data_scene(C);
1591         View3D *v3d = CTX_wm_view3d(C);
1592         Base *base;
1593
1594         if (only_depth)
1595                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1596
1597         if (only_depth || use_depth) {
1598                 glEnable(GL_DEPTH_TEST);
1599                 glDepthFunc(GL_LESS);
1600                 glDepthMask(GL_TRUE);
1601                 v3d->zbuf = true;
1602         }
1603
1604         for (base = scene->base.first; base; base = base->next) {
1605                 if (v3d->lay & base->lay) {
1606                         /* dupli drawing */
1607                         if (base->object->transflag & OB_DUPLI)
1608                                 draw_dupli_objects(scene, ar, v3d, base);
1609
1610                         draw_object(scene, ar, v3d, base, 0);
1611                 }
1612         }
1613
1614         if (only_depth)
1615                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1616
1617         if (only_depth || use_depth) {
1618                 glDisable(GL_DEPTH_TEST);
1619                 v3d->zbuf = false;
1620         }
1621 }
1622
1623 /**
1624  * Draw only the scene depth buffer
1625  */
1626 static void draw_depth_buffer(const bContext *C, ARegion *ar)
1627 {
1628         draw_all_objects(C, ar, true, true);
1629 }
1630
1631 /**
1632  * Required if the shaders need it or external engines
1633  * (e.g., Cycles requires depth buffer handled separately).
1634  */
1635 static void view3d_draw_prerender_buffers(const bContext *C, ARegion *ar, DrawData *draw_data)
1636 {
1637         View3D *v3d = CTX_wm_view3d(C);
1638
1639         /* TODO viewport */
1640         if (draw_data->is_render && ((!draw_data->clip_border) || (v3d->drawtype <= OB_WIRE))) {
1641                 draw_depth_buffer(C, ar);
1642         }
1643 }
1644
1645 /**
1646  * Draw all the plates that will fill the RGBD buffer
1647  */
1648 static void view3d_draw_solid_plates(const bContext *C, ARegion *ar, DrawData *draw_data)
1649 {
1650         Scene *scene = CTX_data_scene(C);
1651         View3D *v3d = CTX_wm_view3d(C);
1652
1653         /* realtime plates */
1654         if ((!draw_data->is_render) || draw_data->clip_border) {
1655                 view3d_draw_background(C);
1656                 view3d_draw_render_solid_surfaces(C, ar, true);
1657                 view3d_draw_render_transparent_surfaces(C);
1658                 view3d_draw_post_draw(C);
1659         }
1660
1661         /* offline plates*/
1662         if (draw_data->is_render) {
1663                 view3d_draw_render_draw(C, scene, ar, v3d, draw_data->clip_border, &draw_data->border_rect);
1664         }
1665
1666 #if VIEW3D_DRAW_DEBUG
1667         view3d_draw_debug_post_solid(C, ar, draw_data);
1668 #endif
1669 }
1670
1671 /**
1672  * Wires, outline, ...
1673  */
1674 static void view3d_draw_geometry_overlay(const bContext *C)
1675 {
1676         view3d_draw_wire_plates(C);
1677         view3d_draw_outline_plates(C);
1678 }
1679
1680 /* drawing cameras, lamps, ... */
1681 static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
1682 {
1683         /* TODO viewport
1684          * for now we draw them all, in the near future
1685          * we filter them based on the plates/layers
1686          */
1687         Scene *scene = CTX_data_scene(C);
1688         View3D *v3d = CTX_wm_view3d(C);
1689         RegionView3D *rv3d = ar->regiondata;
1690         Object *ob_act = CTX_data_active_object(C);
1691         Base *base;
1692
1693         bool is_boundingbox = ((v3d->drawtype == OB_BOUNDBOX) ||
1694                                 ((v3d->drawtype == OB_RENDER) && (v3d->prev_drawtype == OB_BOUNDBOX)));
1695
1696         unsigned char ob_wire_col[4];            /* dont initialize this */
1697
1698         glEnable(GL_DEPTH_TEST);
1699         glDepthMask(GL_TRUE);
1700         /* TODO Viewport
1701          * we are already temporarily writing to zbuffer in draw_object()
1702          * for now let's avoid writing again to zbuffer to prevent glitches
1703          */
1704
1705         for (base = scene->base.first; base; base = base->next) {
1706                 if (v3d->lay & base->lay) {
1707                         Object *ob = base->object;
1708
1709                         draw_object_wire_color(scene, base, ob_wire_col);
1710                         view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col);
1711                 }
1712         }
1713
1714         glDepthMask(GL_FALSE);
1715         glDisable(GL_DEPTH_TEST);
1716 }
1717
1718 /**
1719 * Parent lines, grid, ...
1720 */
1721 static void view3d_draw_other_elements(const bContext *C, ARegion *ar)
1722 {
1723         /* TODO viewport */
1724         view3d_draw_grid(C, ar);
1725 }
1726
1727 /**
1728  * Paint brushes, armatures, ...
1729  */
1730 static void view3d_draw_tool_ui(const bContext *C)
1731 {
1732         /* TODO viewport */
1733 }
1734
1735 /**
1736  * Blueprint images
1737  */
1738 static void view3d_draw_reference_images(const bContext *C)
1739 {
1740         /* TODO viewport */
1741 }
1742
1743 /**
1744 * 3D manipulators
1745 */
1746 static void view3d_draw_manipulator(const bContext *C)
1747 {
1748         View3D *v3d = CTX_wm_view3d(C);
1749         v3d->zbuf = false;
1750         BIF_draw_manipulator(C);
1751 }
1752
1753 /**
1754 * Information drawn on top of the solid plates and composed data
1755 */
1756 static void view3d_draw_region_info(const bContext *C, ARegion *ar)
1757 {
1758         rcti rect;
1759
1760         /* correct projection matrix */
1761         ED_region_pixelspace(ar);
1762
1763         /* local coordinate visible rect inside region, to accomodate overlapping ui */
1764         ED_region_visible_rect(ar, &rect);
1765
1766         view3d_draw_border(C, ar);
1767         view3d_draw_grease_pencil(C);
1768
1769         /* TODO viewport */
1770 }
1771
1772 /**
1773  * This could run once per view, or even in parallel
1774  * for each of them. What is a "view"?
1775  * - a viewport with the camera elsewhere
1776  * - left/right stereo
1777  * - panorama / fisheye individual cubemap faces
1778  */
1779 static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data)
1780 {
1781         /* TODO - Technically this should be drawn to a few FBO, so we can handle
1782          * compositing better, but for now this will get the ball rolling (dfelinto) */
1783
1784         view3d_draw_setup_view(C, ar);
1785         view3d_draw_prerender_buffers(C, ar, draw_data);
1786         view3d_draw_solid_plates(C, ar, draw_data);
1787         view3d_draw_geometry_overlay(C);
1788         view3d_draw_non_meshes(C, ar);
1789         view3d_draw_other_elements(C, ar);
1790         view3d_draw_tool_ui(C);
1791         view3d_draw_reference_images(C);
1792         view3d_draw_manipulator(C);
1793         view3d_draw_region_info(C, ar);
1794
1795 #if VIEW3D_DRAW_DEBUG
1796         view3d_draw_debug(C, ar, draw_data);
1797 #endif
1798 }
1799
1800 void view3d_main_region_draw(const bContext *C, ARegion *ar)
1801 {
1802         View3D *v3d = CTX_wm_view3d(C);
1803         RegionView3D *rv3d = ar->regiondata;
1804
1805         if (IS_VIEWPORT_LEGACY(v3d)) {
1806                 view3d_main_region_draw_legacy(C, ar);
1807                 return;
1808         }
1809
1810         if (!rv3d->viewport)
1811                 rv3d->viewport = GPU_viewport_create();
1812
1813         /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
1814          * before we even call the drawing routine, but let's move on for now (dfelinto)
1815          * but this is a provisory way to start seeing things in the viewport */
1816         DrawData draw_data;
1817         view3d_draw_data_init(C, ar, rv3d, &draw_data);
1818         view3d_draw_view(C, ar, &draw_data);
1819
1820         v3d->flag |= V3D_INVALID_BACKBUF;
1821 }
1822
1823 /* ******************** legacy interface ***************** */
1824 /**
1825  * This will be removed once the viewport gets replaced
1826  * meanwhile it should keep the old viewport working.
1827  */
1828
1829 void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
1830 {
1831         drawgrid(unit, ar, v3d, grid_unit);
1832 }
1833
1834 void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
1835 {
1836         drawfloor(scene, v3d, grid_unit, write_depth);
1837 }
1838
1839 void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
1840 {
1841         view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
1842 }
1843
1844 bool VP_legacy_view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
1845 {
1846         return view3d_stereo3d_active(C, scene, v3d, rv3d);
1847 }
1848
1849 void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
1850 {
1851         view3d_stereo3d_setup(scene, v3d, ar);
1852 }
1853
1854 bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
1855 {
1856         return use_depth_doit(scene, v3d);
1857 }
1858
1859 void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
1860 {
1861         drawviewborder(scene, ar, v3d);
1862 }
1863
1864 void VP_drawrenderborder(ARegion *ar, View3D *v3d)
1865 {
1866         drawrenderborder(ar, v3d);
1867 }
1868
1869 void VP_view3d_draw_background_none(void)
1870 {
1871         view3d_draw_background_none();
1872 }
1873
1874 void VP_view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
1875 {
1876         view3d_draw_background_world(scene, v3d, rv3d);
1877 }