Blender V4.5
wm_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstdlib>
12#include <cstring>
13
14#include "DNA_camera_types.h"
15#include "DNA_listBase.h"
16#include "DNA_object_types.h"
17#include "DNA_screen_types.h"
18#include "DNA_space_types.h"
19#include "DNA_userdef_types.h"
20#include "DNA_view3d_types.h"
22
23#include "MEM_guardedalloc.h"
24
25#include "BLI_listbase.h"
26#include "BLI_math_matrix.h"
27#include "BLI_math_vector.h"
29#include "BLI_rect.h"
30#include "BLI_utildefines.h"
31
32#include "BKE_context.hh"
33#include "BKE_image.hh"
34#include "BKE_scene.hh"
35#include "BKE_screen.hh"
36
37#include "GHOST_C-api.h"
38
39#include "ED_node.hh"
40#include "ED_screen.hh"
41#include "ED_view3d.hh"
42
43#include "GPU_batch_presets.hh"
44#include "GPU_capabilities.hh"
45#include "GPU_context.hh"
46#include "GPU_debug.hh"
47#include "GPU_framebuffer.hh"
48#include "GPU_immediate.hh"
49#include "GPU_matrix.hh"
50#include "GPU_state.hh"
51#include "GPU_texture.hh"
52#include "GPU_viewport.hh"
53
54#include "RE_engine.h"
55
56#include "WM_api.hh"
57#include "WM_toolsystem.hh"
58#include "WM_types.hh"
59#include "wm.hh"
60#include "wm_draw.hh"
61#include "wm_event_system.hh"
62#include "wm_surface.hh"
63#include "wm_window.hh"
64
65#include "UI_resources.hh"
66
67#ifdef WITH_OPENSUBDIV
68# include "BKE_subsurf.hh"
69#endif
70
71/* -------------------------------------------------------------------- */
74
79{
81 GHOST_TGrabCursorMode mode_dummy;
82 GHOST_TAxisFlag wrap_axis_dummy;
83 int bounds[4] = {0};
84 bool use_software_cursor_dummy = false;
85 GHOST_GetCursorGrabState(static_cast<GHOST_WindowHandle>(win->ghostwin),
86 &mode_dummy,
87 &wrap_axis_dummy,
88 bounds,
89 &use_software_cursor_dummy);
90 if ((bounds[0] != bounds[2]) || (bounds[1] != bounds[3])) {
91 return true;
92 }
93 }
94 return false;
95}
96
98
99/* -------------------------------------------------------------------- */
102
103static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
104{
106 wmWindow *win = CTX_wm_window(C);
108
109 /* Don't draw paint cursors with locked interface. Painting is not possible
110 * then, and cursor drawing can use scene data that another thread may be
111 * modifying. */
112 if (wm->runtime->is_interface_locked) {
113 return;
114 }
115
116 if (!region->runtime->visible || region != screen->active_region) {
117 return;
118 }
119
121 if ((pc->space_type != SPACE_TYPE_ANY) && (area->spacetype != pc->space_type)) {
122 continue;
123 }
124
125 if (!ELEM(pc->region_type, RGN_TYPE_ANY, region->regiontype)) {
126 continue;
127 }
128
129 if (pc->poll == nullptr || pc->poll(C)) {
130 UI_SetTheme(area->spacetype, region->regiontype);
131
132 /* Prevent drawing outside region. */
133 GPU_scissor_test(true);
134 GPU_scissor(region->winrct.xmin,
135 region->winrct.ymin,
136 BLI_rcti_size_x(&region->winrct) + 1,
137 BLI_rcti_size_y(&region->winrct) + 1);
138 /* Reading the cursor location from the operating-system while the cursor is grabbed
139 * conflicts with grabbing logic that hides the cursor, then keeps it centered to accumulate
140 * deltas without it escaping from the window. In this case we never want to show the actual
141 * cursor coordinates so limit reading the cursor location to when the cursor is grabbed and
142 * wrapping in a region since this is the case when it would otherwise attempt to draw the
143 * cursor outside the view/window. See: #102792. */
144 const int *xy = win->eventstate->xy;
145 int xy_buf[2];
148 wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
149 {
150 xy = xy_buf;
151 }
152
153 pc->draw(C, xy, win->eventstate->tablet.tilt, pc->customdata);
154 GPU_scissor_test(false);
155 }
156 }
157}
158
160
161/* -------------------------------------------------------------------- */
167
171static struct {
172 int8_t enabled;
173 int winid;
174 int xy[2];
176 /*enabled*/ -1,
177 /*winid*/ -1,
179
186
188{
189 if (UNLIKELY(g_software_cursor.enabled == -1)) {
191 }
192 return g_software_cursor.enabled;
193}
194
195static bool wm_software_cursor_needed_for_window(const wmWindow *win, GrabState *grab_state)
196{
198 if (GHOST_GetCursorVisibility(static_cast<GHOST_WindowHandle>(win->ghostwin))) {
199 /* NOTE: The value in `win->grabcursor` can't be used as it
200 * doesn't always match GHOST's value in the case of tablet events. */
201 bool use_software_cursor;
202 GHOST_GetCursorGrabState(static_cast<GHOST_WindowHandle>(win->ghostwin),
203 &grab_state->mode,
204 &grab_state->wrap_axis,
205 grab_state->bounds,
206 &use_software_cursor);
207 if (use_software_cursor) {
208 return true;
209 }
210 }
211 return false;
212}
213
215{
216 return (g_software_cursor.winid != win->winid) ||
217 (g_software_cursor.xy[0] != win->eventstate->xy[0]) ||
218 (g_software_cursor.xy[1] != win->eventstate->xy[1]);
219}
220
222{
223
224 g_software_cursor.winid = win->winid;
225 g_software_cursor.xy[0] = win->eventstate->xy[0];
226 g_software_cursor.xy[1] = win->eventstate->xy[1];
227}
228
230{
231 g_software_cursor.winid = -1;
232 g_software_cursor.xy[0] = -1;
233 g_software_cursor.xy[1] = -1;
234}
235
237{
238 if (g_software_cursor.winid == win->winid) {
240 }
241}
242
243static void wm_software_cursor_draw_bitmap(const int event_xy[2],
244 const GHOST_CursorBitmapRef *bitmap)
245{
247
248 float gl_matrix[4][4];
250 GPUTexture *texture = GPU_texture_create_2d(
251 "softeare_cursor", bitmap->data_size[0], bitmap->data_size[1], 1, GPU_RGBA8, usage, nullptr);
254
256
257 /* The DPI as a scale without the UI scale preference. */
258 const float system_scale = UI_SCALE_FAC / U.ui_scale;
259 const int scale = std::max(1, round_fl_to_int(system_scale));
260
261 unit_m4(gl_matrix);
262
263 gl_matrix[3][0] = event_xy[0] - (bitmap->hot_spot[0] * scale);
264 gl_matrix[3][1] = event_xy[1] - ((bitmap->data_size[1] - bitmap->hot_spot[1]) * scale);
265
266 gl_matrix[0][0] = bitmap->data_size[0] * scale;
267 gl_matrix[1][1] = bitmap->data_size[1] * scale;
268
269 GPU_matrix_mul(gl_matrix);
270
271 GPUVertFormat *imm_format = immVertexFormat();
273 uint texCoord = GPU_vertformat_attr_add(
274 imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
275
276 /* Use 3D image for correct display of planar tracked images. */
278
279 immBindTexture("image", texture);
280
282
283 immAttr2f(texCoord, 0.0f, 1.0f);
284 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
285
286 immAttr2f(texCoord, 1.0f, 1.0f);
287 immVertex3f(pos, 1.0f, 0.0f, 0.0f);
288
289 immAttr2f(texCoord, 1.0f, 0.0f);
290 immVertex3f(pos, 1.0f, 1.0f, 0.0f);
291
292 immAttr2f(texCoord, 0.0f, 0.0f);
293 immVertex3f(pos, 0.0f, 1.0f, 0.0f);
294
295 immEnd();
296
298
302
304}
305
306static void wm_software_cursor_draw_crosshair(const int event_xy[2])
307{
308 /* Draw a primitive cross-hair cursor.
309 * NOTE: the `win->cursor` could be used for drawing although it's complicated as some cursors
310 * are set by the operating-system, where the pixel information isn't easily available. */
311
312 /* The DPI as a scale without the UI scale preference. */
313 const float system_scale = UI_SCALE_FAC / U.ui_scale;
314 /* The cursor scaled by the "default" size. */
315 const float cursor_scale = float(WM_cursor_preferred_logical_size()) /
317 const float unit = max_ff(system_scale * cursor_scale, 1.0f);
320
321 immUniformColor4f(1, 1, 1, 1);
322 {
323 const int ofs_line = (8 * unit);
324 const int ofs_size = (2 * unit);
326 event_xy[0] - ofs_line,
327 event_xy[1] - ofs_size,
328 event_xy[0] + ofs_line,
329 event_xy[1] + ofs_size);
331 event_xy[0] - ofs_size,
332 event_xy[1] - ofs_line,
333 event_xy[0] + ofs_size,
334 event_xy[1] + ofs_line);
335 }
336 immUniformColor4f(0, 0, 0, 1);
337 {
338 const int ofs_line = (7 * unit);
339 const int ofs_size = (1 * unit);
341 event_xy[0] - ofs_line,
342 event_xy[1] - ofs_size,
343 event_xy[0] + ofs_line,
344 event_xy[1] + ofs_size);
346 event_xy[0] - ofs_size,
347 event_xy[1] - ofs_line,
348 event_xy[0] + ofs_size,
349 event_xy[1] + ofs_line);
350 }
352}
353
354static void wm_software_cursor_draw(wmWindow *win, const GrabState *grab_state)
355{
356 int event_xy[2] = {UNPACK2(win->eventstate->xy)};
357
358 if (grab_state->wrap_axis & GHOST_kAxisX) {
359 const int min = grab_state->bounds[0];
360 const int max = grab_state->bounds[2];
361 if (min != max) {
362 event_xy[0] = mod_i(event_xy[0] - min, max - min) + min;
363 }
364 }
365 if (grab_state->wrap_axis & GHOST_kAxisY) {
366 const int height = WM_window_native_pixel_y(win);
367 const int min = height - grab_state->bounds[1];
368 const int max = height - grab_state->bounds[3];
369 if (min != max) {
370 event_xy[1] = mod_i(event_xy[1] - max, min - max) + max;
371 }
372 }
373
374 GHOST_CursorBitmapRef bitmap = {nullptr};
375 if (GHOST_GetCursorBitmap(static_cast<GHOST_WindowHandle>(win->ghostwin), &bitmap) ==
377 {
378 wm_software_cursor_draw_bitmap(event_xy, &bitmap);
379 }
380 else {
382 }
383}
384
386
387/* -------------------------------------------------------------------- */
390
391static void wm_region_draw_overlay(bContext *C, const ScrArea *area, ARegion *region)
392{
393 const wmWindow *win = CTX_wm_window(C);
394
395 wmViewport(&region->winrct);
396 UI_SetTheme(area->spacetype, region->regiontype);
397 region->runtime->type->draw_overlay(C, region);
398 wmWindowViewport(win);
399}
400
402
403/* -------------------------------------------------------------------- */
406
408 ScrArea *area,
409 ARegion *region,
410 eStereoViews sview)
411{
412 /* We could detect better when stereo is actually needed, by inspecting the
413 * image in the image editor and sequencer. */
415 return false;
416 }
417
418 switch (area->spacetype) {
419 case SPACE_IMAGE: {
420 if (region->regiontype == RGN_TYPE_WINDOW) {
421 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
422 sima->iuser.multiview_eye = sview;
423 return true;
424 }
425 break;
426 }
427 case SPACE_VIEW3D: {
428 if (region->regiontype == RGN_TYPE_WINDOW) {
429 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
430 if (v3d->camera && v3d->camera->type == OB_CAMERA) {
431 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
432 RenderEngine *engine = rv3d->view_render ? RE_view_engine_get(rv3d->view_render) :
433 nullptr;
434 if (engine && !(engine->type->flag & RE_USE_STEREO_VIEWPORT)) {
435 return false;
436 }
437
438 Camera *cam = static_cast<Camera *>(v3d->camera->data);
439 CameraBGImage *bgpic = static_cast<CameraBGImage *>(cam->bg_images.first);
440 v3d->multiview_eye = sview;
441 if (bgpic) {
442 bgpic->iuser.multiview_eye = sview;
443 }
444 return true;
445 }
446 }
447 break;
448 }
449 case SPACE_NODE: {
450 if (region->regiontype == RGN_TYPE_WINDOW) {
451 SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first);
452 if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
453 Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
454 ima->eye = sview;
455 return true;
456 }
457 }
458 break;
459 }
460 case SPACE_SEQ: {
461 SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
462 sseq->multiview_eye = sview;
463
464 if (region->regiontype == RGN_TYPE_PREVIEW) {
465 return true;
466 }
467 }
468 }
469
470 return false;
471}
472
474 ScrArea *area,
475 ARegion *region,
476 bool tag_redraw)
477{
478 if (region->runtime->gizmo_map == nullptr) {
479 return;
480 }
481
482 wmGizmoMap *gzmap = region->runtime->gizmo_map;
484 if (tag_redraw && (gzgroup->type->flag & WM_GIZMOGROUPTYPE_VR_REDRAWS)) {
485 ScrArea *ctx_area = CTX_wm_area(C);
486 ARegion *ctx_region = CTX_wm_region(C);
487
488 CTX_wm_area_set(C, area);
489 CTX_wm_region_set(C, region);
490
491 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
493 }
494
495 /* Reset. */
496 CTX_wm_area_set(C, ctx_area);
497 CTX_wm_region_set(C, ctx_region);
498 }
499
500 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
501 if (gz->do_draw) {
502 if (tag_redraw) {
504 }
505 gz->do_draw = false;
506 }
507 }
508 }
509}
510
511static void wm_region_test_render_do_draw(const Scene *scene,
512 Depsgraph *depsgraph,
513 ScrArea *area,
514 ARegion *region)
515{
516 /* Tag region for redraw from render engine preview running inside of it. */
517 if (area->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) {
518 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
519 RenderEngine *engine = rv3d->view_render ? RE_view_engine_get(rv3d->view_render) : nullptr;
520 GPUViewport *viewport = WM_draw_region_get_viewport(region);
521
522 if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
523 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
524 rcti border_rect;
525
526 /* Do partial redraw when possible. */
527 if (ED_view3d_calc_render_border(scene, depsgraph, v3d, region, &border_rect)) {
528 ED_region_tag_redraw_partial(region, &border_rect, false);
529 }
530 else {
532 }
533
534 engine->flag &= ~RE_ENGINE_DO_DRAW;
535 }
536 else if (viewport && GPU_viewport_do_update(viewport)) {
538 }
539 }
540}
541
542#ifdef WITH_XR_OPENXR
543static void wm_region_test_xr_do_draw(const wmWindowManager *wm,
544 const ScrArea *area,
545 ARegion *region)
546{
547 if ((area->spacetype == SPACE_VIEW3D) && (region->regiontype == RGN_TYPE_WINDOW)) {
548 if (ED_view3d_is_region_xr_mirror_active(
549 wm, static_cast<const View3D *>(area->spacedata.first), region))
550 {
552 }
553 }
554}
555#endif
556
557static bool wm_region_use_viewport_by_type(short space_type, short region_type)
558{
559 return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE) &&
560 region_type == RGN_TYPE_WINDOW) ||
561 ((space_type == SPACE_SEQ) && ELEM(region_type, RGN_TYPE_PREVIEW, RGN_TYPE_WINDOW));
562}
563
565{
567}
568
569static const char *wm_area_name(ScrArea *area)
570{
571#define SPACE_NAME(space) \
572 case space: \
573 return #space;
574
575 switch (area->spacetype) {
595 default:
596 return "Unknown Space";
597 }
598}
599
601
602/* -------------------------------------------------------------------- */
607
610
611 void (*draw)(const wmWindow *win, void *customdata);
613};
614
616 void (*draw)(const wmWindow *win, void *customdata),
617 void *customdata)
618{
619 WindowDrawCB *wdc = MEM_callocN<WindowDrawCB>("WindowDrawCB");
620
621 BLI_addtail(&win->drawcalls, wdc);
622 wdc->draw = draw;
623 wdc->customdata = customdata;
624
625 return wdc;
626}
627
628void WM_draw_cb_exit(wmWindow *win, void *handle)
629{
630 LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) {
631 if (wdc == (WindowDrawCB *)handle) {
632 BLI_remlink(&win->drawcalls, wdc);
633 MEM_freeN(wdc);
634 return;
635 }
636 }
637}
638
640{
641 LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) {
642 wdc->draw(win, wdc->customdata);
643 }
644}
645
647
648/* -------------------------------------------------------------------- */
656
658{
659 if (region->runtime->draw_buffer) {
660 if (region->runtime->draw_buffer->viewport) {
661 GPU_viewport_free(region->runtime->draw_buffer->viewport);
662 }
663 if (region->runtime->draw_buffer->offscreen) {
664 GPU_offscreen_free(region->runtime->draw_buffer->offscreen);
665 }
666
667 MEM_freeN(region->runtime->draw_buffer);
668 region->runtime->draw_buffer = nullptr;
669 }
670}
671
673{
674 /* Setup offscreen color texture for drawing. */
675 GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
676
677 /* No mipmaps or filtering. */
678 GPU_texture_mipmap_mode(texture, false, false);
679}
680
682{
683 bool use_hdr = false;
684 if (scene && ((scene->view_settings.flag & COLORMANAGE_VIEW_USE_HDR) != 0)) {
685 use_hdr = GPU_hdr_support();
686 }
687 eGPUTextureFormat desired_format = (use_hdr) ? GPU_RGBA16F : GPU_RGBA8;
688 return desired_format;
689}
690
692 ARegion *region,
693 bool stereo,
694 bool use_viewport)
695{
696
697 /* Determine desired offscreen format depending on HDR availability. */
698 eGPUTextureFormat desired_format = get_hdr_framebuffer_format(scene);
699
700 if (region->runtime->draw_buffer) {
701 if (region->runtime->draw_buffer->stereo != stereo) {
702 /* Free draw buffer on stereo changes. */
704 }
705 else {
706 /* Free offscreen buffer on size changes. Viewport auto resizes. */
707 GPUOffScreen *offscreen = region->runtime->draw_buffer->offscreen;
708 if (offscreen && (GPU_offscreen_width(offscreen) != region->winx ||
709 GPU_offscreen_height(offscreen) != region->winy ||
710 GPU_offscreen_format(offscreen) != desired_format))
711 {
713 }
714 }
715 }
716
717 if (!region->runtime->draw_buffer) {
718 if (use_viewport) {
719 /* Allocate viewport which includes an off-screen buffer with depth multi-sample, etc. */
720 region->runtime->draw_buffer = MEM_callocN<wmDrawBuffer>("wmDrawBuffer");
721 region->runtime->draw_buffer->viewport = stereo ? GPU_viewport_stereo_create() :
723 }
724 else {
725 /* Allocate off-screen buffer if it does not exist. This one has no
726 * depth or multi-sample buffers. 3D view creates its own buffers with
727 * the data it needs. */
728 GPUOffScreen *offscreen = GPU_offscreen_create(region->winx,
729 region->winy,
730 false,
731 desired_format,
733 true,
734 nullptr);
735 if (!offscreen) {
736 WM_global_report(RPT_ERROR, "Region could not be drawn!");
737 return;
738 }
739
741
742 region->runtime->draw_buffer = MEM_callocN<wmDrawBuffer>("wmDrawBuffer");
743 region->runtime->draw_buffer->offscreen = offscreen;
744 }
745
746 region->runtime->draw_buffer->bound_view = -1;
747 region->runtime->draw_buffer->stereo = stereo;
748 }
749}
750
751static void wm_draw_region_bind(ARegion *region, int view)
752{
753 if (!region->runtime->draw_buffer) {
754 return;
755 }
756
757 if (region->runtime->draw_buffer->viewport) {
758 GPU_viewport_bind(region->runtime->draw_buffer->viewport, view, &region->winrct);
759 }
760 else {
761 GPU_offscreen_bind(region->runtime->draw_buffer->offscreen, false);
762
763 /* For now scissor is expected by region drawing, we could disable it
764 * and do the enable/disable in the specific cases that setup scissor. */
765 GPU_scissor_test(true);
766 GPU_scissor(0, 0, region->winx, region->winy);
767 }
768
769 region->runtime->draw_buffer->bound_view = view;
770}
771
772static void wm_draw_region_unbind(ARegion *region)
773{
774 if (!region->runtime->draw_buffer) {
775 return;
776 }
777
778 region->runtime->draw_buffer->bound_view = -1;
779
780 if (region->runtime->draw_buffer->viewport) {
781 GPU_viewport_unbind(region->runtime->draw_buffer->viewport);
782 }
783 else {
784 GPU_scissor_test(false);
785 GPU_offscreen_unbind(region->runtime->draw_buffer->offscreen, false);
786 }
787}
788
789static void wm_draw_region_blit(ARegion *region, int view)
790{
791 if (!region->runtime->draw_buffer) {
792 return;
793 }
794
795 if (view == -1) {
796 /* Non-stereo drawing. */
797 view = 0;
798 }
799 else if (view > 0) {
800 if (region->runtime->draw_buffer->viewport == nullptr) {
801 /* Region does not need stereo or failed to allocate stereo buffers. */
802 view = 0;
803 }
804 }
805
806 if (region->runtime->draw_buffer->viewport) {
807 GPU_viewport_draw_to_screen(region->runtime->draw_buffer->viewport, view, &region->winrct);
808 }
809 else {
811 region->runtime->draw_buffer->offscreen, region->winrct.xmin, region->winrct.ymin);
812 }
813}
814
815GPUTexture *wm_draw_region_texture(ARegion *region, int view)
816{
817 if (!region->runtime->draw_buffer) {
818 return nullptr;
819 }
820
821 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
822 if (viewport) {
823 return GPU_viewport_color_texture(viewport, view);
824 }
825 return GPU_offscreen_color_texture(region->runtime->draw_buffer->offscreen);
826}
827
828void wm_draw_region_blend(ARegion *region, int view, bool blend)
829{
830 if (!region->runtime->draw_buffer) {
831 return;
832 }
833
834 /* Alpha is always 1, except when blend timer is running. */
835 float alpha = ED_region_blend_alpha(region);
836 if (alpha <= 0.0f) {
837 return;
838 }
839
840 if (!blend) {
841 alpha = 1.0f;
842 }
843
844 /* #wmOrtho for the screen has this same offset. */
845 const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&region->winrct) + 1);
846 const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&region->winrct) + 1);
847
848 rcti rect_geo = region->winrct;
849 rect_geo.xmax += 1;
850 rect_geo.ymax += 1;
851
852 rctf rect_tex;
853 rect_tex.xmin = halfx;
854 rect_tex.ymin = halfy;
855 rect_tex.xmax = 1.0f + halfx;
856 rect_tex.ymax = 1.0f + halfy;
857
858 float alpha_easing = 1.0f - alpha;
859 alpha_easing = 1.0f - alpha_easing * alpha_easing;
860
861 /* Slide vertical panels. */
862 float ofs_x = BLI_rcti_size_x(&region->winrct) * (1.0f - alpha_easing);
864 rect_geo.xmin += ofs_x;
865 rect_tex.xmax *= alpha_easing;
866 alpha = 1.0f;
867 }
869 rect_geo.xmax -= ofs_x;
870 rect_tex.xmin += 1.0f - alpha_easing;
871 alpha = 1.0f;
872 }
873
874 /* Not the same layout as #rctf/#rcti. */
875 const float rectt[4] = {rect_tex.xmin, rect_tex.ymin, rect_tex.xmax, rect_tex.ymax};
876 const float rectg[4] = {
877 float(rect_geo.xmin), float(rect_geo.ymin), float(rect_geo.xmax), float(rect_geo.ymax)};
878
879 if (blend) {
880 /* Regions drawn off-screen have pre-multiplied alpha. */
882 }
883
884 /* Setup actual texture. */
885 GPUTexture *texture = wm_draw_region_texture(region, view);
886
888 GPU_shader_bind(shader);
889
890 int color_loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR);
891 int rect_tex_loc = GPU_shader_get_uniform(shader, "rect_icon");
892 int rect_geo_loc = GPU_shader_get_uniform(shader, "rect_geom");
893 int texture_bind_loc = GPU_shader_get_sampler_binding(shader, "image");
894
895 GPU_texture_bind(texture, texture_bind_loc);
896
897 GPU_shader_uniform_float_ex(shader, rect_tex_loc, 4, 1, rectt);
898 GPU_shader_uniform_float_ex(shader, rect_geo_loc, 4, 1, rectg);
899 GPU_shader_uniform_float_ex(shader, color_loc, 4, 1, blender::float4{1, 1, 1, 1});
900
901 blender::gpu::Batch *quad = GPU_batch_preset_quad();
902 GPU_batch_set_shader(quad, shader);
904
906
907 if (blend) {
909 }
910}
911
913{
914 if (!region->runtime->draw_buffer) {
915 return nullptr;
916 }
917
918 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
919 return viewport;
920}
921
923{
924 if (!region->runtime->draw_buffer || region->runtime->draw_buffer->bound_view == -1) {
925 return nullptr;
926 }
927
928 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
929 return viewport;
930}
931
932static void wm_draw_area_offscreen(bContext *C, wmWindow *win, ScrArea *area, bool stereo)
933{
935 Main *bmain = CTX_data_main(C);
936
937 CTX_wm_area_set(C, area);
939
940 /* Compute UI layouts for dynamically size regions. */
941 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
942 if (region->flag & RGN_FLAG_POLL_FAILED) {
943 continue;
944 }
945 /* Dynamic region may have been flagged as too small because their size on init is 0.
946 * ARegion.visible is false then, as expected. The layout should still be created then, so
947 * the region size can be updated (it may turn out to be not too small then). */
948 const bool ignore_visibility = (region->flag & RGN_FLAG_DYNAMIC_SIZE) &&
949 (region->flag & RGN_FLAG_TOO_SMALL) &&
950 !(region->flag & RGN_FLAG_HIDDEN);
951
952 if ((region->runtime->visible || ignore_visibility) && region->runtime->do_draw &&
953 region->runtime->type && region->runtime->type->layout)
954 {
955 CTX_wm_region_set(C, region);
956 ED_region_do_layout(C, region);
957 CTX_wm_region_set(C, nullptr);
958 }
959 }
960
961 ED_area_update_region_sizes(wm, win, area);
962
964 if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
967 }
969 }
970
971 /* Then do actual drawing of regions. */
972 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
973 if (!region->runtime->visible || !region->runtime->do_draw) {
974 continue;
975 }
976
977 CTX_wm_region_set(C, region);
978 bool use_viewport = WM_region_use_viewport(area, region);
979
980 GPU_debug_group_begin(use_viewport ? "Viewport" : "ARegion");
981
982 if (stereo && wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID)) {
983 Scene *scene = WM_window_get_active_scene(win);
984 wm_draw_region_buffer_create(scene, region, true, use_viewport);
985
986 for (int view = 0; view < 2; view++) {
987 eStereoViews sview;
988 if (view == 0) {
989 sview = STEREO_LEFT_ID;
990 }
991 else {
992 sview = STEREO_RIGHT_ID;
993 wm_draw_region_stereo_set(bmain, area, region, sview);
994 }
995
996 wm_draw_region_bind(region, view);
997 ED_region_do_draw(C, region);
998 wm_draw_region_unbind(region);
999 }
1000 if (use_viewport) {
1001 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
1003 }
1004 }
1005 else {
1006 wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID);
1007 Scene *scene = WM_window_get_active_scene(win);
1008 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1009 wm_draw_region_bind(region, 0);
1010 ED_region_do_draw(C, region);
1011 wm_draw_region_unbind(region);
1012 }
1013
1015
1016 region->runtime->do_draw = 0;
1017 CTX_wm_region_set(C, nullptr);
1018 }
1019
1020 CTX_wm_area_set(C, nullptr);
1021
1023}
1024
1025static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
1026{
1027 bScreen *screen = WM_window_get_active_screen(win);
1028
1029 /* Draw screen areas into their own frame buffer. Status bar and spreadsheet is drawn
1030 * last, because mesh and memory usage statistics are affected by drawing of other
1031 * editors like the 3D viewport. */
1032 ED_screen_areas_iter (win, screen, area) {
1034 wm_draw_area_offscreen(C, win, area, stereo);
1035 }
1036 }
1037 ED_screen_areas_iter (win, screen, area) {
1039 wm_draw_area_offscreen(C, win, area, stereo);
1040 }
1041 }
1042
1043 /* Draw menus into their own frame-buffer. */
1044 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1045 if (!region->runtime->visible) {
1046 continue;
1047 }
1048 CTX_wm_region_popup_set(C, region);
1049
1050 GPU_debug_group_begin("Menu");
1051
1052 if (region->runtime->type && region->runtime->type->layout) {
1053 /* UI code reads the OpenGL state, but we have to refresh
1054 * the UI layout beforehand in case the menu size changes. */
1055 wmViewport(&region->winrct);
1056 region->runtime->type->layout(C, region);
1057 }
1058
1059 Scene *scene = WM_window_get_active_scene(win);
1060 wm_draw_region_buffer_create(scene, region, false, false);
1061 wm_draw_region_bind(region, 0);
1062 GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
1063 ED_region_do_draw(C, region);
1064 wm_draw_region_unbind(region);
1065
1067
1068 region->runtime->do_draw = 0;
1069 CTX_wm_region_popup_set(C, nullptr);
1070 }
1071}
1072
1074{
1076 bScreen *screen = WM_window_get_active_screen(win);
1077
1078 GPU_debug_group_begin("Window Redraw");
1079
1080 /* Draw into the window frame-buffer, in full window coordinates. */
1081 wmWindowViewport(win);
1082
1083/* We draw on all pixels of the windows so we don't need to clear them before.
1084 * Actually this is only a problem when resizing the window.
1085 * If it becomes a problem we should clear only when window size changes. */
1086#if 0
1087 GPU_clear_color(0, 0, 0, 0);
1088#endif
1089
1090 /* Blit non-overlapping area regions. */
1091 ED_screen_areas_iter (win, screen, area) {
1092 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1093 if (!region->runtime->visible) {
1094 continue;
1095 }
1096
1097 if (region->overlap == false) {
1098 /* Blit from off-screen buffer. */
1099 wm_draw_region_blit(region, view);
1100 }
1101 }
1102 }
1103
1104 /* Draw overlays and paint cursors. */
1105 ED_screen_areas_iter (win, screen, area) {
1106 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1107 if (!region->runtime->visible) {
1108 continue;
1109 }
1110 const bool do_paint_cursor = (wm->paintcursors.first && region == screen->active_region);
1111 const bool do_draw_overlay = (region->runtime->type && region->runtime->type->draw_overlay);
1112 if (!(do_paint_cursor || do_draw_overlay)) {
1113 continue;
1114 }
1115
1116 CTX_wm_area_set(C, area);
1117 CTX_wm_region_set(C, region);
1118 if (do_draw_overlay) {
1119 wm_region_draw_overlay(C, area, region);
1120 }
1121 if (do_paint_cursor) {
1122 wm_paintcursor_draw(C, area, region);
1123 }
1124 CTX_wm_region_set(C, nullptr);
1125 CTX_wm_area_set(C, nullptr);
1126 }
1127 }
1128 wmWindowViewport(win);
1129
1130 /* Blend in overlapping area regions. */
1131 ED_screen_areas_iter (win, screen, area) {
1132 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1133 if (!region->runtime->visible) {
1134 continue;
1135 }
1136 if (region->overlap) {
1137 wm_draw_region_blend(region, 0, true);
1138 }
1139 }
1140 }
1141
1142 /* After area regions so we can do area 'overlay' drawing. */
1143 UI_SetTheme(0, 0);
1145
1146 /* Needs zero offset here or it looks blurry. #128112. */
1147 wmWindowViewport_ex(win, 0.0f);
1148
1149 wm_draw_callbacks(win);
1150 wmWindowViewport(win);
1151
1152 /* Blend in floating regions (menus). */
1153 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1154 if (!region->runtime->visible) {
1155 continue;
1156 }
1157 wm_draw_region_blend(region, 0, true);
1158 }
1159
1160 /* Always draw, not only when screen tagged. */
1161 if (win->gesture.first) {
1162 wm_gesture_draw(win);
1163 wmWindowViewport(win);
1164 }
1165
1166 /* Needs pixel coords in screen. */
1167 if (wm->drags.first) {
1168 wm_drags_draw(C, win);
1169 wmWindowViewport(win);
1170 }
1171
1173 GrabState grab_state;
1174 if (wm_software_cursor_needed_for_window(win, &grab_state)) {
1175 wm_software_cursor_draw(win, &grab_state);
1177 }
1178 else {
1179 /* Checking the window is needed so one window doesn't clear the cursor state of another. */
1181 }
1182 }
1183
1185}
1186
1188{
1189 GPU_context_begin_frame(static_cast<GPUContext *>(win->gpuctx));
1190
1191 bScreen *screen = WM_window_get_active_screen(win);
1192 bool stereo = WM_stereo3d_enabled(win, false);
1193
1194 /* Avoid any BGL call issued before this to alter the window drawing. */
1195 GPU_bgl_end();
1196
1197 /* Draw area regions into their own frame-buffer. This way we can redraw
1198 * the areas that need it, and blit the rest from existing frame-buffers. */
1199 wm_draw_window_offscreen(C, win, stereo);
1200
1201 /* Now we draw into the window frame-buffer, in full window coordinates. */
1202 if (!stereo) {
1203 /* Regular mono drawing. */
1204 wm_draw_window_onscreen(C, win, -1);
1205 }
1207 /* For page-flip we simply draw to both back buffers. */
1209 wm_draw_window_onscreen(C, win, 1);
1210
1212 wm_draw_window_onscreen(C, win, 0);
1213 }
1215 /* For anaglyph and interlace, we draw individual regions with
1216 * stereo frame-buffers using different shaders. */
1217 wm_draw_window_onscreen(C, win, -1);
1218 }
1219 else {
1220 /* Determine desired offscreen format depending on HDR availability. */
1222
1223 /* For side-by-side and top-bottom, we need to render each view to an
1224 * an off-screen texture and then draw it. This used to happen for all
1225 * stereo methods, but it's less efficient than drawing directly. */
1226 const blender::int2 win_size = WM_window_native_pixel_size(win);
1227 GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
1228 win_size[1],
1229 false,
1230 desired_format,
1232 false,
1233 nullptr);
1234
1235 if (offscreen) {
1236 GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
1238
1239 for (int view = 0; view < 2; view++) {
1240 /* Draw view into offscreen buffer. */
1241 GPU_offscreen_bind(offscreen, false);
1243 GPU_offscreen_unbind(offscreen, false);
1244
1245 /* Draw offscreen buffer to screen. */
1247
1248 wmWindowViewport(win);
1251 }
1252 else {
1254 }
1255
1257 }
1258
1259 GPU_offscreen_free(offscreen);
1260 }
1261 else {
1262 /* Still draw something in case of allocation failure. */
1263 wm_draw_window_onscreen(C, win, 0);
1264 }
1265 }
1266
1267 screen->do_draw = false;
1268
1269 GPU_context_end_frame(static_cast<GPUContext *>(win->gpuctx));
1270}
1271
1275static void wm_draw_surface(bContext *C, wmSurface *surface)
1276{
1278 wm_surface_make_drawable(surface);
1279
1281
1282 surface->draw(C);
1283
1285
1286 /* Avoid interference with window drawable. */
1288}
1289
1291
1292/* -------------------------------------------------------------------- */
1297
1299 const wmWindow *win,
1300 int r_size[2])
1301{
1302 /* Don't assert as file-save uses this for a screenshot, where redrawing isn't an option
1303 * because of the side-effects of drawing a window on save.
1304 * In this case the thumbnail might not work and there are currently no better alternatives. */
1305 // BLI_assert(WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ);
1306
1307 /* WARNING: Reading from the front-buffer immediately after drawing may fail,
1308 * for a slower but more reliable version of this function
1309 * #WM_window_pixels_read_from_offscreen should be preferred.
1310 * See it's comments for details on why it's needed, see also #98462. */
1311 bool setup_context = wm->windrawable != win;
1312
1313 if (setup_context) {
1314 GHOST_ActivateWindowDrawingContext(static_cast<GHOST_WindowHandle>(win->ghostwin));
1315 GPU_context_active_set(static_cast<GPUContext *>(win->gpuctx));
1316 }
1317
1318 const blender::int2 win_size = WM_window_native_pixel_size(win);
1319 const uint rect_len = win_size[0] * win_size[1];
1320 uint8_t *rect = MEM_malloc_arrayN<uint8_t>(4 * rect_len, __func__);
1321
1322 GPU_frontbuffer_read_color(0, 0, win_size[0], win_size[1], 4, GPU_DATA_UBYTE, rect);
1323
1324 if (setup_context) {
1325 if (wm->windrawable) {
1327 static_cast<GHOST_WindowHandle>(wm->windrawable->ghostwin));
1328 GPU_context_active_set(static_cast<GPUContext *>(wm->windrawable->gpuctx));
1329 }
1330 }
1331
1332 /* Clear alpha, it is not set to a meaningful value in OpenGL. */
1333 uchar *cp = (uchar *)rect;
1334 uint i;
1335 for (i = 0, cp += 3; i < rect_len; i++, cp += 4) {
1336 *cp = 0xff;
1337 }
1338
1339 r_size[0] = win_size[0];
1340 r_size[1] = win_size[1];
1341 return rect;
1342}
1343
1345 const wmWindow *win,
1346 const int pos[2],
1347 float r_col[3])
1348{
1350 bool setup_context = wm->windrawable != win;
1351
1352 if (setup_context) {
1353 GHOST_ActivateWindowDrawingContext(static_cast<GHOST_WindowHandle>(win->ghostwin));
1354 GPU_context_active_set(static_cast<GPUContext *>(win->gpuctx));
1355 }
1356
1357 /* NOTE(@jbakker): Vulkan backend isn't able to read 3 channels from a 4 channel texture with
1358 * data data-conversions is needed. Data conversion happens inline for all channels. This is a
1359 * vulkan backend issue and should be solved. However the solution has a lot of branches that
1360 * requires testing so a quick fix has been added to the place where this was used. The solution
1361 * is to implement all the cases in 'VKFramebuffer::read'.
1362 */
1363 blender::float4 color_with_alpha;
1364 GPU_frontbuffer_read_color(pos[0], pos[1], 1, 1, 4, GPU_DATA_FLOAT, color_with_alpha);
1365 copy_v3_v3(r_col, color_with_alpha.xyz());
1366
1367 if (setup_context) {
1368 if (wm->windrawable) {
1370 static_cast<GHOST_WindowHandle>(wm->windrawable->ghostwin));
1371 GPU_context_active_set(static_cast<GPUContext *>(wm->windrawable->gpuctx));
1372 }
1373 }
1374}
1375
1377{
1378 /* NOTE(@ideasman42): There is a problem reading the windows front-buffer after redrawing
1379 * the window in some cases (typically to clear UI elements such as menus or search popup).
1380 * With EGL `eglSurfaceAttrib(..)` may support setting the `EGL_SWAP_BEHAVIOR` attribute to
1381 * `EGL_BUFFER_PRESERVED` however not all implementations support this.
1382 * Requesting the ability with `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` can even cause the EGL context
1383 * not to initialize at all.
1384 * Confusingly there are some cases where this *does* work, depending on the state of the window
1385 * and prior calls to swap-buffers, however ensuring the state exactly as needed to satisfy a
1386 * particular GPU back-end is fragile, see #98462.
1387 *
1388 * So provide an alternative to #WM_window_pixels_read that avoids using the front-buffer. */
1389
1390 /* Draw into an off-screen buffer and read its contents. */
1391 const blender::int2 win_size = WM_window_native_pixel_size(win);
1392
1393 /* Determine desired offscreen format depending on HDR availability. */
1395
1396 GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
1397 win_size[1],
1398 false,
1399 desired_format,
1401 false,
1402 nullptr);
1403 if (UNLIKELY(!offscreen)) {
1404 return nullptr;
1405 }
1406
1407 const uint rect_len = win_size[0] * win_size[1];
1408 uint8_t *rect = MEM_malloc_arrayN<uint8_t>(4 * rect_len, __func__);
1409 GPU_offscreen_bind(offscreen, false);
1410 wm_draw_window_onscreen(C, win, -1);
1411 GPU_offscreen_unbind(offscreen, false);
1412 GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, rect);
1413 GPU_offscreen_free(offscreen);
1414
1415 r_size[0] = win_size[0];
1416 r_size[1] = win_size[1];
1417 return rect;
1418}
1419
1421 wmWindow *win,
1422 const int pos[2],
1423 float r_col[3])
1424{
1425 /* A version of #WM_window_pixels_read_from_offscreen that reads a single sample. */
1426 const blender::int2 win_size = WM_window_native_pixel_size(win);
1427 zero_v3(r_col);
1428
1429 /* While this shouldn't happen, return in the case it does. */
1430 BLI_assert(uint(pos[0]) < uint(win_size[0]) && uint(pos[1]) < uint(win_size[1]));
1431 if (!(uint(pos[0]) < uint(win_size[0]) && uint(pos[1]) < uint(win_size[1]))) {
1432 return false;
1433 }
1434
1436 win_size[0], win_size[1], false, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, false, nullptr);
1437 if (UNLIKELY(!offscreen)) {
1438 return false;
1439 }
1440
1441 float rect_pixel[4];
1442 GPU_offscreen_bind(offscreen, false);
1443 wm_draw_window_onscreen(C, win, -1);
1444 GPU_offscreen_unbind(offscreen, false);
1445 GPU_offscreen_read_color_region(offscreen, GPU_DATA_FLOAT, pos[0], pos[1], 1, 1, rect_pixel);
1446 GPU_offscreen_free(offscreen);
1447 copy_v3_v3(r_col, rect_pixel);
1448 return true;
1449}
1450
1451uint8_t *WM_window_pixels_read(bContext *C, wmWindow *win, int r_size[2])
1452{
1455 }
1456 return WM_window_pixels_read_from_offscreen(C, win, r_size);
1457}
1458
1459bool WM_window_pixels_read_sample(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
1460{
1463 return true;
1464 }
1466}
1467
1469{
1470 return GHOST_GetPixelAtCursor(r_col);
1471}
1472
1474
1475/* -------------------------------------------------------------------- */
1478
1479/* Quick test to prevent changing window drawable. */
1481{
1482 const wmWindowManager *wm = CTX_wm_manager(C);
1483 Scene *scene = WM_window_get_active_scene(win);
1484 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1485 Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
1486 bScreen *screen = WM_window_get_active_screen(win);
1487 bool do_draw = false;
1488
1489 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1490 if (region->runtime->do_draw_paintcursor) {
1491 screen->do_draw_paintcursor = true;
1492 region->runtime->do_draw_paintcursor = false;
1493 }
1494 if (region->runtime->visible && region->runtime->do_draw) {
1495 do_draw = true;
1496 }
1497 }
1498
1499 ED_screen_areas_iter (win, screen, area) {
1500 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1501 wm_region_test_gizmo_do_draw(C, area, region, true);
1502 wm_region_test_render_do_draw(scene, depsgraph, area, region);
1503#ifdef WITH_XR_OPENXR
1504 wm_region_test_xr_do_draw(wm, area, region);
1505#endif
1506
1507 if (region->runtime->visible && region->runtime->do_draw) {
1508 do_draw = true;
1509 }
1510 }
1511 }
1512
1513 if (do_draw) {
1514 return true;
1515 }
1516
1517 if (screen->do_refresh) {
1518 return true;
1519 }
1520 if (screen->do_draw) {
1521 return true;
1522 }
1523 if (screen->do_draw_gesture) {
1524 return true;
1525 }
1526 if (screen->do_draw_paintcursor) {
1527 return true;
1528 }
1529 if (screen->do_draw_drag) {
1530 return true;
1531 }
1532
1534 GrabState grab_state;
1535 if (wm_software_cursor_needed_for_window(win, &grab_state)) {
1537 return true;
1538 }
1539 }
1540 else {
1541 /* Detect the edge case when the previous draw used the software cursor but this one doesn't,
1542 * it's important to redraw otherwise the software cursor will remain displayed. */
1543 if (g_software_cursor.winid == win->winid) {
1544 return true;
1545 }
1546 }
1547 }
1548
1549#ifndef WITH_XR_OPENXR
1550 UNUSED_VARS(wm);
1551#endif
1552
1553 return false;
1554}
1555
1556/* Clear drawing flags, after drawing is complete so any draw flags set during
1557 * drawing don't cause any additional redraws. */
1559{
1560 bScreen *screen = WM_window_get_active_screen(win);
1561
1562 ED_screen_areas_iter (win, screen, area) {
1563 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1564 wm_region_test_gizmo_do_draw(C, area, region, false);
1565 }
1566 }
1567
1568 screen->do_draw_gesture = false;
1569 screen->do_draw_paintcursor = false;
1570 screen->do_draw_drag = false;
1571}
1572
1574{
1575 if (win) {
1576 bScreen *screen = WM_window_get_active_screen(win);
1577 screen->do_draw_paintcursor = true;
1578 }
1579}
1580
1582{
1583 Main *bmain = CTX_data_main(C);
1585
1587
1590
1592
1593#ifdef WITH_METAL_BACKEND
1594 /* Reset drawable to ensure GPU context activation happens at least once per frame if only a
1595 * single context exists. This is required to ensure the default framebuffer is updated
1596 * to be the latest backbuffer. */
1598#endif
1599
1600 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
1601#ifdef WIN32
1603 static_cast<GHOST_WindowHandle>(win->ghostwin));
1604
1606 /* Do not update minimized windows, gives issues on Intel (see #33223)
1607 * and AMD (see #50856). it seems logical to skip update for invisible window anyway. */
1608 continue;
1609 }
1610#endif
1611
1612 CTX_wm_window_set(C, win);
1613
1614 if (wm_draw_update_test_window(bmain, C, win)) {
1615 /* Sets context window+screen. */
1616 wm_window_make_drawable(wm, win);
1617
1618 /* Notifiers for screen redraw. */
1619 ED_screen_ensure_updated(C, wm, win);
1620
1621 wm_draw_window(C, win);
1623
1625 }
1626 }
1627
1628 CTX_wm_window_set(C, nullptr);
1629
1630 /* Draw non-windows (surfaces). */
1632
1635}
1636
1637void wm_draw_region_clear(wmWindow *win, ARegion * /*region*/)
1638{
1639 bScreen *screen = WM_window_get_active_screen(win);
1640 screen->do_draw = true;
1641}
1642
1644{
1646}
1647
1649{
1650 /* Function for redraw timer benchmark. */
1651 bool use_viewport = WM_region_use_viewport(area, region);
1652 wmWindow *win = CTX_wm_window(C);
1653 Scene *scene = WM_window_get_active_scene(win);
1654 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1655 wm_draw_region_bind(region, 0);
1656 ED_region_do_draw(C, region);
1657 wm_draw_region_unbind(region);
1658 region->runtime->do_draw = 0;
1659}
1660
1662{
1663 wmWindow *win_prev = CTX_wm_window(C);
1664 ScrArea *area_prev = CTX_wm_area(C);
1665 ARegion *region_prev = CTX_wm_region(C);
1666
1668
1669 CTX_wm_window_set(C, win_prev);
1670 CTX_wm_area_set(C, area_prev);
1671 CTX_wm_region_set(C, region_prev);
1672}
1673
1675
1676/* -------------------------------------------------------------------- */
1685
1686void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type)
1687{
1688 bool use_viewport = wm_region_use_viewport_by_type(space_type, region->regiontype);
1689 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1690}
1691
1693{
1694 wm_draw_region_bind(region, 0);
1695}
1696
1698{
1699 wm_draw_region_unbind(region);
1700}
1701
WorkSpace * CTX_wm_workspace(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
void CTX_wm_window_set(bContext *C, wmWindow *win)
Main * CTX_data_main(const bContext *C)
void CTX_wm_area_set(bContext *C, ScrArea *area)
void CTX_wm_region_set(bContext *C, ARegion *region)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void CTX_wm_region_popup_set(bContext *C, ARegion *region_popup)
ViewLayer * CTX_data_view_layer(const bContext *C)
Image * BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
void BKE_image_free_unused_gpu_textures()
Definition image_gpu.cc:536
Depsgraph * BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3427
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE int mod_i(int i, int n)
void unit_m4(float m[4][4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define UNUSED_VARS(...)
#define UNLIKELY(x)
#define ELEM(...)
@ COLORMANAGE_VIEW_USE_HDR
@ IMA_TYPE_COMPOSITE
These structs are the foundation for all linked lists in the library system.
Object is a sort of wrapper for general info.
@ OB_CAMERA
@ S3D_DISPLAY_ANAGLYPH
@ S3D_DISPLAY_INTERLACE
@ S3D_DISPLAY_SIDEBYSIDE
@ S3D_DISPLAY_PAGEFLIP
eStereoViews
@ STEREO_LEFT_ID
@ STEREO_RIGHT_ID
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
#define RGN_TYPE_ANY
@ RGN_FLAG_DYNAMIC_SIZE
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_POLL_FAILED
@ RGN_FLAG_TOO_SMALL
@ AREA_FLAG_ACTIVE_TOOL_UPDATE
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_RIGHT
@ SNODE_BACKDRAW
@ SPACE_TEXT
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_CONSOLE
@ SPACE_OUTLINER
@ SPACE_STATUSBAR
@ SPACE_TOPBAR
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_USERPREF
@ SPACE_FILE
@ SPACE_PROPERTIES
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_EMPTY
@ SPACE_SCRIPT
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ SPACE_INFO
#define SPACE_TYPE_ANY
#define UI_SCALE_FAC
bool ED_node_is_compositor(const SpaceNode *snode)
Definition node_edit.cc:548
float ED_region_blend_alpha(ARegion *region)
void ED_screen_ensure_updated(bContext *C, wmWindowManager *wm, wmWindow *win)
#define ED_screen_areas_iter(win, screen, area_name)
Definition ED_screen.hh:288
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:659
void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
Definition area.cc:687
void ED_screen_draw_edges(wmWindow *win)
void ED_region_do_layout(bContext *C, ARegion *region)
Definition area.cc:479
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area)
Definition area.cc:2050
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:675
void ED_region_do_draw(bContext *C, ARegion *region)
Definition area.cc:502
bool ED_view3d_calc_render_border(const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *region, rcti *r_rect)
static AppView * view
GHOST C-API function and type declarations.
GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle)
GHOST_TSuccess GHOST_GetPixelAtCursor(float r_color[3])
void GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle, GHOST_TGrabCursorMode *r_mode, GHOST_TAxisFlag *r_axis_flag, int r_bounds[4], bool *r_use_software_cursor)
GHOST_TSuccess GHOST_GetCursorBitmap(GHOST_WindowHandle windowhandle, GHOST_CursorBitmapRef *bitmap)
bool GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle)
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
GHOST_TWindowState
@ GHOST_kWindowStateMinimized
GHOST_TAxisFlag
@ GHOST_kAxisX
@ GHOST_kAxisY
@ GHOST_kSuccess
Definition GHOST_Types.h:80
GHOST_TGrabCursorMode
@ GHOST_kGrabWrap
@ GHOST_kGrabHide
void GPU_batch_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
blender::gpu::Batch * GPU_batch_preset_quad()
bool GPU_hdr_support()
void GPU_render_end()
void GPU_render_step(bool force_resource_release=false)
void GPU_context_main_lock()
void GPU_context_begin_frame(GPUContext *ctx)
void GPU_render_begin()
void GPU_context_main_unlock()
void GPU_context_end_frame(GPUContext *ctx)
void GPU_context_active_set(GPUContext *)
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
void GPU_offscreen_draw_to_screen(GPUOffScreen *offscreen, int x, int y)
int GPU_offscreen_width(const GPUOffScreen *offscreen)
void GPU_offscreen_bind(GPUOffScreen *offscreen, bool save)
void GPU_frontbuffer_read_color(int x, int y, int width, int height, int channels, eGPUDataFormat data_format, void *r_data)
int GPU_offscreen_height(const GPUOffScreen *offscreen)
GPUOffScreen * GPU_offscreen_create(int width, int height, bool with_depth_buffer, eGPUTextureFormat format, eGPUTextureUsage usage, bool clear, char err_out[256])
@ GPU_BACKBUFFER_LEFT
@ GPU_BACKBUFFER_RIGHT
GPUTexture * GPU_offscreen_color_texture(const GPUOffScreen *offscreen)
void GPU_clear_color(float red, float green, float blue, float alpha)
void GPU_offscreen_read_color_region(GPUOffScreen *offscreen, eGPUDataFormat data_format, int x, int y, int w, int h, void *r_data)
void GPU_offscreen_free(GPUOffScreen *offscreen)
void GPU_backbuffer_bind(eGPUBackBuffer back_buffer_type)
eGPUTextureFormat GPU_offscreen_format(const GPUOffScreen *offscreen)
void GPU_offscreen_read_color(GPUOffScreen *offscreen, eGPUDataFormat data_format, void *r_data)
void GPU_offscreen_unbind(GPUOffScreen *offscreen, bool restore)
void immEnd()
void immUnbindProgram()
void immUniformColor4f(float r, float g, float b, float a)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immBindTexture(const char *name, GPUTexture *tex)
void immVertex3f(uint attr_id, float x, float y, float z)
GPUVertFormat * immVertexFormat()
void immAttr2f(uint attr_id, float x, float y)
void immBegin(GPUPrimType, uint vertex_len)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_push()
#define GPU_matrix_mul(x)
void GPU_matrix_pop()
@ GPU_PRIM_TRI_FAN
int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_float_ex(GPUShader *shader, int location, int length, int array_size, const float *value)
@ GPU_UNIFORM_COLOR
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
GPUShader * GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_2D_IMAGE_RECT_COLOR
@ GPU_SHADER_3D_IMAGE
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
void GPU_bgl_end()
Definition gpu_state.cc:360
void GPU_texture_bind(GPUTexture *texture, int unit)
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
void GPU_texture_unbind(GPUTexture *texture)
@ GPU_DATA_UBYTE
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_GENERAL
void GPU_texture_mipmap_mode(GPUTexture *texture, bool use_mipmap, bool use_filter)
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
eGPUTextureFormat
@ GPU_RGBA16F
@ GPU_RGBA8
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
GPUTexture * GPU_viewport_color_texture(GPUViewport *viewport, int view)
void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
GPUViewport * GPU_viewport_create()
GPUViewport * GPU_viewport_stereo_create()
bool GPU_viewport_do_update(GPUViewport *viewport)
void GPU_viewport_free(GPUViewport *viewport)
void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format)
void GPU_viewport_unbind(GPUViewport *viewport)
#define GLA_PIXEL_OFS
Read Guarded memory(de)allocation.
@ RE_USE_STEREO_VIEWPORT
Definition RE_engine.h:49
@ RE_ENGINE_DO_DRAW
Definition RE_engine.h:61
#define C
Definition RandGen.cpp:29
void UI_SetTheme(int spacetype, int regionid)
#define WM_CURSOR_DEFAULT_LOGICAL_SIZE
Definition WM_api.hh:531
@ WM_CAPABILITY_CURSOR_WARP
Definition WM_api.hh:168
@ WM_CAPABILITY_GPU_FRONT_BUFFER_READ
Definition WM_api.hh:191
@ WM_GIZMOGROUPTYPE_VR_REDRAWS
#define WM_TOOLSYSTEM_SPACE_MASK
#define U
BPy_StructRNA * depsgraph
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
uint pos
blender::gpu::Batch * quad
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
bool enabled
RenderEngine * RE_view_engine_get(const ViewRender *view_render)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong state[N]
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
#define min(a, b)
Definition sort.cc:36
void * regiondata
ARegionRuntimeHandle * runtime
struct ImageUser iuser
struct ListBase bg_images
const uint8_t * data
Definition GHOST_Types.h:63
GHOST_TAxisFlag wrap_axis
Definition wm_draw.cc:183
GHOST_TGrabCursorMode mode
Definition wm_draw.cc:182
int bounds[4]
Definition wm_draw.cc:184
void * first
struct ViewRender * view_render
RenderEngineType * type
Definition RE_engine.h:131
ColorManagedViewSettings view_settings
ListBase spacedata
ListBase regionbase
struct ImageUser iuser
char multiview_eye
struct Object * camera
void(* draw)(const wmWindow *win, void *customdata)
Definition wm_draw.cc:611
WindowDrawCB * prev
Definition wm_draw.cc:609
WindowDrawCB * next
Definition wm_draw.cc:609
void * customdata
Definition wm_draw.cc:612
char do_draw_drag
ListBase regionbase
char do_draw_paintcursor
char do_draw_gesture
struct ARegion * active_region
VecBase< T, 3 > xyz() const
float xmax
float xmin
float ymax
float ymin
int ymin
int ymax
int xmin
int xmax
int xy[2]
Definition WM_types.hh:758
wmTabletData tablet
Definition WM_types.hh:783
GPUContext * blender_gpu_context
Definition wm_surface.hh:24
void(* draw)(bContext *)
Definition wm_surface.hh:28
blender::float2 tilt
Definition WM_types.hh:707
WindowManagerRuntimeHandle * runtime
struct wmWindow * windrawable
struct wmEvent * eventstate
struct Stereo3dFormat * stereo3d_format
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
void wm_drags_draw(bContext *C, wmWindow *win)
static void wm_draw_callbacks(wmWindow *win)
Definition wm_draw.cc:639
void WM_draw_region_viewport_unbind(ARegion *region)
Definition wm_draw.cc:1697
static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
Definition wm_draw.cc:672
uint8_t * WM_window_pixels_read_from_frontbuffer(const wmWindowManager *wm, const wmWindow *win, int r_size[2])
Definition wm_draw.cc:1298
static void wm_draw_region_unbind(ARegion *region)
Definition wm_draw.cc:772
static void wm_draw_region_bind(ARegion *region, int view)
Definition wm_draw.cc:751
static bool wm_software_cursor_needed_for_window(const wmWindow *win, GrabState *grab_state)
Definition wm_draw.cc:195
static const char * wm_area_name(ScrArea *area)
Definition wm_draw.cc:569
uint8_t * WM_window_pixels_read(bContext *C, wmWindow *win, int r_size[2])
Definition wm_draw.cc:1451
static bool wm_region_use_viewport_by_type(short space_type, short region_type)
Definition wm_draw.cc:557
static void wm_draw_surface(bContext *C, wmSurface *surface)
Definition wm_draw.cc:1275
void WM_window_pixels_read_sample_from_frontbuffer(const wmWindowManager *wm, const wmWindow *win, const int pos[2], float r_col[3])
Definition wm_draw.cc:1344
static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
Definition wm_draw.cc:1025
void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type)
Definition wm_draw.cc:1686
static struct @227072351314272261175162320203167073350335233230 g_software_cursor
static void wm_draw_area_offscreen(bContext *C, wmWindow *win, ScrArea *area, bool stereo)
Definition wm_draw.cc:932
void WM_redraw_windows(bContext *C)
Definition wm_draw.cc:1661
int xy[2]
Definition wm_draw.cc:174
static void wm_draw_region_buffer_free(ARegion *region)
Definition wm_draw.cc:657
static void wm_draw_region_buffer_create(Scene *scene, ARegion *region, bool stereo, bool use_viewport)
Definition wm_draw.cc:691
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition wm_draw.cc:912
void * WM_draw_cb_activate(wmWindow *win, void(*draw)(const wmWindow *win, void *customdata), void *customdata)
Definition wm_draw.cc:615
static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:103
void wm_draw_region_blend(ARegion *region, int view, bool blend)
Definition wm_draw.cc:828
static void wm_draw_update_clear_window(bContext *C, wmWindow *win)
Definition wm_draw.cc:1558
static bool wm_software_cursor_needed()
Definition wm_draw.cc:187
GPUTexture * wm_draw_region_texture(ARegion *region, int view)
Definition wm_draw.cc:815
static eGPUTextureFormat get_hdr_framebuffer_format(const Scene *scene)
Definition wm_draw.cc:681
bool WM_region_use_viewport(ScrArea *area, ARegion *region)
Definition wm_draw.cc:564
#define SPACE_NAME(space)
static void wm_region_test_render_do_draw(const Scene *scene, Depsgraph *depsgraph, ScrArea *area, ARegion *region)
Definition wm_draw.cc:511
static bool wm_draw_region_stereo_set(Main *bmain, ScrArea *area, ARegion *region, eStereoViews sview)
Definition wm_draw.cc:407
bool WM_window_pixels_read_sample_from_offscreen(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
Definition wm_draw.cc:1420
void WM_draw_cb_exit(wmWindow *win, void *handle)
Definition wm_draw.cc:628
void wm_draw_region_clear(wmWindow *win, ARegion *)
Definition wm_draw.cc:1637
static void wm_region_test_gizmo_do_draw(bContext *C, ScrArea *area, ARegion *region, bool tag_redraw)
Definition wm_draw.cc:473
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *)
Definition wm_draw.cc:1573
static void wm_software_cursor_draw(wmWindow *win, const GrabState *grab_state)
Definition wm_draw.cc:354
static bool wm_software_cursor_motion_test(const wmWindow *win)
Definition wm_draw.cc:214
static void wm_software_cursor_motion_clear_with_window(const wmWindow *win)
Definition wm_draw.cc:236
void WM_draw_region_viewport_bind(ARegion *region)
Definition wm_draw.cc:1692
GPUViewport * WM_draw_region_get_bound_viewport(ARegion *region)
Definition wm_draw.cc:922
static void wm_software_cursor_draw_crosshair(const int event_xy[2])
Definition wm_draw.cc:306
int winid
Definition wm_draw.cc:173
void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:1648
static void wm_draw_region_blit(ARegion *region, int view)
Definition wm_draw.cc:789
uint8_t * WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_size[2])
Definition wm_draw.cc:1376
void WM_draw_region_free(ARegion *region)
Definition wm_draw.cc:1643
static void wm_software_cursor_motion_update(const wmWindow *win)
Definition wm_draw.cc:221
static void wm_region_draw_overlay(bContext *C, const ScrArea *area, ARegion *region)
Definition wm_draw.cc:391
static void wm_draw_window(bContext *C, wmWindow *win)
Definition wm_draw.cc:1187
static void wm_software_cursor_draw_bitmap(const int event_xy[2], const GHOST_CursorBitmapRef *bitmap)
Definition wm_draw.cc:243
static bool wm_window_grab_warp_region_is_set(const wmWindow *win)
Definition wm_draw.cc:78
bool WM_desktop_cursor_sample_read(float r_col[3])
Definition wm_draw.cc:1468
void wm_draw_update(bContext *C)
Definition wm_draw.cc:1581
static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win)
Definition wm_draw.cc:1480
static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
Definition wm_draw.cc:1073
static void wm_software_cursor_motion_clear()
Definition wm_draw.cc:229
bool WM_window_pixels_read_sample(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
Definition wm_draw.cc:1459
void WM_global_report(eReportType type, const char *message)
void wm_gesture_draw(wmWindow *win)
bool WM_gizmo_group_type_poll(const bContext *C, const wmGizmoGroupType *gzgt)
const ListBase * WM_gizmomap_group_list(wmGizmoMap *gzmap)
void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
Definition wm_stereo.cc:41
bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
Definition wm_stereo.cc:138
void wm_stereo3d_draw_topbottom(wmWindow *win, int view)
Definition wm_stereo.cc:90
void wmViewport(const rcti *winrct)
void wmWindowViewport(const wmWindow *win)
void wmWindowViewport_ex(const wmWindow *win, float offset)
void wm_surface_make_drawable(wmSurface *surface)
Definition wm_surface.cc:76
void wm_surface_clear_drawable()
Definition wm_surface.cc:47
void wm_surfaces_iter(bContext *C, void(*cb)(bContext *C, wmSurface *))
Definition wm_surface.cc:27
void WM_toolsystem_update_from_context(bContext *C, WorkSpace *workspace, const Scene *scene, ViewLayer *view_layer, ScrArea *area)
blender::int2 WM_window_native_pixel_size(const wmWindow *win)
void wm_window_swap_buffers(wmWindow *win)
Push rendered buffer to the screen.
bool wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y)
int WM_window_native_pixel_y(const wmWindow *win)
void wm_window_clear_drawable(wmWindowManager *wm)
void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
eWM_CapabilitiesFlag WM_capabilities_flag()
uint WM_cursor_preferred_logical_size()
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Scene * WM_window_get_active_scene(const wmWindow *win)
bScreen * WM_window_get_active_screen(const wmWindow *win)