blender 2.8: OpenGL immediate mode: action_draw
[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         VertexFormat *format = immVertexFormat();
510         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
511
512         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
513
514         /* passepartout, specified in camera edit buttons */
515         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
516                 const float winx = (ar->winx + 1);
517                 const float winy = (ar->winy + 1);
518
519                 float alpha = 1.0f;
520
521                 if (ca->passepartalpha != 1.0f) {
522                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
523                         glEnable(GL_BLEND);
524                         alpha = ca->passepartalpha;
525                 }
526
527                 immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
528
529                 if (x1i > 0.0f)
530                         immRectf(pos, 0.0f, winy, x1i, 0.0f);
531                 if (x2i < winx)
532                         immRectf(pos, x2i, winy, winx, 0.0f);
533                 if (y2i < winy)
534                         immRectf(pos, x1i, winy, x2i, y2i);
535                 if (y2i > 0.0f)
536                         immRectf(pos, x1i, y1i, x2i, 0.0f);
537
538                 glDisable(GL_BLEND);
539         }
540
541         setlinestyle(0);
542
543         immUniformThemeColor(TH_BACK);
544         imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
545
546 #ifdef VIEW3D_CAMERA_BORDER_HACK
547         if (view3d_camera_border_hack_test == true) {
548                 immUniformColor3ubv(view3d_camera_border_hack_col);
549                 imm_draw_line_box(pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
550                 view3d_camera_border_hack_test = false;
551         }
552 #endif
553
554         setlinestyle(3);
555
556         /* outer line not to confuse with object selecton */
557         if (v3d->flag2 & V3D_LOCK_CAMERA) {
558                 immUniformThemeColor(TH_REDALERT);
559                 imm_draw_line_box(pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
560         }
561
562         immUniformThemeColor(TH_VIEW_OVERLAY);
563         imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
564
565         /* border */
566         if (scene->r.mode & R_BORDER) {
567                 float x3, y3, x4, y4;
568
569                 x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
570                 y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
571                 x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
572                 y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
573
574                 imm_cpack(0x4040FF);
575                 imm_draw_line_box(pos, x3, y3, x4, y4);
576         }
577
578         /* safety border */
579         if (ca) {
580                 if (ca->dtx & CAM_DTX_CENTER) {
581                         float x3, y3;
582
583                         x3 = x1 + 0.5f * (x2 - x1);
584                         y3 = y1 + 0.5f * (y2 - y1);
585
586                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
587                         immBegin(GL_LINES, 4);
588
589                         immVertex2f(pos, x1, y3);
590                         immVertex2f(pos, x2, y3);
591
592                         immVertex2f(pos, x3, y1);
593                         immVertex2f(pos, x3, y2);
594
595                         immEnd();
596                 }
597
598                 if (ca->dtx & CAM_DTX_CENTER_DIAG) {
599
600                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
601                         immBegin(GL_LINES, 4);
602
603                         immVertex2f(pos, x1, y1);
604                         immVertex2f(pos, x2, y2);
605
606                         immVertex2f(pos, x1, y2);
607                         immVertex2f(pos, x2, y1);
608
609                         immEnd();
610                 }
611
612                 if (ca->dtx & CAM_DTX_THIRDS) {
613                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
614                         drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f / 3.0f);
615                 }
616
617                 if (ca->dtx & CAM_DTX_GOLDEN) {
618                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
619                         drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
620                 }
621
622                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
623                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
624                         drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'A');
625                 }
626
627                 if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
628                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
629                         drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'B');
630                 }
631
632                 if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
633                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
634                         drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'A');
635                 }
636
637                 if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
638                         immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
639                         drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'B');
640                 }
641
642                 if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
643                         UI_draw_safe_areas(
644                                 pos, x1, x2, y1, y2,
645                                 scene->safe_areas.title,
646                                 scene->safe_areas.action);
647
648                         if (ca->flag & CAM_SHOW_SAFE_CENTER) {
649                                 UI_draw_safe_areas(
650                                         pos, x1, x2, y1, y2,
651                                         scene->safe_areas.title_center,
652                                         scene->safe_areas.action_center);
653                         }
654                 }
655
656                 if (ca->flag & CAM_SHOWSENSOR) {
657                         /* determine sensor fit, and get sensor x/y, for auto fit we
658                          * assume and square sensor and only use sensor_x */
659                         float sizex = scene->r.xsch * scene->r.xasp;
660                         float sizey = scene->r.ysch * scene->r.yasp;
661                         int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey);
662                         float sensor_x = ca->sensor_x;
663                         float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y;
664
665                         /* determine sensor plane */
666                         rctf rect;
667
668                         if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
669                                 float sensor_scale = (x2i - x1i) / sensor_x;
670                                 float sensor_height = sensor_scale * sensor_y;
671
672                                 rect.xmin = x1i;
673                                 rect.xmax = x2i;
674                                 rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f;
675                                 rect.ymax = rect.ymin + sensor_height;
676                         }
677                         else {
678                                 float sensor_scale = (y2i - y1i) / sensor_y;
679                                 float sensor_width = sensor_scale * sensor_x;
680
681                                 rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f;
682                                 rect.xmax = rect.xmin + sensor_width;
683                                 rect.ymin = y1i;
684                                 rect.ymax = y2i;
685                         }
686
687                         /* draw */
688                         float color[4];
689                         UI_GetThemeColorShade4fv(TH_VIEW_OVERLAY, 100, color);
690                         UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);
691                 }
692         }
693
694         setlinestyle(0);
695
696         /* camera name - draw in highlighted text color */
697         if (ca && (ca->flag & CAM_SHOWNAME)) {
698                 UI_ThemeColor(TH_TEXT_HI);
699                 BLF_draw_default(
700                         x1i, y1i - (0.7f * U.widget_unit), 0.0f,
701                         v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
702         }
703
704         immUnbindProgram();
705 }
706
707 static void drawrenderborder(ARegion *ar, View3D *v3d)
708 {
709         /* use the same program for everything */
710         VertexFormat *format = immVertexFormat();
711         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
712         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
713
714         glLineWidth(1.0f);
715         setlinestyle(3);
716         imm_cpack(0x4040FF);
717
718         imm_draw_line_box(
719             pos, v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
720             v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
721
722         setlinestyle(0);
723
724         immUnbindProgram();
725 }
726
727 /* ******************** offline engine ***************** */
728
729 static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
730         ARegion *ar, View3D *v3d,
731         bool clip_border, const rcti *border_rect)
732 {
733         RegionView3D *rv3d = ar->regiondata;
734         RenderEngineType *type;
735         GLint scissor[4];
736
737         /* create render engine */
738         if (!rv3d->render_engine) {
739                 RenderEngine *engine;
740
741                 type = RE_engines_find(scene->r.engine);
742
743                 if (!(type->view_update && type->view_draw))
744                         return false;
745
746                 engine = RE_engine_create_ex(type, true);
747
748                 engine->tile_x = scene->r.tilex;
749                 engine->tile_y = scene->r.tiley;
750
751                 type->view_update(engine, C);
752
753                 rv3d->render_engine = engine;
754         }
755
756         /* background draw */
757         glMatrixMode(GL_PROJECTION);
758         glPushMatrix();
759         glMatrixMode(GL_MODELVIEW);
760         glPushMatrix();
761         ED_region_pixelspace(ar);
762
763         if (clip_border) {
764                 /* for border draw, we only need to clear a subset of the 3d view */
765                 if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
766                         glGetIntegerv(GL_SCISSOR_BOX, scissor);
767                         glScissor(border_rect->xmin, border_rect->ymin,
768                                 BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
769                 }
770                 else {
771                         return false;
772                 }
773         }
774
775         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
776         /* don't change depth buffer */
777         glClear(GL_COLOR_BUFFER_BIT); /* is this necessary? -- merwin */
778
779         /* render result draw */
780         type = rv3d->render_engine->type;
781         type->view_draw(rv3d->render_engine, C);
782
783         if (clip_border) {
784                 /* restore scissor as it was before */
785                 glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
786         }
787
788         glMatrixMode(GL_PROJECTION);
789         glPopMatrix();
790         glMatrixMode(GL_MODELVIEW);
791         glPopMatrix();
792
793         return true;
794 }
795
796 /* ******************** background plates ***************** */
797
798 static void view3d_draw_background_gradient()
799 {
800         gpuMatrixBegin3D(); /* TODO: finish 2D API */
801
802         glClear(GL_DEPTH_BUFFER_BIT);
803
804         VertexFormat *format = immVertexFormat();
805         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
806         unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
807         unsigned char col_hi[3], col_lo[3];
808
809         immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
810
811         UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
812         UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
813
814         immBegin(GL_QUADS, 4);
815         immAttrib3ubv(color, col_lo);
816         immVertex2f(pos, -1.0f, -1.0f);
817         immVertex2f(pos, 1.0f, -1.0f);
818
819         immAttrib3ubv(color, col_hi);
820         immVertex2f(pos, 1.0f, 1.0f);
821         immVertex2f(pos, -1.0f, 1.0f);
822         immEnd();
823
824         immUnbindProgram();
825
826         gpuMatrixEnd();
827 }
828
829 static void view3d_draw_background_none()
830 {
831         if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
832                 view3d_draw_background_gradient();
833         }
834         else {
835                 UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
836                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
837         }
838 }
839
840 static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
841 {
842         if (scene->world) {
843                 GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
844
845                 /* calculate full shader for background */
846                 GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
847
848                 if (GPU_material_bound(gpumat)) {
849
850                         glClear(GL_DEPTH_BUFFER_BIT);
851
852                         /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode,
853                         * we can't get rid of the following code without a bigger refactor
854                         * or we dropping this functionality. */
855
856                         glBegin(GL_TRIANGLE_STRIP);
857                         glVertex2f(-1.0f, -1.0f);
858                         glVertex2f(1.0f, -1.0f);
859                         glVertex2f(-1.0f, 1.0f);
860                         glVertex2f(1.0f, 1.0f);
861                         glEnd();
862
863                         GPU_material_unbind(gpumat);
864                 }
865                 else {
866                         view3d_draw_background_none();
867                 }
868         }
869         else {
870                 view3d_draw_background_none();
871         }
872 }
873
874 /* ******************** solid plates ***************** */
875
876 /**
877  * Clear the buffer and draw the proper shader
878  */
879 static void view3d_draw_background(const bContext *C)
880 {
881         Scene *scene = CTX_data_scene(C);
882         View3D *v3d = CTX_wm_view3d(C);
883         RegionView3D *rv3d = CTX_wm_region_view3d(C);
884
885         glDisable(GL_DEPTH_TEST);
886         glDepthMask(GL_TRUE);
887         /* Background functions do not read or write depth, but they do clear or completely
888          * overwrite color buffer. It's more efficient to clear color & depth in once call, so
889          * background functions do this even though they don't use depth.
890          */
891
892         switch (v3d->debug.background) {
893                 case V3D_DEBUG_BACKGROUND_WORLD:
894                         view3d_draw_background_world(scene, v3d, rv3d);
895                         break;
896                 case V3D_DEBUG_BACKGROUND_GRADIENT:
897                         view3d_draw_background_gradient();
898                         break;
899                 case V3D_DEBUG_BACKGROUND_NONE:
900                 default:
901                         view3d_draw_background_none();
902                         break;
903         }
904 }
905
906 /**
907  *
908  */
909 static void view3d_draw_render_solid_surfaces(const bContext *C, ARegion *ar, const bool run_screen_shaders)
910 {
911         /* TODO viewport */
912         draw_all_objects(C, ar, false, use_depth(C));
913 }
914
915 /**
916  *
917  */
918 static void view3d_draw_render_transparent_surfaces(const bContext *C)
919 {
920         /* TODO viewport */
921 }
922
923 /**
924  *
925  */
926 static void view3d_draw_post_draw(const bContext *C)
927 {
928         /* TODO viewport */
929 }
930
931 /* ******************** geometry overlay ***************** */
932
933 /**
934  * Front/back wire frames
935  */
936 static void view3d_draw_wire_plates(const bContext *C)
937 {
938         /* TODO viewport */
939 }
940
941 /**
942  * Special treatment for selected objects
943  */
944 static void view3d_draw_outline_plates(const bContext *C)
945 {
946         /* TODO viewport */
947 }
948
949 /* ******************** other elements ***************** */
950
951
952 #define DEBUG_GRID 0
953
954 static void gridline_range(double x0, double dx, double max, int* first_out, int* count_out)
955 {
956         /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
957         * x0 is gridline 0, the axis in screen space
958         * Area covers [0 .. max) pixels */
959
960         int first = (int)ceil(-x0 / dx);
961         int last = (int)floor((max - x0) / dx);
962
963         if (first <= last) {
964                 *first_out = first;
965                 *count_out = last - first + 1;
966         }
967         else {
968                 *first_out = 0;
969                 *count_out = 0;
970         }
971
972 #if DEBUG_GRID
973         printf("   first %d * dx = %f\n", first, x0 + first * dx);
974         printf("   last %d * dx = %f\n", last, x0 + last * dx);
975         printf("   count = %d\n", *count_out);
976 #endif
977 }
978
979 static int gridline_count(ARegion *ar, double x0, double y0, double dx)
980 {
981         /* x0 & y0 establish the "phase" of the grid within this 2D region
982         * dx is the frequency, shared by x & y directions
983         * pass in dx of smallest (highest precision) grid we want to draw */
984
985 #if DEBUG_GRID
986         printf("  %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx);
987 #endif
988
989         int first, x_ct, y_ct;
990
991         gridline_range(x0, dx, ar->winx, &first, &x_ct);
992         gridline_range(y0, dx, ar->winy, &first, &y_ct);
993
994         int total_ct = x_ct + y_ct;
995
996 #if DEBUG_GRID
997         printf("   %d + %d = %d gridlines\n", x_ct, y_ct, total_ct);
998 #endif
999
1000         return total_ct;
1001 }
1002
1003 static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
1004 {
1005         /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
1006         * always skip exact x0 & y0 axes; they will be drawn later in color
1007         *
1008         * set grid color once, just before the first line is drawn
1009         * it's harmless to set same color for every line, or every vertex
1010         * but if no lines are drawn, color must not be set! */
1011
1012 #if DEBUG_GRID
1013         printf("  %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod);
1014 #endif
1015
1016         const float x_max = (float)ar->winx;
1017         const float y_max = (float)ar->winy;
1018
1019         int first, ct;
1020         int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
1021         int lines_skipped_for_next_unit = 0;
1022
1023         /* draw vertical lines */
1024         gridline_range(x0, dx, x_max, &first, &ct);
1025
1026         for (int i = first; i < first + ct; ++i) {
1027                 if (i == 0)
1028                         continue;
1029                 else if (skip_mod && (i % skip_mod) == 0) {
1030                         ++lines_skipped_for_next_unit;
1031                         continue;
1032                 }
1033
1034                 if (x_ct == 0)
1035                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1036
1037                 float x = (float)(x0 + i * dx);
1038                 immVertex2f(pos, x, 0.0f);
1039                 immVertex2f(pos, x, y_max);
1040                 ++x_ct;
1041         }
1042
1043         /* draw horizontal lines */
1044         gridline_range(y0, dx, y_max, &first, &ct);
1045
1046         for (int i = first; i < first + ct; ++i) {
1047                 if (i == 0)
1048                         continue;
1049                 else if (skip_mod && (i % skip_mod) == 0) {
1050                         ++lines_skipped_for_next_unit;
1051                         continue;
1052                 }
1053
1054                 if (x_ct + y_ct == 0)
1055                         immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
1056
1057                 float y = (float)(y0 + i * dx);
1058                 immVertex2f(pos, 0.0f, y);
1059                 immVertex2f(pos, x_max, y);
1060                 ++y_ct;
1061         }
1062
1063 #if DEBUG_GRID
1064         int total_ct = x_ct + y_ct;
1065         printf("    %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit);
1066 #endif
1067
1068         return lines_skipped_for_next_unit > 0;
1069 }
1070
1071 #define GRID_MIN_PX_D 6.0
1072 #define GRID_MIN_PX_F 6.0f
1073
1074 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
1075 {
1076         RegionView3D *rv3d = ar->regiondata;
1077
1078 #if DEBUG_GRID
1079         printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy);
1080 #endif
1081
1082         double fx = rv3d->persmat[3][0];
1083         double fy = rv3d->persmat[3][1];
1084         double fw = rv3d->persmat[3][3];
1085
1086         const double wx = 0.5 * ar->winx;  /* use double precision to avoid rounding errors */
1087         const double wy = 0.5 * ar->winy;
1088
1089         double x = wx * fx / fw;
1090         double y = wy * fy / fw;
1091
1092         double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
1093         mul_m4_v4d(rv3d->persmat, vec4);
1094         fx = vec4[0];
1095         fy = vec4[1];
1096         fw = vec4[3];
1097
1098         double dx = fabs(x - wx * fx / fw);
1099         if (dx == 0) dx = fabs(y - wy * fy / fw);
1100
1101         x += wx;
1102         y += wy;
1103
1104         /* now x, y, and dx have their final values
1105         * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
1106         * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
1107
1108         glLineWidth(1.0f);
1109
1110 #if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
1111         glDepthMask(GL_FALSE);  /* disable write in zbuffer */
1112 #endif
1113
1114         VertexFormat* format = immVertexFormat();
1115         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
1116         unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
1117
1118         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
1119
1120         unsigned char col[3], col2[3];
1121         UI_GetThemeColor3ubv(TH_GRID, col);
1122
1123         if (unit->system) {
1124                 const void *usys;
1125                 int len;
1126
1127                 bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
1128
1129                 bool first = true;
1130
1131                 if (usys) {
1132                         int i = len;
1133                         while (i--) {
1134                                 double scalar = bUnit_GetScaler(usys, i);
1135
1136                                 double dx_scalar = dx * scalar / (double)unit->scale_length;
1137                                 if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
1138                                         /* very very small grid items are less useful when dealing with units */
1139                                         continue;
1140                                 }
1141
1142                                 if (first) {
1143                                         first = false;
1144
1145                                         /* Store the smallest drawn grid size units name so users know how big each grid cell is */
1146                                         *grid_unit = bUnit_GetNameDisplay(usys, i);
1147                                         rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
1148
1149                                         int gridline_ct = gridline_count(ar, x, y, dx_scalar);
1150                                         if (gridline_ct == 0)
1151                                                 goto drawgrid_cleanup; /* nothing to draw */
1152
1153                                         immBegin(GL_LINES, gridline_ct * 2);
1154                                 }
1155
1156                                 float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
1157                                 /* tweak to have the fade a bit nicer */
1158                                 blend_fac = (blend_fac * blend_fac) * 2.0f;
1159                                 CLAMP(blend_fac, 0.3f, 1.0f);
1160
1161                                 UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
1162
1163                                 const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
1164 #if DEBUG_GRID
1165                                 printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar);
1166                                 if (i > 0)
1167                                         printf("next unit is %d times larger\n", skip_mod);
1168                                 else
1169                                         printf("largest unit\n");
1170 #endif
1171                                 if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
1172                                         break;
1173                         }
1174                 }
1175         }
1176         else {
1177                 const double sublines = v3d->gridsubdiv;
1178                 const float  sublines_fl = v3d->gridsubdiv;
1179
1180                 int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
1181
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                                 if (dx < GRID_MIN_PX_D) {
1189                                         rv3d->gridview *= sublines_fl;
1190                                         dx *= sublines;
1191                                         grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
1192                                 }
1193                         }
1194                 }
1195                 else {
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)) {  /* start blending in */
1200                                         rv3d->gridview /= sublines_fl;
1201                                         dx /= sublines;
1202                                         if (dx > (GRID_MIN_PX_D * 10.0)) {
1203                                                 grids_to_draw = 1;
1204                                         }
1205                                 }
1206                         }
1207                 }
1208
1209                 int gridline_ct = gridline_count(ar, x, y, dx);
1210                 if (gridline_ct == 0)
1211                         goto drawgrid_cleanup; /* nothing to draw */
1212
1213                 immBegin(GL_LINES, gridline_ct * 2);
1214
1215                 if (grids_to_draw == 2) {
1216                         UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
1217                         if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
1218                                 drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
1219                 }
1220                 else if (grids_to_draw == 1) {
1221                         drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
1222                 }
1223         }
1224
1225         /* draw visible axes */
1226         /* horizontal line */
1227         if (0 <= y && y < ar->winy) {
1228                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
1229                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1230                 immVertex2f(pos, 0.0f, y);
1231                 immVertex2f(pos, (float)ar->winx, y);
1232         }
1233
1234         /* vertical line */
1235         if (0 <= x && x < ar->winx) {
1236                 UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
1237                 immAttrib3ub(color, col2[0], col2[1], col2[2]);
1238                 immVertex2f(pos, x, 0.0f);
1239                 immVertex2f(pos, x, (float)ar->winy);
1240         }
1241
1242         immEnd();
1243
1244 drawgrid_cleanup:
1245         immUnbindProgram();
1246
1247 #if 0 /* depth write is left enabled above */
1248         glDepthMask(GL_TRUE);  /* enable write in zbuffer */
1249 #endif
1250 }
1251
1252 #undef DEBUG_GRID
1253 #undef GRID_MIN_PX_D
1254 #undef GRID_MIN_PX_F
1255
1256 static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
1257 {
1258         /* draw only if there is something to draw */
1259         if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
1260                 /* draw how many lines?
1261                 * trunc(v3d->gridlines / 2) * 4
1262                 * + 2 for xy axes (possibly with special colors)
1263                 * + 1 for z axis (the only line not in xy plane)
1264                 * even v3d->gridlines are honored, odd rounded down */
1265                 const int gridlines = v3d->gridlines / 2;
1266                 const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
1267                 const float grid = gridlines * grid_scale;
1268
1269                 const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
1270
1271                 bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
1272                 bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
1273                 bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
1274
1275                 unsigned char col_grid[3], col_axis[3];
1276
1277                 glLineWidth(1.0f);
1278
1279                 UI_GetThemeColor3ubv(TH_GRID, col_grid);
1280
1281                 if (!write_depth)
1282                         glDepthMask(GL_FALSE);
1283
1284                 if (show_floor) {
1285                         const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
1286                         const int sublines = v3d->gridsubdiv;
1287
1288                         unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
1289
1290                         VertexFormat* format = immVertexFormat();
1291                         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
1292                         unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
1293
1294                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1295
1296                         immBegin(GL_LINES, vertex_ct);
1297
1298                         /* draw normal grid lines */
1299                         UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
1300
1301                         for (int a = 1; a <= gridlines; a++) {
1302                                 /* skip emphasised divider lines */
1303                                 if (a % sublines != 0) {
1304                                         const float line = a * grid_scale;
1305
1306                                         immAttrib3ubv(color, col_grid_light);
1307
1308                                         immVertex2f(pos, -grid, -line);
1309                                         immVertex2f(pos, +grid, -line);
1310                                         immVertex2f(pos, -grid, +line);
1311                                         immVertex2f(pos, +grid, +line);
1312
1313                                         immVertex2f(pos, -line, -grid);
1314                                         immVertex2f(pos, -line, +grid);
1315                                         immVertex2f(pos, +line, -grid);
1316                                         immVertex2f(pos, +line, +grid);
1317                                 }
1318                         }
1319
1320                         /* draw emphasised grid lines */
1321                         UI_GetThemeColor3ubv(TH_BACK, col_bg);
1322                         /* emphasise division lines lighter instead of darker, if background is darker than grid */
1323                         UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
1324                                 (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
1325                                 col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
1326
1327                         if (sublines <= gridlines) {
1328                                 immAttrib3ubv(color, col_grid_emphasise);
1329
1330                                 for (int a = sublines; a <= gridlines; a += sublines) {
1331                                         const float line = a * grid_scale;
1332
1333                                         immVertex2f(pos, -grid, -line);
1334                                         immVertex2f(pos, +grid, -line);
1335                                         immVertex2f(pos, -grid, +line);
1336                                         immVertex2f(pos, +grid, +line);
1337
1338                                         immVertex2f(pos, -line, -grid);
1339                                         immVertex2f(pos, -line, +grid);
1340                                         immVertex2f(pos, +line, -grid);
1341                                         immVertex2f(pos, +line, +grid);
1342                                 }
1343                         }
1344
1345                         /* draw X axis */
1346                         if (show_axis_x) {
1347                                 show_axis_x = false; /* drawing now, won't need to draw later */
1348                                 UI_make_axis_color(col_grid, col_axis, 'X');
1349                                 immAttrib3ubv(color, col_axis);
1350                         }
1351                         else
1352                                 immAttrib3ubv(color, col_grid_emphasise);
1353
1354                         immVertex2f(pos, -grid, 0.0f);
1355                         immVertex2f(pos, +grid, 0.0f);
1356
1357                         /* draw Y axis */
1358                         if (show_axis_y) {
1359                                 show_axis_y = false; /* drawing now, won't need to draw later */
1360                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1361                                 immAttrib3ubv(color, col_axis);
1362                         }
1363                         else
1364                                 immAttrib3ubv(color, col_grid_emphasise);
1365
1366                         immVertex2f(pos, 0.0f, -grid);
1367                         immVertex2f(pos, 0.0f, +grid);
1368
1369                         immEnd();
1370                         immUnbindProgram();
1371
1372                         /* done with XY plane */
1373                 }
1374
1375                 if (show_axis_x || show_axis_y || show_axis_z) {
1376                         /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
1377
1378                         VertexFormat* format = immVertexFormat();
1379                         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
1380                         unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
1381
1382                         immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
1383                         immBegin(GL_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
1384
1385                         if (show_axis_x) {
1386                                 UI_make_axis_color(col_grid, col_axis, 'X');
1387                                 immAttrib3ubv(color, col_axis);
1388                                 immVertex3f(pos, -grid, 0.0f, 0.0f);
1389                                 immVertex3f(pos, +grid, 0.0f, 0.0f);
1390                         }
1391
1392                         if (show_axis_y) {
1393                                 UI_make_axis_color(col_grid, col_axis, 'Y');
1394                                 immAttrib3ubv(color, col_axis);
1395                                 immVertex3f(pos, 0.0f, -grid, 0.0f);
1396                                 immVertex3f(pos, 0.0f, +grid, 0.0f);
1397                         }
1398
1399                         if (show_axis_z) {
1400                                 UI_make_axis_color(col_grid, col_axis, 'Z');
1401                                 immAttrib3ubv(color, col_axis);
1402                                 immVertex3f(pos, 0.0f, 0.0f, -grid);
1403                                 immVertex3f(pos, 0.0f, 0.0f, +grid);
1404                         }
1405
1406                         immEnd();
1407                         immUnbindProgram();
1408                 }
1409
1410                 if (!write_depth)
1411                         glDepthMask(GL_TRUE);
1412         }
1413 }
1414
1415 /** could move this elsewhere, but tied into #ED_view3d_grid_scale */
1416 float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
1417 {
1418         /* apply units */
1419         if (scene->unit.system) {
1420                 const void *usys;
1421                 int len;
1422
1423                 bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
1424
1425                 if (usys) {
1426                         int i = bUnit_GetBaseUnit(usys);
1427                         if (grid_unit)
1428                                 *grid_unit = bUnit_GetNameDisplay(usys, i);
1429                         return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
1430                 }
1431         }
1432
1433         return 1.0f;
1434 }
1435
1436 float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
1437 {
1438         return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
1439 }
1440
1441 /**
1442  *
1443  */
1444 static void view3d_draw_grid(const bContext *C, ARegion *ar)
1445 {
1446         /* TODO viewport
1447          * Missing is the flags to check whether to draw it
1448          * for now now we are using the flags in v3d itself.
1449          *
1450          * Also for now always assume depth is there, so we
1451          * draw on top of it.
1452          */
1453         Scene *scene = CTX_data_scene(C);
1454         View3D *v3d = CTX_wm_view3d(C);
1455         RegionView3D *rv3d = ar->regiondata;
1456
1457         const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
1458         const char *grid_unit = NULL;
1459
1460         /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
1461          * objects if done last
1462          * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
1463          */
1464         rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
1465
1466         glEnable(GL_DEPTH_TEST);
1467         glDepthMask(GL_FALSE); /* read & test depth, but don't alter it. TODO: separate UI depth buffer */
1468
1469         if (!draw_floor) {
1470                 ED_region_pixelspace(ar);
1471                 *(&grid_unit) = NULL;  /* drawgrid need this to detect/affect smallest valid unit... */
1472                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
1473
1474                 glMatrixMode(GL_PROJECTION);
1475                 glLoadMatrixf(rv3d->winmat);
1476                 glMatrixMode(GL_MODELVIEW);
1477                 glLoadMatrixf(rv3d->viewmat);
1478         }
1479         else {
1480                 drawfloor(scene, v3d, &grid_unit, false);
1481         }
1482
1483         glDisable(GL_DEPTH_TEST);
1484 }
1485
1486 /* ******************** non-meshes ***************** */
1487
1488 static void view3d_draw_non_mesh(
1489 Scene *scene, Object *ob, Base *base, View3D *v3d,
1490 RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
1491 {
1492         glMatrixMode(GL_PROJECTION);
1493         glPushMatrix();
1494         glMatrixMode(GL_MODELVIEW);
1495         glPushMatrix();
1496
1497         /* multiply view with object matrix.
1498         * local viewmat and persmat, to calculate projections */
1499         ED_view3d_init_mats_rv3d_gl(ob, rv3d);
1500
1501         switch (ob->type) {
1502                 case OB_MESH:
1503                 case OB_FONT:
1504                 case OB_CURVE:
1505                 case OB_SURF:
1506                 case OB_MBALL:
1507                         if (is_boundingbox) {
1508                                 draw_bounding_volume(ob, ob->boundtype);
1509                         }
1510                         break;
1511                 case OB_EMPTY:
1512                         drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
1513                         break;
1514                 case OB_LAMP:
1515                         drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, ob == OBACT);
1516                         break;
1517                 case OB_CAMERA:
1518                         drawcamera(scene, v3d, rv3d, base, DRAW_CONSTCOLOR, color);
1519                         break;
1520                 case OB_SPEAKER:
1521                         drawspeaker(color);
1522                         break;
1523                 case OB_LATTICE:
1524                         /* TODO */
1525                         break;
1526                 case OB_ARMATURE:
1527                         /* TODO */
1528                         break;
1529                 default:
1530                 /* TODO Viewport: handle the other cases*/
1531                         break;
1532         }
1533
1534         if (ob->rigidbody_object) {
1535                 draw_rigidbody_shape(ob);
1536         }
1537
1538         ED_view3d_clear_mats_rv3d(rv3d);
1539
1540         glMatrixMode(GL_PROJECTION);
1541         glPopMatrix();
1542         glMatrixMode(GL_MODELVIEW);
1543         glPopMatrix();
1544 }
1545
1546 /* ******************** info ***************** */
1547
1548 /**
1549 * Render and camera border
1550 */
1551 static void view3d_draw_border(const bContext *C, ARegion *ar)
1552 {
1553         Scene *scene = CTX_data_scene(C);
1554         RegionView3D *rv3d = ar->regiondata;
1555         View3D *v3d = CTX_wm_view3d(C);
1556
1557         if (rv3d->persp == RV3D_CAMOB) {
1558                 drawviewborder(scene, ar, v3d);
1559         }
1560         else if (v3d->flag2 & V3D_RENDER_BORDER) {
1561                 drawrenderborder(ar, v3d);
1562         }
1563 }
1564
1565 /**
1566 * Grease Pencil
1567 */
1568 static void view3d_draw_grease_pencil(const bContext *C)
1569 {
1570         /* TODO viewport */
1571 }
1572
1573 /* ******************** view loop ***************** */
1574
1575 /**
1576  * Set the correct matrices
1577  */
1578 static void view3d_draw_setup_view(const bContext *C, ARegion *ar)
1579 {
1580         Scene *scene = CTX_data_scene(C);
1581         View3D *v3d = CTX_wm_view3d(C);
1582         RegionView3D *rv3d = ar->regiondata;
1583
1584         /* setup the view matrix */
1585         if (view3d_stereo3d_active(C, scene, v3d, rv3d))
1586                 view3d_stereo3d_setup(scene, v3d, ar);
1587         else
1588                 view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
1589 }
1590
1591 static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth)
1592 {
1593         Scene *scene = CTX_data_scene(C);
1594         View3D *v3d = CTX_wm_view3d(C);
1595         Base *base;
1596
1597         if (only_depth)
1598                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1599
1600         if (only_depth || use_depth) {
1601                 glEnable(GL_DEPTH_TEST);
1602                 glDepthFunc(GL_LESS);
1603                 glDepthMask(GL_TRUE);
1604                 v3d->zbuf = true;
1605         }
1606
1607         for (base = scene->base.first; base; base = base->next) {
1608                 if (v3d->lay & base->lay) {
1609                         /* dupli drawing */
1610                         if (base->object->transflag & OB_DUPLI)
1611                                 draw_dupli_objects(scene, ar, v3d, base);
1612
1613                         draw_object(scene, ar, v3d, base, 0);
1614                 }
1615         }
1616
1617         if (only_depth)
1618                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1619
1620         if (only_depth || use_depth) {
1621                 glDisable(GL_DEPTH_TEST);
1622                 v3d->zbuf = false;
1623         }
1624 }
1625
1626 /**
1627  * Draw only the scene depth buffer
1628  */
1629 static void draw_depth_buffer(const bContext *C, ARegion *ar)
1630 {
1631         draw_all_objects(C, ar, true, true);
1632 }
1633
1634 /**
1635  * Required if the shaders need it or external engines
1636  * (e.g., Cycles requires depth buffer handled separately).
1637  */
1638 static void view3d_draw_prerender_buffers(const bContext *C, ARegion *ar, DrawData *draw_data)
1639 {
1640         View3D *v3d = CTX_wm_view3d(C);
1641
1642         /* TODO viewport */
1643         if (draw_data->is_render && ((!draw_data->clip_border) || (v3d->drawtype <= OB_WIRE))) {
1644                 draw_depth_buffer(C, ar);
1645         }
1646 }
1647
1648 /**
1649  * Draw all the plates that will fill the RGBD buffer
1650  */
1651 static void view3d_draw_solid_plates(const bContext *C, ARegion *ar, DrawData *draw_data)
1652 {
1653         Scene *scene = CTX_data_scene(C);
1654         View3D *v3d = CTX_wm_view3d(C);
1655
1656         /* realtime plates */
1657         if ((!draw_data->is_render) || draw_data->clip_border) {
1658                 view3d_draw_background(C);
1659                 view3d_draw_render_solid_surfaces(C, ar, true);
1660                 view3d_draw_render_transparent_surfaces(C);
1661                 view3d_draw_post_draw(C);
1662         }
1663
1664         /* offline plates*/
1665         if (draw_data->is_render) {
1666                 view3d_draw_render_draw(C, scene, ar, v3d, draw_data->clip_border, &draw_data->border_rect);
1667         }
1668
1669 #if VIEW3D_DRAW_DEBUG
1670         view3d_draw_debug_post_solid(C, ar, draw_data);
1671 #endif
1672 }
1673
1674 /**
1675  * Wires, outline, ...
1676  */
1677 static void view3d_draw_geometry_overlay(const bContext *C)
1678 {
1679         view3d_draw_wire_plates(C);
1680         view3d_draw_outline_plates(C);
1681 }
1682
1683 /* drawing cameras, lamps, ... */
1684 static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
1685 {
1686         /* TODO viewport
1687          * for now we draw them all, in the near future
1688          * we filter them based on the plates/layers
1689          */
1690         Scene *scene = CTX_data_scene(C);
1691         View3D *v3d = CTX_wm_view3d(C);
1692         RegionView3D *rv3d = ar->regiondata;
1693         Object *ob_act = CTX_data_active_object(C);
1694         Base *base;
1695
1696         bool is_boundingbox = ((v3d->drawtype == OB_BOUNDBOX) ||
1697                                 ((v3d->drawtype == OB_RENDER) && (v3d->prev_drawtype == OB_BOUNDBOX)));
1698
1699         unsigned char ob_wire_col[4];            /* dont initialize this */
1700
1701         glEnable(GL_DEPTH_TEST);
1702         glDepthMask(GL_TRUE);
1703         /* TODO Viewport
1704          * we are already temporarily writing to zbuffer in draw_object()
1705          * for now let's avoid writing again to zbuffer to prevent glitches
1706          */
1707
1708         for (base = scene->base.first; base; base = base->next) {
1709                 if (v3d->lay & base->lay) {
1710                         Object *ob = base->object;
1711
1712                         draw_object_wire_color(scene, base, ob_wire_col);
1713                         view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, is_boundingbox, ob_wire_col);
1714                 }
1715         }
1716
1717         glDepthMask(GL_FALSE);
1718         glDisable(GL_DEPTH_TEST);
1719 }
1720
1721 /**
1722 * Parent lines, grid, ...
1723 */
1724 static void view3d_draw_other_elements(const bContext *C, ARegion *ar)
1725 {
1726         /* TODO viewport */
1727         view3d_draw_grid(C, ar);
1728 }
1729
1730 /**
1731  * Paint brushes, armatures, ...
1732  */
1733 static void view3d_draw_tool_ui(const bContext *C)
1734 {
1735         /* TODO viewport */
1736 }
1737
1738 /**
1739  * Blueprint images
1740  */
1741 static void view3d_draw_reference_images(const bContext *C)
1742 {
1743         /* TODO viewport */
1744 }
1745
1746 /**
1747 * 3D manipulators
1748 */
1749 static void view3d_draw_manipulator(const bContext *C)
1750 {
1751         View3D *v3d = CTX_wm_view3d(C);
1752         v3d->zbuf = false;
1753         BIF_draw_manipulator(C);
1754 }
1755
1756 /**
1757 * Information drawn on top of the solid plates and composed data
1758 */
1759 static void view3d_draw_region_info(const bContext *C, ARegion *ar)
1760 {
1761         rcti rect;
1762
1763         /* correct projection matrix */
1764         ED_region_pixelspace(ar);
1765
1766         /* local coordinate visible rect inside region, to accomodate overlapping ui */
1767         ED_region_visible_rect(ar, &rect);
1768
1769         view3d_draw_border(C, ar);
1770         view3d_draw_grease_pencil(C);
1771
1772         /* TODO viewport */
1773 }
1774
1775 /**
1776  * This could run once per view, or even in parallel
1777  * for each of them. What is a "view"?
1778  * - a viewport with the camera elsewhere
1779  * - left/right stereo
1780  * - panorama / fisheye individual cubemap faces
1781  */
1782 static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data)
1783 {
1784         /* TODO - Technically this should be drawn to a few FBO, so we can handle
1785          * compositing better, but for now this will get the ball rolling (dfelinto) */
1786
1787         view3d_draw_setup_view(C, ar);
1788         view3d_draw_prerender_buffers(C, ar, draw_data);
1789         view3d_draw_solid_plates(C, ar, draw_data);
1790         view3d_draw_geometry_overlay(C);
1791         view3d_draw_non_meshes(C, ar);
1792         view3d_draw_other_elements(C, ar);
1793         view3d_draw_tool_ui(C);
1794         view3d_draw_reference_images(C);
1795         view3d_draw_manipulator(C);
1796         view3d_draw_region_info(C, ar);
1797
1798 #if VIEW3D_DRAW_DEBUG
1799         view3d_draw_debug(C, ar, draw_data);
1800 #endif
1801 }
1802
1803 void view3d_main_region_draw(const bContext *C, ARegion *ar)
1804 {
1805         View3D *v3d = CTX_wm_view3d(C);
1806         RegionView3D *rv3d = ar->regiondata;
1807
1808         if (IS_VIEWPORT_LEGACY(v3d)) {
1809                 view3d_main_region_draw_legacy(C, ar);
1810                 return;
1811         }
1812
1813         if (!rv3d->viewport)
1814                 rv3d->viewport = GPU_viewport_create();
1815
1816         /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
1817          * before we even call the drawing routine, but let's move on for now (dfelinto)
1818          * but this is a provisory way to start seeing things in the viewport */
1819         DrawData draw_data;
1820         view3d_draw_data_init(C, ar, rv3d, &draw_data);
1821         view3d_draw_view(C, ar, &draw_data);
1822
1823         v3d->flag |= V3D_INVALID_BACKBUF;
1824 }
1825
1826 /* ******************** legacy interface ***************** */
1827 /**
1828  * This will be removed once the viewport gets replaced
1829  * meanwhile it should keep the old viewport working.
1830  */
1831
1832 void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
1833 {
1834         drawgrid(unit, ar, v3d, grid_unit);
1835 }
1836
1837 void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
1838 {
1839         drawfloor(scene, v3d, grid_unit, write_depth);
1840 }
1841
1842 void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
1843 {
1844         view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
1845 }
1846
1847 bool VP_legacy_view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
1848 {
1849         return view3d_stereo3d_active(C, scene, v3d, rv3d);
1850 }
1851
1852 void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
1853 {
1854         view3d_stereo3d_setup(scene, v3d, ar);
1855 }
1856
1857 bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
1858 {
1859         return use_depth_doit(scene, v3d);
1860 }
1861
1862 void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
1863 {
1864         drawviewborder(scene, ar, v3d);
1865 }
1866
1867 void VP_drawrenderborder(ARegion *ar, View3D *v3d)
1868 {
1869         drawrenderborder(ar, v3d);
1870 }
1871
1872 void VP_view3d_draw_background_none(void)
1873 {
1874         view3d_draw_background_none();
1875 }
1876
1877 void VP_view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
1878 {
1879         view3d_draw_background_world(scene, v3d, rv3d);
1880 }