Blender V5.0
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_color_types.h"
16#include "DNA_listBase.h"
17#include "DNA_object_types.h"
18#include "DNA_screen_types.h"
19#include "DNA_space_types.h"
20#include "DNA_userdef_types.h"
21#include "DNA_view3d_types.h"
23
24#include "MEM_guardedalloc.h"
25
26#include "BLI_listbase.h"
27#include "BLI_math_matrix.h"
28#include "BLI_math_vector.h"
30#include "BLI_rect.h"
31#include "BLI_utildefines.h"
32
33#include "BKE_context.hh"
34#include "BKE_image.hh"
35#include "BKE_layer.hh"
36#include "BKE_scene.hh"
37#include "BKE_screen.hh"
38
39#include "GHOST_C-api.h"
40
41#include "ED_node.hh"
42#include "ED_screen.hh"
43#include "ED_view3d.hh"
44
45#include "GPU_batch_presets.hh"
46#include "GPU_capabilities.hh"
47#include "GPU_context.hh"
48#include "GPU_debug.hh"
49#include "GPU_framebuffer.hh"
50#include "GPU_immediate.hh"
51#include "GPU_matrix.hh"
52#include "GPU_state.hh"
53#include "GPU_texture.hh"
54#include "GPU_viewport.hh"
55
56#include "RE_engine.h"
57
58#include "WM_api.hh"
59#include "WM_toolsystem.hh"
60#include "WM_types.hh"
61#include "wm.hh"
62#include "wm_draw.hh"
63#include "wm_event_system.hh"
64#include "wm_surface.hh"
65#include "wm_window.hh"
66
67#include "UI_resources.hh"
68
70
71#ifdef WITH_OPENSUBDIV
72# include "BKE_subsurf.hh"
73#endif
74
75/* -------------------------------------------------------------------- */
78
83{
85 GHOST_TGrabCursorMode mode_dummy;
86 GHOST_TAxisFlag wrap_axis_dummy;
87 int bounds[4] = {0};
88 bool use_software_cursor_dummy = false;
89 GHOST_GetCursorGrabState(static_cast<GHOST_WindowHandle>(win->ghostwin),
90 &mode_dummy,
91 &wrap_axis_dummy,
92 bounds,
93 &use_software_cursor_dummy);
94 if ((bounds[0] != bounds[2]) || (bounds[1] != bounds[3])) {
95 return true;
96 }
97 }
98 return false;
99}
100
102
103/* -------------------------------------------------------------------- */
106
107static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
108{
110 wmWindow *win = CTX_wm_window(C);
112
113 /* Don't draw paint cursors with locked interface. Painting is not possible
114 * then, and cursor drawing can use scene data that another thread may be
115 * modifying. */
116 if (wm->runtime->is_interface_locked) {
117 return;
118 }
119
120 if (!region->runtime->visible || region != screen->active_region) {
121 return;
122 }
123
124 LISTBASE_FOREACH_MUTABLE (wmPaintCursor *, pc, &wm->runtime->paintcursors) {
125 if ((pc->space_type != SPACE_TYPE_ANY) && (area->spacetype != pc->space_type)) {
126 continue;
127 }
128
129 if (!ELEM(pc->region_type, RGN_TYPE_ANY, region->regiontype)) {
130 continue;
131 }
132
133 if (pc->poll == nullptr || pc->poll(C)) {
134 UI_SetTheme(area->spacetype, region->regiontype);
135
136 /* Prevent drawing outside region. */
137 GPU_scissor_test(true);
138 GPU_scissor(region->winrct.xmin,
139 region->winrct.ymin,
140 BLI_rcti_size_x(&region->winrct) + 1,
141 BLI_rcti_size_y(&region->winrct) + 1);
142 /* Reading the cursor location from the operating-system while the cursor is grabbed
143 * conflicts with grabbing logic that hides the cursor, then keeps it centered to accumulate
144 * deltas without it escaping from the window. In this case we never want to show the actual
145 * cursor coordinates so limit reading the cursor location to when the cursor is grabbed and
146 * wrapping in a region since this is the case when it would otherwise attempt to draw the
147 * cursor outside the view/window. See: #102792. */
148 const int *xy = win->eventstate->xy;
149 int xy_buf[2];
152 wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
153 {
154 xy = xy_buf;
155 }
156
157 pc->draw(C, xy, win->eventstate->tablet.tilt, pc->customdata);
158 GPU_scissor_test(false);
159 }
160 }
161}
162
164
165/* -------------------------------------------------------------------- */
171
175static struct {
176 int8_t enabled;
177 int winid;
178 int xy[2];
180 /*enabled*/ -1,
181 /*winid*/ -1,
183
190
192{
193 if (UNLIKELY(g_software_cursor.enabled == -1)) {
195 }
196 return g_software_cursor.enabled;
197}
198
199static bool wm_software_cursor_needed_for_window(const wmWindow *win, GrabState *grab_state)
200{
202 if (GHOST_GetCursorVisibility(static_cast<GHOST_WindowHandle>(win->ghostwin))) {
203 /* NOTE: The value in `win->grabcursor` can't be used as it
204 * doesn't always match GHOST's value in the case of tablet events. */
205 bool use_software_cursor;
206 GHOST_GetCursorGrabState(static_cast<GHOST_WindowHandle>(win->ghostwin),
207 &grab_state->mode,
208 &grab_state->wrap_axis,
209 grab_state->bounds,
210 &use_software_cursor);
211 if (use_software_cursor) {
212 return true;
213 }
214 }
215 return false;
216}
217
219{
220 return (g_software_cursor.winid != win->winid) ||
221 (g_software_cursor.xy[0] != win->eventstate->xy[0]) ||
222 (g_software_cursor.xy[1] != win->eventstate->xy[1]);
223}
224
226{
227
228 g_software_cursor.winid = win->winid;
229 g_software_cursor.xy[0] = win->eventstate->xy[0];
230 g_software_cursor.xy[1] = win->eventstate->xy[1];
231}
232
234{
235 g_software_cursor.winid = -1;
236 g_software_cursor.xy[0] = -1;
237 g_software_cursor.xy[1] = -1;
238}
239
241{
242 if (g_software_cursor.winid == win->winid) {
244 }
245}
246
247static void wm_software_cursor_draw_bitmap(const float system_scale,
248 const int event_xy[2],
249 const GHOST_CursorBitmapRef *bitmap)
250{
252
253 float gl_matrix[4][4];
256 "software_cursor",
257 bitmap->data_size[0],
258 bitmap->data_size[1],
259 1,
260 blender::gpu::TextureFormat::UNORM_8_8_8_8,
261 usage,
262 nullptr);
265
267
268 /* With RGBA cursors, the cursor will have been generated at the correct size,
269 * there is no need to perform additional scaling.
270 *
271 * NOTE: *technically* if a window spans two output of different scales,
272 * we should scale to the output. This use case is currently not accounted for. */
273 const int scale = (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_RGBA) ?
274 1 :
275 std::max(1, round_fl_to_int(system_scale));
276
277 unit_m4(gl_matrix);
278
279 gl_matrix[3][0] = event_xy[0] - (bitmap->hot_spot[0] * scale);
280 gl_matrix[3][1] = event_xy[1] - ((bitmap->data_size[1] - bitmap->hot_spot[1]) * scale);
281
282 gl_matrix[0][0] = bitmap->data_size[0] * scale;
283 gl_matrix[1][1] = bitmap->data_size[1] * scale;
284
285 GPU_matrix_mul(gl_matrix);
286
287 GPUVertFormat *imm_format = immVertexFormat();
289 imm_format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32_32);
290 uint texCoord = GPU_vertformat_attr_add(
291 imm_format, "texCoord", blender::gpu::VertAttrType::SFLOAT_32_32);
292
293 /* Use 3D image for correct display of planar tracked images. */
295
296 immBindTexture("image", texture);
297
299
300 immAttr2f(texCoord, 0.0f, 1.0f);
301 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
302
303 immAttr2f(texCoord, 1.0f, 1.0f);
304 immVertex3f(pos, 1.0f, 0.0f, 0.0f);
305
306 immAttr2f(texCoord, 1.0f, 0.0f);
307 immVertex3f(pos, 1.0f, 1.0f, 0.0f);
308
309 immAttr2f(texCoord, 0.0f, 0.0f);
310 immVertex3f(pos, 0.0f, 1.0f, 0.0f);
311
312 immEnd();
313
315
319
321}
322
323static void wm_software_cursor_draw_crosshair(const float system_scale, const int event_xy[2])
324{
325 /* Draw a primitive cross-hair cursor.
326 * NOTE: the `win->cursor` could be used for drawing although it's complicated as some cursors
327 * are set by the operating-system, where the pixel information isn't easily available. */
328
329 /* The cursor scaled by the "default" size. */
330 const float cursor_scale = float(WM_cursor_preferred_logical_size()) /
332 const float unit = max_ff(system_scale * cursor_scale, 1.0f);
334 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
336
337 immUniformColor4f(1, 1, 1, 1);
338 {
339 const int ofs_line = (8 * unit);
340 const int ofs_size = (2 * unit);
342 event_xy[0] - ofs_line,
343 event_xy[1] - ofs_size,
344 event_xy[0] + ofs_line,
345 event_xy[1] + ofs_size);
347 event_xy[0] - ofs_size,
348 event_xy[1] - ofs_line,
349 event_xy[0] + ofs_size,
350 event_xy[1] + ofs_line);
351 }
352 immUniformColor4f(0, 0, 0, 1);
353 {
354 const int ofs_line = (7 * unit);
355 const int ofs_size = (1 * unit);
357 event_xy[0] - ofs_line,
358 event_xy[1] - ofs_size,
359 event_xy[0] + ofs_line,
360 event_xy[1] + ofs_size);
362 event_xy[0] - ofs_size,
363 event_xy[1] - ofs_line,
364 event_xy[0] + ofs_size,
365 event_xy[1] + ofs_line);
366 }
368}
369
370static void wm_software_cursor_draw(wmWindow *win, const GrabState *grab_state)
371{
372 int event_xy[2] = {UNPACK2(win->eventstate->xy)};
373
374 if (grab_state->wrap_axis & GHOST_kAxisX) {
375 const int min = grab_state->bounds[0];
376 const int max = grab_state->bounds[2];
377 if (min != max) {
378 event_xy[0] = mod_i(event_xy[0] - min, max - min) + min;
379 }
380 }
381 if (grab_state->wrap_axis & GHOST_kAxisY) {
382 const int height = WM_window_native_pixel_y(win);
383 const int min = height - grab_state->bounds[1];
384 const int max = height - grab_state->bounds[3];
385 if (min != max) {
386 event_xy[1] = mod_i(event_xy[1] - max, min - max) + max;
387 }
388 }
389
390 const float system_scale = WM_window_dpi_get_scale(win);
391
392 GHOST_CursorBitmapRef bitmap = {nullptr};
393 if (GHOST_GetCursorBitmap(static_cast<GHOST_WindowHandle>(win->ghostwin), &bitmap) ==
395 {
396 wm_software_cursor_draw_bitmap(system_scale, event_xy, &bitmap);
397 }
398 else {
399 wm_software_cursor_draw_crosshair(system_scale, event_xy);
400 }
401}
402
404
405/* -------------------------------------------------------------------- */
408
409static void wm_region_draw_overlay(bContext *C, const ScrArea *area, ARegion *region)
410{
411 const wmWindow *win = CTX_wm_window(C);
412
413 wmViewport(&region->winrct);
414 UI_SetTheme(area->spacetype, region->regiontype);
415 region->runtime->type->draw_overlay(C, region);
416 wmWindowViewport(win);
417}
418
420
421/* -------------------------------------------------------------------- */
424
426 ScrArea *area,
427 ARegion *region,
428 eStereoViews sview)
429{
430 /* We could detect better when stereo is actually needed, by inspecting the
431 * image in the image editor and sequencer. */
433 return false;
434 }
435
436 switch (area->spacetype) {
437 case SPACE_IMAGE: {
438 if (region->regiontype == RGN_TYPE_WINDOW) {
439 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
440 sima->iuser.multiview_eye = sview;
441 return true;
442 }
443 break;
444 }
445 case SPACE_VIEW3D: {
446 if (region->regiontype == RGN_TYPE_WINDOW) {
447 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
448 if (v3d->camera && v3d->camera->type == OB_CAMERA) {
449 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
450 RenderEngine *engine = rv3d->view_render ? RE_view_engine_get(rv3d->view_render) :
451 nullptr;
452 if (engine && !(engine->type->flag & RE_USE_STEREO_VIEWPORT)) {
453 return false;
454 }
455
456 Camera *cam = static_cast<Camera *>(v3d->camera->data);
457 CameraBGImage *bgpic = static_cast<CameraBGImage *>(cam->bg_images.first);
458 v3d->multiview_eye = sview;
459 if (bgpic) {
460 bgpic->iuser.multiview_eye = sview;
461 }
462 return true;
463 }
464 }
465 break;
466 }
467 case SPACE_NODE: {
468 if (region->regiontype == RGN_TYPE_WINDOW) {
469 SpaceNode *snode = static_cast<SpaceNode *>(area->spacedata.first);
470 if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
471 Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
472 ima->eye = sview;
473 return true;
474 }
475 }
476 break;
477 }
478 case SPACE_SEQ: {
479 SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
480 sseq->multiview_eye = sview;
481
482 if (region->regiontype == RGN_TYPE_PREVIEW) {
483 return true;
484 }
485 }
486 }
487
488 return false;
489}
490
492 ScrArea *area,
493 ARegion *region,
494 bool tag_redraw)
495{
496 if (region->runtime->gizmo_map == nullptr) {
497 return;
498 }
499
500 wmGizmoMap *gzmap = region->runtime->gizmo_map;
502 if (tag_redraw && (gzgroup->type->flag & WM_GIZMOGROUPTYPE_VR_REDRAWS)) {
503 ScrArea *ctx_area = CTX_wm_area(C);
504 ARegion *ctx_region = CTX_wm_region(C);
505
506 CTX_wm_area_set(C, area);
507 CTX_wm_region_set(C, region);
508
509 if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
511 }
512
513 /* Reset. */
514 CTX_wm_area_set(C, ctx_area);
515 CTX_wm_region_set(C, ctx_region);
516 }
517
518 LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
519 if (gz->do_draw) {
520 if (tag_redraw) {
522 }
523 gz->do_draw = false;
524 }
525 }
526 }
527}
528
529static void wm_region_test_render_do_draw(const Scene *scene,
530 Depsgraph *depsgraph,
531 ScrArea *area,
532 ARegion *region)
533{
534 /* Tag region for redraw from render engine preview running inside of it. */
535 if (area->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) {
536 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
537 RenderEngine *engine = rv3d->view_render ? RE_view_engine_get(rv3d->view_render) : nullptr;
538 GPUViewport *viewport = WM_draw_region_get_viewport(region);
539
540 if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
541 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
542 rcti border_rect;
543
544 /* Do partial redraw when possible. */
545 if (ED_view3d_calc_render_border(scene, depsgraph, v3d, region, &border_rect)) {
546 ED_region_tag_redraw_partial(region, &border_rect, false);
547 }
548 else {
550 }
551
552 engine->flag &= ~RE_ENGINE_DO_DRAW;
553 }
554 else if (viewport && GPU_viewport_do_update(viewport)) {
556 }
557 }
558}
559
560#ifdef WITH_XR_OPENXR
561static void wm_region_test_xr_do_draw(const wmWindowManager *wm,
562 const ScrArea *area,
563 ARegion *region)
564{
565 if ((area->spacetype == SPACE_VIEW3D) && (region->regiontype == RGN_TYPE_WINDOW)) {
566 if (ED_view3d_is_region_xr_mirror_active(
567 wm, static_cast<const View3D *>(area->spacedata.first), region))
568 {
570 }
571 }
572}
573#endif
574
575static bool wm_region_use_viewport_by_type(short space_type, short region_type)
576{
577 return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE) &&
578 region_type == RGN_TYPE_WINDOW) ||
579 ((space_type == SPACE_SEQ) && ELEM(region_type, RGN_TYPE_PREVIEW, RGN_TYPE_WINDOW));
580}
581
583{
585}
586
587static const char *wm_area_name(const ScrArea *area)
588{
589#define SPACE_NAME(space) \
590 case space: { \
591 return #space; \
592 }
593 switch (eSpace_Type(area->spacetype)) {
614 }
615#undef SPACE_NAME
616
617 return "Unknown Space";
618}
619
621
622/* -------------------------------------------------------------------- */
627
630
631 void (*draw)(const wmWindow *win, void *customdata);
633};
634
636 void (*draw)(const wmWindow *win, void *customdata),
637 void *customdata)
638{
639 WindowDrawCB *wdc = MEM_callocN<WindowDrawCB>("WindowDrawCB");
640
641 BLI_addtail(&win->drawcalls, wdc);
642 wdc->draw = draw;
643 wdc->customdata = customdata;
644
645 return wdc;
646}
647
648void WM_draw_cb_exit(wmWindow *win, void *handle)
649{
650 LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) {
651 if (wdc == (WindowDrawCB *)handle) {
652 BLI_remlink(&win->drawcalls, wdc);
653 MEM_freeN(wdc);
654 return;
655 }
656 }
657}
658
660{
661 /* Allow callbacks to remove themselves. */
663 wdc->draw(win, wdc->customdata);
664 }
665}
666
668
669/* -------------------------------------------------------------------- */
677
679{
680 if (region->runtime->draw_buffer) {
681 if (region->runtime->draw_buffer->viewport) {
682 GPU_viewport_free(region->runtime->draw_buffer->viewport);
683 }
684 if (region->runtime->draw_buffer->offscreen) {
685 GPU_offscreen_free(region->runtime->draw_buffer->offscreen);
686 }
687
688 MEM_freeN(region->runtime->draw_buffer);
689 region->runtime->draw_buffer = nullptr;
690 }
691}
692
694{
695 /* Setup offscreen color texture for drawing. */
697
698 /* No mipmaps or filtering. */
699 GPU_texture_mipmap_mode(texture, false, false);
700}
701
703{
704 bool use_float = false;
705
710 {
711 use_float = GPU_hdr_support();
712 }
713 blender::gpu::TextureFormat desired_format =
714 (use_float) ? blender::gpu::TextureFormat::SFLOAT_16_16_16_16 :
715 blender::gpu::TextureFormat::UNORM_8_8_8_8;
716 return desired_format;
717}
718
720 ARegion *region,
721 bool stereo,
722 bool use_viewport)
723{
724
725 /* Determine desired offscreen format depending on HDR availability. */
727
728 if (region->runtime->draw_buffer) {
729 if (region->runtime->draw_buffer->stereo != stereo) {
730 /* Free draw buffer on stereo changes. */
732 }
733 else {
734 /* Free offscreen buffer on size changes. Viewport auto resizes. */
735 GPUOffScreen *offscreen = region->runtime->draw_buffer->offscreen;
736 if (offscreen && (GPU_offscreen_width(offscreen) != region->winx ||
737 GPU_offscreen_height(offscreen) != region->winy ||
738 GPU_offscreen_format(offscreen) != desired_format))
739 {
741 }
742 }
743 }
744
745 if (!region->runtime->draw_buffer) {
746 if (use_viewport) {
747 /* Allocate viewport which includes an off-screen buffer with depth multi-sample, etc. */
748 region->runtime->draw_buffer = MEM_callocN<wmDrawBuffer>("wmDrawBuffer");
749 region->runtime->draw_buffer->viewport = stereo ? GPU_viewport_stereo_create() :
751 }
752 else {
753 /* Allocate off-screen buffer if it does not exist. This one has no
754 * depth or multi-sample buffers. 3D view creates its own buffers with
755 * the data it needs. */
756 GPUOffScreen *offscreen = GPU_offscreen_create(region->winx,
757 region->winy,
758 false,
759 desired_format,
761 true,
762 nullptr);
763 if (!offscreen) {
764 WM_global_report(RPT_ERROR, "Region could not be drawn!");
765 return;
766 }
767
769
770 region->runtime->draw_buffer = MEM_callocN<wmDrawBuffer>("wmDrawBuffer");
771 region->runtime->draw_buffer->offscreen = offscreen;
772 }
773
774 region->runtime->draw_buffer->bound_view = -1;
775 region->runtime->draw_buffer->stereo = stereo;
776 }
777}
778
779static void wm_draw_region_bind(ARegion *region, int view)
780{
781 if (!region->runtime->draw_buffer) {
782 return;
783 }
784
785 if (region->runtime->draw_buffer->viewport) {
786 GPU_viewport_bind(region->runtime->draw_buffer->viewport, view, &region->winrct);
787 }
788 else {
789 GPU_offscreen_bind(region->runtime->draw_buffer->offscreen, false);
790
791 /* For now scissor is expected by region drawing, we could disable it
792 * and do the enable/disable in the specific cases that setup scissor. */
793 GPU_scissor_test(true);
794 GPU_scissor(0, 0, region->winx, region->winy);
795 }
796
797 region->runtime->draw_buffer->bound_view = view;
798}
799
800static void wm_draw_region_unbind(ARegion *region)
801{
802 if (!region->runtime->draw_buffer) {
803 return;
804 }
805
806 region->runtime->draw_buffer->bound_view = -1;
807
808 if (region->runtime->draw_buffer->viewport) {
809 GPU_viewport_unbind(region->runtime->draw_buffer->viewport);
810 }
811 else {
812 GPU_scissor_test(false);
813 GPU_offscreen_unbind(region->runtime->draw_buffer->offscreen, false);
814 }
815}
816
817static void wm_draw_region_blit(ARegion *region, int view)
818{
819 if (!region->runtime->draw_buffer) {
820 return;
821 }
822
823 if (view == -1) {
824 /* Non-stereo drawing. */
825 view = 0;
826 }
827 else if (view > 0) {
828 if (region->runtime->draw_buffer->viewport == nullptr) {
829 /* Region does not need stereo or failed to allocate stereo buffers. */
830 view = 0;
831 }
832 }
833
834 if (region->runtime->draw_buffer->viewport) {
835 GPU_viewport_draw_to_screen(region->runtime->draw_buffer->viewport, view, &region->winrct);
836 }
837 else {
839 region->runtime->draw_buffer->offscreen, region->winrct.xmin, region->winrct.ymin);
840 }
841}
842
844{
845 if (!region->runtime->draw_buffer) {
846 return nullptr;
847 }
848
849 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
850 if (viewport) {
851 return GPU_viewport_color_texture(viewport, view);
852 }
853 return GPU_offscreen_color_texture(region->runtime->draw_buffer->offscreen);
854}
855
856void wm_draw_region_blend(ARegion *region, int view, bool blend)
857{
858 if (!region->runtime->draw_buffer) {
859 return;
860 }
861
862 /* Alpha is always 1, except when blend timer is running. */
863 float alpha = ED_region_blend_alpha(region);
864 if (alpha <= 0.0f) {
865 return;
866 }
867
868 if (!blend) {
869 alpha = 1.0f;
870 }
871
872 /* #wmOrtho for the screen has this same offset. */
873 const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&region->winrct) + 1);
874 const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&region->winrct) + 1);
875
876 rcti rect_geo = region->winrct;
877 rect_geo.xmax += 1;
878 rect_geo.ymax += 1;
879
880 rctf rect_tex;
881 rect_tex.xmin = halfx;
882 rect_tex.ymin = halfy;
883 rect_tex.xmax = 1.0f + halfx;
884 rect_tex.ymax = 1.0f + halfy;
885
886 float alpha_easing = 1.0f - alpha;
887 alpha_easing = 1.0f - alpha_easing * alpha_easing;
888
889 /* Slide vertical panels. */
890 float ofs_x = BLI_rcti_size_x(&region->winrct) * (1.0f - alpha_easing);
892 rect_geo.xmin += ofs_x;
893 rect_tex.xmax *= alpha_easing;
894 alpha = 1.0f;
895 }
897 rect_geo.xmax -= ofs_x;
898 rect_tex.xmin += 1.0f - alpha_easing;
899 alpha = 1.0f;
900 }
901
902 /* Not the same layout as #rctf/#rcti. */
903 const float rectt[4] = {rect_tex.xmin, rect_tex.ymin, rect_tex.xmax, rect_tex.ymax};
904 const float rectg[4] = {
905 float(rect_geo.xmin), float(rect_geo.ymin), float(rect_geo.xmax), float(rect_geo.ymax)};
906
907 if (blend) {
908 /* Regions drawn off-screen have pre-multiplied alpha. */
910 }
911
912 /* Setup actual texture. */
914
916 GPU_shader_bind(shader);
917
918 int color_loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR);
919 int rect_tex_loc = GPU_shader_get_uniform(shader, "rect_icon");
920 int rect_geo_loc = GPU_shader_get_uniform(shader, "rect_geom");
921 int texture_bind_loc = GPU_shader_get_sampler_binding(shader, "image");
922
923 GPU_texture_bind(texture, texture_bind_loc);
924
925 GPU_shader_uniform_float_ex(shader, rect_tex_loc, 4, 1, rectt);
926 GPU_shader_uniform_float_ex(shader, rect_geo_loc, 4, 1, rectg);
927 GPU_shader_uniform_float_ex(shader, color_loc, 4, 1, blender::float4{1, 1, 1, 1});
928
929 blender::gpu::Batch *quad = GPU_batch_preset_quad();
930 GPU_batch_set_shader(quad, shader);
932
934
935 if (blend) {
937 }
938}
939
941{
942 if (!region->runtime->draw_buffer) {
943 return nullptr;
944 }
945
946 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
947 return viewport;
948}
949
951{
952 if (!region->runtime->draw_buffer || region->runtime->draw_buffer->bound_view == -1) {
953 return nullptr;
954 }
955
956 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
957 return viewport;
958}
959
960static void wm_draw_area_offscreen(bContext *C, wmWindow *win, ScrArea *area, bool stereo)
961{
963 Main *bmain = CTX_data_main(C);
964
965 CTX_wm_area_set(C, area);
967
968 /* Compute UI layouts for dynamically size regions. */
969 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
970 if (region->flag & RGN_FLAG_POLL_FAILED) {
971 continue;
972 }
973 /* Dynamic region may have been flagged as too small because their size on init is 0.
974 * ARegion.visible is false then, as expected. The layout should still be created then, so
975 * the region size can be updated (it may turn out to be not too small then). */
976 const bool ignore_visibility = (region->flag & RGN_FLAG_DYNAMIC_SIZE) &&
977 (region->flag & RGN_FLAG_TOO_SMALL) &&
978 !(region->flag & RGN_FLAG_HIDDEN);
979
980 if ((region->runtime->visible || ignore_visibility) && region->runtime->do_draw &&
981 region->runtime->type && region->runtime->type->layout)
982 {
983 CTX_wm_region_set(C, region);
984 ED_region_do_layout(C, region);
985 CTX_wm_region_set(C, nullptr);
986 }
987 }
988
989 ED_area_update_region_sizes(wm, win, area);
990
992 if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
995 }
997 }
998
999 /* Then do actual drawing of regions. */
1000 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1001 if (!region->runtime->visible || !region->runtime->do_draw) {
1002 continue;
1003 }
1004
1005 CTX_wm_region_set(C, region);
1006 bool use_viewport = WM_region_use_viewport(area, region);
1007
1008 GPU_debug_group_begin(use_viewport ? "Viewport" : "ARegion");
1009
1010 if (stereo && wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID)) {
1011 Scene *scene = WM_window_get_active_scene(win);
1012 wm_draw_region_buffer_create(scene, region, true, use_viewport);
1013
1014 for (int view = 0; view < 2; view++) {
1015 eStereoViews sview;
1016 if (view == 0) {
1017 sview = STEREO_LEFT_ID;
1018 }
1019 else {
1020 sview = STEREO_RIGHT_ID;
1021 wm_draw_region_stereo_set(bmain, area, region, sview);
1022 }
1023
1024 wm_draw_region_bind(region, view);
1025 ED_region_do_draw(C, region);
1026 wm_draw_region_unbind(region);
1027 }
1028 if (use_viewport) {
1029 GPUViewport *viewport = region->runtime->draw_buffer->viewport;
1031 }
1032 }
1033 else {
1034 wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID);
1035 Scene *scene = WM_window_get_active_scene(win);
1036 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1037 wm_draw_region_bind(region, 0);
1038 ED_region_do_draw(C, region);
1039 wm_draw_region_unbind(region);
1040 }
1041
1043
1044 region->runtime->do_draw = 0;
1045 CTX_wm_region_set(C, nullptr);
1046 }
1047
1048 CTX_wm_area_set(C, nullptr);
1049
1051}
1052
1053static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
1054{
1055 bScreen *screen = WM_window_get_active_screen(win);
1056
1057 /* Draw screen areas into their own frame buffer. Status bar and spreadsheet is drawn
1058 * last, because mesh and memory usage statistics are affected by drawing of other
1059 * editors like the 3D viewport. */
1060 ED_screen_areas_iter (win, screen, area) {
1062 wm_draw_area_offscreen(C, win, area, stereo);
1063 }
1064 }
1065 ED_screen_areas_iter (win, screen, area) {
1067 wm_draw_area_offscreen(C, win, area, stereo);
1068 }
1069 }
1070
1071 /* Draw menus into their own frame-buffer. */
1072 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1073 if (!region->runtime->visible) {
1074 continue;
1075 }
1076 CTX_wm_region_popup_set(C, region);
1077
1078 GPU_debug_group_begin("Menu");
1079
1080 if (region->runtime->type && region->runtime->type->layout) {
1081 /* UI code reads the OpenGL state, but we have to refresh
1082 * the UI layout beforehand in case the menu size changes. */
1083 wmViewport(&region->winrct);
1084 region->runtime->type->layout(C, region);
1085 }
1086
1087 Scene *scene = WM_window_get_active_scene(win);
1088 wm_draw_region_buffer_create(scene, region, false, false);
1089 wm_draw_region_bind(region, 0);
1090 GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
1091 ED_region_do_draw(C, region);
1092 wm_draw_region_unbind(region);
1093
1095
1096 region->runtime->do_draw = 0;
1097 CTX_wm_region_popup_set(C, nullptr);
1098 }
1099}
1100
1102{
1104 bScreen *screen = WM_window_get_active_screen(win);
1105
1106 GPU_debug_group_begin("Window Redraw");
1107
1108 /* Draw into the window frame-buffer, in full window coordinates. */
1109 wmWindowViewport(win);
1110
1111/* We draw on all pixels of the windows so we don't need to clear them before.
1112 * Actually this is only a problem when resizing the window.
1113 * If it becomes a problem we should clear only when window size changes. */
1114#if 0
1115 GPU_clear_color(0, 0, 0, 0);
1116#endif
1117
1118 /* Blit non-overlapping area regions. */
1119 ED_screen_areas_iter (win, screen, area) {
1120 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1121 if (!region->runtime->visible) {
1122 continue;
1123 }
1124
1125 if (region->overlap == false) {
1126 /* Blit from off-screen buffer. */
1127 wm_draw_region_blit(region, view);
1128 }
1129 }
1130 }
1131
1132 /* Draw overlays and paint cursors. */
1133 ED_screen_areas_iter (win, screen, area) {
1134 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1135 if (!region->runtime->visible) {
1136 continue;
1137 }
1138 const bool do_paint_cursor = (wm->runtime->paintcursors.first &&
1139 region == screen->active_region);
1140 const bool do_draw_overlay = (region->runtime->type && region->runtime->type->draw_overlay);
1141 if (!(do_paint_cursor || do_draw_overlay)) {
1142 continue;
1143 }
1144
1145 CTX_wm_area_set(C, area);
1146 CTX_wm_region_set(C, region);
1147 if (do_draw_overlay) {
1148 wm_region_draw_overlay(C, area, region);
1149 }
1150 if (do_paint_cursor) {
1151 wm_paintcursor_draw(C, area, region);
1152 }
1153 CTX_wm_region_set(C, nullptr);
1154 CTX_wm_area_set(C, nullptr);
1155 }
1156 }
1157 wmWindowViewport(win);
1158
1159 /* Blend in overlapping area regions. */
1160 ED_screen_areas_iter (win, screen, area) {
1161 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1162 if (!region->runtime->visible) {
1163 continue;
1164 }
1165 if (region->overlap) {
1166 wm_draw_region_blend(region, 0, true);
1167 }
1168 }
1169 }
1170
1171 /* After area regions so we can do area 'overlay' drawing. */
1172 UI_SetTheme(0, 0);
1174
1175 /* Needs zero offset here or it looks blurry. #128112. */
1176 wmWindowViewport_ex(win, 0.0f);
1177
1178 wm_draw_callbacks(win);
1179 wmWindowViewport(win);
1180
1181 /* Blend in floating regions (menus). */
1182 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1183 if (!region->runtime->visible) {
1184 continue;
1185 }
1186 wm_draw_region_blend(region, 0, true);
1187 }
1188
1189 /* Always draw, not only when screen tagged. */
1190 if (win->gesture.first) {
1191 wm_gesture_draw(win);
1192 wmWindowViewport(win);
1193 }
1194
1195 /* Needs pixel coords in screen. */
1196 if (wm->runtime->drags.first) {
1197 wm_drags_draw(C, win);
1198 wmWindowViewport(win);
1199 }
1200
1202 GrabState grab_state;
1203 if (wm_software_cursor_needed_for_window(win, &grab_state)) {
1204 wm_software_cursor_draw(win, &grab_state);
1206 }
1207 else {
1208 /* Checking the window is needed so one window doesn't clear the cursor state of another. */
1210 }
1211 }
1212
1214}
1215
1217{
1218 GPU_context_begin_frame(static_cast<GPUContext *>(win->gpuctx));
1219
1220 bScreen *screen = WM_window_get_active_screen(win);
1221 bool stereo = WM_stereo3d_enabled(win, false);
1222
1223 /* Draw area regions into their own frame-buffer. This way we can redraw
1224 * the areas that need it, and blit the rest from existing frame-buffers. */
1225 wm_draw_window_offscreen(C, win, stereo);
1226
1227 /* Now we draw into the window frame-buffer, in full window coordinates. */
1228 if (!stereo) {
1229 /* Regular mono drawing. */
1230 wm_draw_window_onscreen(C, win, -1);
1231 }
1233 /* For page-flip we simply draw to both back buffers. */
1235 wm_draw_window_onscreen(C, win, 1);
1236
1238 wm_draw_window_onscreen(C, win, 0);
1239 }
1241 /* For anaglyph and interlace, we draw individual regions with
1242 * stereo frame-buffers using different shaders. */
1243 wm_draw_window_onscreen(C, win, -1);
1244 }
1245 else {
1246 /* Determine desired offscreen format depending on HDR availability. */
1249
1250 /* For side-by-side and top-bottom, we need to render each view to an
1251 * an off-screen texture and then draw it. This used to happen for all
1252 * stereo methods, but it's less efficient than drawing directly. */
1253 const blender::int2 win_size = WM_window_native_pixel_size(win);
1254 GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
1255 win_size[1],
1256 false,
1257 desired_format,
1259 false,
1260 nullptr);
1261
1262 if (offscreen) {
1265
1266 for (int view = 0; view < 2; view++) {
1267 /* Draw view into offscreen buffer. */
1268 GPU_offscreen_bind(offscreen, false);
1270 GPU_offscreen_unbind(offscreen, false);
1271
1272 /* Draw offscreen buffer to screen. */
1274
1275 wmWindowViewport(win);
1278 }
1279 else {
1281 }
1282
1284 }
1285
1286 GPU_offscreen_free(offscreen);
1287 }
1288 else {
1289 /* Still draw something in case of allocation failure. */
1290 wm_draw_window_onscreen(C, win, 0);
1291 }
1292 }
1293
1294 screen->do_draw = false;
1295
1296 GPU_context_end_frame(static_cast<GPUContext *>(win->gpuctx));
1297}
1298
1302static void wm_draw_surface(bContext *C, wmSurface *surface)
1303{
1305 wm_surface_make_drawable(surface);
1306
1308
1309 surface->draw(C);
1310
1312
1313 /* Avoid interference with window drawable. */
1315}
1316
1318
1319/* -------------------------------------------------------------------- */
1324
1326 const wmWindow *win,
1327 int r_size[2])
1328{
1329 /* Don't assert as file-save uses this for a screenshot, where redrawing isn't an option
1330 * because of the side-effects of drawing a window on save.
1331 * In this case the thumbnail might not work and there are currently no better alternatives. */
1332 // BLI_assert(WM_capabilities_flag() & WM_CAPABILITY_GPU_FRONT_BUFFER_READ);
1333
1334 /* WARNING: Reading from the front-buffer immediately after drawing may fail,
1335 * for a slower but more reliable version of this function
1336 * #WM_window_pixels_read_from_offscreen should be preferred.
1337 * See it's comments for details on why it's needed, see also #98462. */
1338 bool setup_context = wm->runtime->windrawable != win;
1339
1340 if (setup_context) {
1341 GHOST_ActivateWindowDrawingContext(static_cast<GHOST_WindowHandle>(win->ghostwin));
1342 GPU_context_active_set(static_cast<GPUContext *>(win->gpuctx));
1343 }
1344
1345 const blender::int2 win_size = WM_window_native_pixel_size(win);
1346 const uint rect_len = win_size[0] * win_size[1];
1347 uint8_t *rect = MEM_malloc_arrayN<uint8_t>(4 * rect_len, __func__);
1348
1349 GPU_frontbuffer_read_color(0, 0, win_size[0], win_size[1], 4, GPU_DATA_UBYTE, rect);
1350
1351 if (setup_context) {
1352 if (wm->runtime->windrawable) {
1354 static_cast<GHOST_WindowHandle>(wm->runtime->windrawable->ghostwin));
1355 GPU_context_active_set(static_cast<GPUContext *>(wm->runtime->windrawable->gpuctx));
1356 }
1357 }
1358
1359 /* Clear alpha, it is not set to a meaningful value in OpenGL. */
1360 uchar *cp = (uchar *)rect;
1361 uint i;
1362 for (i = 0, cp += 3; i < rect_len; i++, cp += 4) {
1363 *cp = 0xff;
1364 }
1365
1366 r_size[0] = win_size[0];
1367 r_size[1] = win_size[1];
1368 return rect;
1369}
1370
1372 const wmWindow *win,
1373 const int pos[2],
1374 float r_col[3])
1375{
1377 bool setup_context = wm->runtime->windrawable != win;
1378
1379 if (setup_context) {
1380 GHOST_ActivateWindowDrawingContext(static_cast<GHOST_WindowHandle>(win->ghostwin));
1381 GPU_context_active_set(static_cast<GPUContext *>(win->gpuctx));
1382 }
1383
1384 /* NOTE(@jbakker): Vulkan backend isn't able to read 3 channels from a 4 channel texture with
1385 * data data-conversions is needed. Data conversion happens inline for all channels. This is a
1386 * vulkan backend issue and should be solved. However the solution has a lot of branches that
1387 * requires testing so a quick fix has been added to the place where this was used. The solution
1388 * is to implement all the cases in 'VKFramebuffer::read'.
1389 */
1390 blender::float4 color_with_alpha;
1391 GPU_frontbuffer_read_color(pos[0], pos[1], 1, 1, 4, GPU_DATA_FLOAT, color_with_alpha);
1392 copy_v3_v3(r_col, color_with_alpha.xyz());
1393
1394 if (setup_context) {
1395 if (wm->runtime->windrawable) {
1397 static_cast<GHOST_WindowHandle>(wm->runtime->windrawable->ghostwin));
1398 GPU_context_active_set(static_cast<GPUContext *>(wm->runtime->windrawable->gpuctx));
1399 }
1400 }
1401}
1402
1404{
1405 /* NOTE(@ideasman42): There is a problem reading the windows front-buffer after redrawing
1406 * the window in some cases (typically to clear UI elements such as menus or search popup).
1407 * With EGL `eglSurfaceAttrib(..)` may support setting the `EGL_SWAP_BEHAVIOR` attribute to
1408 * `EGL_BUFFER_PRESERVED` however not all implementations support this.
1409 * Requesting the ability with `EGL_SWAP_BEHAVIOR_PRESERVED_BIT` can even cause the EGL context
1410 * not to initialize at all.
1411 * Confusingly there are some cases where this *does* work, depending on the state of the window
1412 * and prior calls to swap-buffers, however ensuring the state exactly as needed to satisfy a
1413 * particular GPU back-end is fragile, see #98462.
1414 *
1415 * So provide an alternative to #WM_window_pixels_read that avoids using the front-buffer. */
1416
1417 /* Draw into an off-screen buffer and read its contents. */
1418 const blender::int2 win_size = WM_window_native_pixel_size(win);
1419
1420 /* Determine desired offscreen format depending on HDR availability. */
1423
1424 GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
1425 win_size[1],
1426 false,
1427 desired_format,
1429 false,
1430 nullptr);
1431 if (UNLIKELY(!offscreen)) {
1432 return nullptr;
1433 }
1434
1435 const uint rect_len = win_size[0] * win_size[1];
1436 uint8_t *rect = MEM_malloc_arrayN<uint8_t>(4 * rect_len, __func__);
1437 GPU_offscreen_bind(offscreen, false);
1438 wm_draw_window_onscreen(C, win, -1);
1439 GPU_offscreen_unbind(offscreen, false);
1440 GPU_offscreen_read_color(offscreen, GPU_DATA_UBYTE, rect);
1441 GPU_offscreen_free(offscreen);
1442
1443 r_size[0] = win_size[0];
1444 r_size[1] = win_size[1];
1445 return rect;
1446}
1447
1449 wmWindow *win,
1450 const int pos[2],
1451 float r_col[3])
1452{
1453 /* A version of #WM_window_pixels_read_from_offscreen that reads a single sample. */
1454 const blender::int2 win_size = WM_window_native_pixel_size(win);
1455 zero_v3(r_col);
1456
1457 /* While this shouldn't happen, return in the case it does. */
1458 BLI_assert(uint(pos[0]) < uint(win_size[0]) && uint(pos[1]) < uint(win_size[1]));
1459 if (!(uint(pos[0]) < uint(win_size[0]) && uint(pos[1]) < uint(win_size[1]))) {
1460 return false;
1461 }
1462
1463 GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
1464 win_size[1],
1465 false,
1466 blender::gpu::TextureFormat::UNORM_8_8_8_8,
1468 false,
1469 nullptr);
1470 if (UNLIKELY(!offscreen)) {
1471 return false;
1472 }
1473
1474 float rect_pixel[4];
1475 GPU_offscreen_bind(offscreen, false);
1476 wm_draw_window_onscreen(C, win, -1);
1477 GPU_offscreen_unbind(offscreen, false);
1478 GPU_offscreen_read_color_region(offscreen, GPU_DATA_FLOAT, pos[0], pos[1], 1, 1, rect_pixel);
1479 GPU_offscreen_free(offscreen);
1480 copy_v3_v3(r_col, rect_pixel);
1481 return true;
1482}
1483
1484uint8_t *WM_window_pixels_read(bContext *C, wmWindow *win, int r_size[2])
1485{
1488 }
1489 return WM_window_pixels_read_from_offscreen(C, win, r_size);
1490}
1491
1492bool WM_window_pixels_read_sample(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
1493{
1496 return true;
1497 }
1499}
1500
1502{
1503 return GHOST_GetPixelAtCursor(r_col);
1504}
1505
1507
1508/* -------------------------------------------------------------------- */
1511
1512/* Quick test to prevent changing window drawable. */
1514{
1515 const wmWindowManager *wm = CTX_wm_manager(C);
1516 Scene *scene = WM_window_get_active_scene(win);
1517 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
1518 Depsgraph *depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, view_layer);
1519 bScreen *screen = WM_window_get_active_screen(win);
1520 bool do_draw = false;
1521
1522 LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
1523 if (region->runtime->do_draw_paintcursor) {
1524 screen->do_draw_paintcursor = true;
1525 region->runtime->do_draw_paintcursor = false;
1526 }
1527 if (region->runtime->visible && region->runtime->do_draw) {
1528 do_draw = true;
1529 }
1530 }
1531
1532 ED_screen_areas_iter (win, screen, area) {
1533 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1534 wm_region_test_gizmo_do_draw(C, area, region, true);
1535 wm_region_test_render_do_draw(scene, depsgraph, area, region);
1536#ifdef WITH_XR_OPENXR
1537 wm_region_test_xr_do_draw(wm, area, region);
1538#endif
1539
1540 if (region->runtime->visible && region->runtime->do_draw) {
1541 do_draw = true;
1542 }
1543 }
1544 }
1545
1546 if (do_draw) {
1547 return true;
1548 }
1549
1550 if (screen->do_refresh) {
1551 return true;
1552 }
1553 if (screen->do_draw) {
1554 return true;
1555 }
1556 if (screen->do_draw_gesture) {
1557 return true;
1558 }
1559 if (screen->do_draw_paintcursor) {
1560 return true;
1561 }
1562 if (screen->do_draw_drag) {
1563 return true;
1564 }
1565
1567 GrabState grab_state;
1568 if (wm_software_cursor_needed_for_window(win, &grab_state)) {
1570 return true;
1571 }
1572 }
1573 else {
1574 /* Detect the edge case when the previous draw used the software cursor but this one doesn't,
1575 * it's important to redraw otherwise the software cursor will remain displayed. */
1576 if (g_software_cursor.winid == win->winid) {
1577 return true;
1578 }
1579 }
1580 }
1581
1582#ifndef WITH_XR_OPENXR
1583 UNUSED_VARS(wm);
1584#endif
1585
1586 return false;
1587}
1588
1589/* Clear drawing flags, after drawing is complete so any draw flags set during
1590 * drawing don't cause any additional redraws. */
1592{
1593 bScreen *screen = WM_window_get_active_screen(win);
1594
1595 ED_screen_areas_iter (win, screen, area) {
1596 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
1597 wm_region_test_gizmo_do_draw(C, area, region, false);
1598 }
1599 }
1600
1601 screen->do_draw_gesture = false;
1602 screen->do_draw_paintcursor = false;
1603 screen->do_draw_drag = false;
1604}
1605
1607{
1608 if (win) {
1609 bScreen *screen = WM_window_get_active_screen(win);
1610 screen->do_draw_paintcursor = true;
1611 }
1612}
1613
1615{
1616 Main *bmain = CTX_data_main(C);
1618
1620
1623
1625
1626#ifdef WITH_METAL_BACKEND
1627 /* Reset drawable to ensure GPU context activation happens at least once per frame if only a
1628 * single context exists. This is required to ensure the default framebuffer is updated
1629 * to be the latest backbuffer. */
1631#endif
1632
1633 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
1634#ifdef WIN32
1636 static_cast<GHOST_WindowHandle>(win->ghostwin));
1637
1639 /* Do not update minimized windows, gives issues on Intel (see #33223)
1640 * and AMD (see #50856). it seems logical to skip update for invisible window anyway. */
1641 continue;
1642 }
1643#endif
1644
1645 CTX_wm_window_set(C, win);
1646
1647 if (wm_draw_update_test_window(bmain, C, win)) {
1648 /* Sets context window+screen. */
1649 wm_window_make_drawable(wm, win);
1651
1652 /* Notifiers for screen redraw. */
1653 ED_screen_ensure_updated(C, wm, win);
1654
1655 wm_draw_window(C, win);
1657
1659 }
1660 }
1661
1662 CTX_wm_window_set(C, nullptr);
1663
1664 /* Draw non-windows (surfaces). */
1666
1669}
1670
1671void wm_draw_region_clear(wmWindow *win, ARegion * /*region*/)
1672{
1673 bScreen *screen = WM_window_get_active_screen(win);
1674 screen->do_draw = true;
1675}
1676
1678{
1680}
1681
1683{
1684 /* Function for redraw timer benchmark. */
1685 bool use_viewport = WM_region_use_viewport(area, region);
1686 wmWindow *win = CTX_wm_window(C);
1687 Scene *scene = WM_window_get_active_scene(win);
1688 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1689 wm_draw_region_bind(region, 0);
1690 ED_region_do_draw(C, region);
1691 wm_draw_region_unbind(region);
1692 region->runtime->do_draw = 0;
1693}
1694
1696{
1697 wmWindow *win_prev = CTX_wm_window(C);
1698 ScrArea *area_prev = CTX_wm_area(C);
1699 ARegion *region_prev = CTX_wm_region(C);
1700
1702
1703 CTX_wm_window_set(C, win_prev);
1704 CTX_wm_area_set(C, area_prev);
1705 CTX_wm_region_set(C, region_prev);
1706}
1707
1709
1710/* -------------------------------------------------------------------- */
1719
1720void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type)
1721{
1722 bool use_viewport = wm_region_use_viewport_by_type(space_type, region->regiontype);
1723 wm_draw_region_buffer_create(scene, region, false, use_viewport);
1724}
1725
1727{
1728 wm_draw_region_bind(region, 0);
1729}
1730
1732{
1733 wm_draw_region_unbind(region);
1734}
1735
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:547
@ RPT_ERROR
Definition BKE_report.hh:39
Depsgraph * BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3416
#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(...)
@ 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
@ AREA_FLAG_ACTIVE_TOOL_UPDATE
#define RGN_ALIGN_ENUM_FROM_MASK(align)
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_RIGHT
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ RGN_FLAG_DYNAMIC_SIZE
@ RGN_FLAG_HIDDEN
@ RGN_FLAG_POLL_FAILED
@ RGN_FLAG_TOO_SMALL
#define RGN_TYPE_ANY
@ SNODE_BACKDRAW
eSpace_Type
@ 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
bool ED_node_is_compositor(const SpaceNode *snode)
Definition node_edit.cc:487
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:296
void ED_region_tag_redraw_no_rebuild(ARegion *region)
Definition area.cc:638
void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
Definition area.cc:666
void ED_screen_draw_edges(wmWindow *win)
void ED_region_do_layout(bContext *C, ARegion *region)
Definition area.cc:456
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area)
Definition area.cc:2046
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:654
void ED_region_do_draw(bContext *C, ARegion *region)
Definition area.cc:479
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:57
GHOST_TGrabCursorMode
@ GHOST_kGrabWrap
@ GHOST_kGrabHide
void GPU_batch_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *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
blender::gpu::Texture * GPU_offscreen_color_texture(const GPUOffScreen *offscreen)
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)
@ GPU_BACKBUFFER_LEFT
@ GPU_BACKBUFFER_RIGHT
void GPU_backbuffer_bind(GPUBackBuffer back_buffer_type)
blender::gpu::TextureFormat GPU_offscreen_format(const GPUOffScreen *offscreen)
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, blender::gpu::TextureFormat format, eGPUTextureUsage usage, bool clear, char err_out[256])
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_offscreen_read_color(GPUOffScreen *offscreen, eGPUDataFormat data_format, void *r_data)
void GPU_offscreen_unbind(GPUOffScreen *offscreen, bool restore)
void immEnd()
void immUnbindProgram()
void immBindTexture(const char *name, blender::gpu::Texture *tex)
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immUniformColor4f(float r, float g, float b, float a)
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(blender::gpu::Shader *shader, const char *name)
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
@ GPU_UNIFORM_COLOR
int GPU_shader_get_uniform(blender::gpu::Shader *shader, const char *name)
int GPU_shader_get_builtin_uniform(blender::gpu::Shader *shader, int builtin)
void GPU_shader_uniform_float_ex(blender::gpu::Shader *shader, int location, int length, int array_size, const float *value)
blender::gpu::Shader * GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_2D_IMAGE_RECT_COLOR
@ GPU_SHADER_3D_IMAGE
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
@ 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(GPUBlend blend)
Definition gpu_state.cc:42
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
void GPU_texture_unbind(blender::gpu::Texture *texture)
@ GPU_DATA_UBYTE
@ GPU_DATA_FLOAT
void GPU_texture_mipmap_mode(blender::gpu::Texture *texture, bool use_mipmap, bool use_filter)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_GENERAL
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
void GPU_texture_bind(blender::gpu::Texture *texture, int unit)
void GPU_texture_free(blender::gpu::Texture *texture)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
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)
blender::gpu::Texture * GPU_viewport_color_texture(GPUViewport *viewport, int view)
void GPU_viewport_unbind(GPUViewport *viewport)
#define GLA_PIXEL_OFS
bool IMB_colormanagement_display_is_hdr(const ColorManagedDisplaySettings *display_settings, const char *view_name)
bool IMB_colormanagement_display_is_wide_gamut(const ColorManagedDisplaySettings *display_settings, const char *view_name)
Read Guarded memory(de)allocation.
@ RE_USE_STEREO_VIEWPORT
Definition RE_engine.h:49
@ RE_ENGINE_DO_DRAW
Definition RE_engine.h:60
#define C
Definition RandGen.cpp:29
void UI_SetTheme(int spacetype, int regionid)
#define WM_CURSOR_DEFAULT_LOGICAL_SIZE
Definition WM_api.hh:567
@ WM_CAPABILITY_CURSOR_WARP
Definition WM_api.hh:170
@ WM_CAPABILITY_CURSOR_RGBA
Definition WM_api.hh:207
@ WM_CAPABILITY_GPU_FRONT_BUFFER_READ
Definition WM_api.hh:193
@ WM_GIZMOGROUPTYPE_VR_REDRAWS
#define WM_TOOLSYSTEM_SPACE_MASK
BPy_StructRNA * depsgraph
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
nullptr float
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:64
GHOST_TAxisFlag wrap_axis
Definition wm_draw.cc:187
GHOST_TGrabCursorMode mode
Definition wm_draw.cc:186
int bounds[4]
Definition wm_draw.cc:188
void * first
struct ViewRender * view_render
RenderEngineType * type
Definition RE_engine.h:130
ColorManagedViewSettings view_settings
ColorManagedDisplaySettings display_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:631
WindowDrawCB * prev
Definition wm_draw.cc:629
WindowDrawCB * next
Definition wm_draw.cc:629
void * customdata
Definition wm_draw.cc:632
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:761
wmTabletData tablet
Definition WM_types.hh:786
GPUContext * blender_gpu_context
Definition wm_surface.hh:24
void(* draw)(bContext *)
Definition wm_surface.hh:28
blender::float2 tilt
Definition WM_types.hh:710
WindowManagerRuntimeHandle * runtime
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:659
void WM_draw_region_viewport_unbind(ARegion *region)
Definition wm_draw.cc:1731
static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
Definition wm_draw.cc:693
uint8_t * WM_window_pixels_read_from_frontbuffer(const wmWindowManager *wm, const wmWindow *win, int r_size[2])
Definition wm_draw.cc:1325
static void wm_draw_region_unbind(ARegion *region)
Definition wm_draw.cc:800
static void wm_draw_region_bind(ARegion *region, int view)
Definition wm_draw.cc:779
static void wm_software_cursor_draw_bitmap(const float system_scale, const int event_xy[2], const GHOST_CursorBitmapRef *bitmap)
Definition wm_draw.cc:247
static bool wm_software_cursor_needed_for_window(const wmWindow *win, GrabState *grab_state)
Definition wm_draw.cc:199
uint8_t * WM_window_pixels_read(bContext *C, wmWindow *win, int r_size[2])
Definition wm_draw.cc:1484
blender::gpu::Texture * wm_draw_region_texture(ARegion *region, int view)
Definition wm_draw.cc:843
static bool wm_region_use_viewport_by_type(short space_type, short region_type)
Definition wm_draw.cc:575
static void wm_draw_surface(bContext *C, wmSurface *surface)
Definition wm_draw.cc:1302
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:1371
static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
Definition wm_draw.cc:1053
void WM_draw_region_viewport_ensure(Scene *scene, ARegion *region, short space_type)
Definition wm_draw.cc:1720
static void wm_draw_area_offscreen(bContext *C, wmWindow *win, ScrArea *area, bool stereo)
Definition wm_draw.cc:960
void WM_redraw_windows(bContext *C)
Definition wm_draw.cc:1695
int xy[2]
Definition wm_draw.cc:178
static void wm_draw_region_buffer_free(ARegion *region)
Definition wm_draw.cc:678
static void wm_draw_region_buffer_create(Scene *scene, ARegion *region, bool stereo, bool use_viewport)
Definition wm_draw.cc:719
GPUViewport * WM_draw_region_get_viewport(ARegion *region)
Definition wm_draw.cc:940
void * WM_draw_cb_activate(wmWindow *win, void(*draw)(const wmWindow *win, void *customdata), void *customdata)
Definition wm_draw.cc:635
static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:107
void wm_draw_region_blend(ARegion *region, int view, bool blend)
Definition wm_draw.cc:856
static void wm_draw_update_clear_window(bContext *C, wmWindow *win)
Definition wm_draw.cc:1591
static bool wm_software_cursor_needed()
Definition wm_draw.cc:191
bool WM_region_use_viewport(ScrArea *area, ARegion *region)
Definition wm_draw.cc:582
#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:529
static bool wm_draw_region_stereo_set(Main *bmain, ScrArea *area, ARegion *region, eStereoViews sview)
Definition wm_draw.cc:425
bool WM_window_pixels_read_sample_from_offscreen(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
Definition wm_draw.cc:1448
void WM_draw_cb_exit(wmWindow *win, void *handle)
Definition wm_draw.cc:648
void wm_draw_region_clear(wmWindow *win, ARegion *)
Definition wm_draw.cc:1671
static const char * wm_area_name(const ScrArea *area)
Definition wm_draw.cc:587
static void wm_region_test_gizmo_do_draw(bContext *C, ScrArea *area, ARegion *region, bool tag_redraw)
Definition wm_draw.cc:491
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *)
Definition wm_draw.cc:1606
static blender::gpu::TextureFormat get_hdr_framebuffer_format(const Scene *scene)
Definition wm_draw.cc:702
static struct @131002343213154054037057266272263130272302153112 g_software_cursor
static void wm_software_cursor_draw(wmWindow *win, const GrabState *grab_state)
Definition wm_draw.cc:370
static bool wm_software_cursor_motion_test(const wmWindow *win)
Definition wm_draw.cc:218
static void wm_software_cursor_motion_clear_with_window(const wmWindow *win)
Definition wm_draw.cc:240
void WM_draw_region_viewport_bind(ARegion *region)
Definition wm_draw.cc:1726
GPUViewport * WM_draw_region_get_bound_viewport(ARegion *region)
Definition wm_draw.cc:950
int winid
Definition wm_draw.cc:177
void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
Definition wm_draw.cc:1682
static void wm_draw_region_blit(ARegion *region, int view)
Definition wm_draw.cc:817
uint8_t * WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_size[2])
Definition wm_draw.cc:1403
void WM_draw_region_free(ARegion *region)
Definition wm_draw.cc:1677
static void wm_software_cursor_motion_update(const wmWindow *win)
Definition wm_draw.cc:225
static void wm_region_draw_overlay(bContext *C, const ScrArea *area, ARegion *region)
Definition wm_draw.cc:409
static void wm_draw_window(bContext *C, wmWindow *win)
Definition wm_draw.cc:1216
static bool wm_window_grab_warp_region_is_set(const wmWindow *win)
Definition wm_draw.cc:82
bool WM_desktop_cursor_sample_read(float r_col[3])
Definition wm_draw.cc:1501
void wm_draw_update(bContext *C)
Definition wm_draw.cc:1614
static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win)
Definition wm_draw.cc:1513
static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
Definition wm_draw.cc:1101
static void wm_software_cursor_motion_clear()
Definition wm_draw.cc:233
static void wm_software_cursor_draw_crosshair(const float system_scale, const int event_xy[2])
Definition wm_draw.cc:323
bool WM_window_pixels_read_sample(bContext *C, wmWindow *win, const int pos[2], float r_col[3])
Definition wm_draw.cc:1492
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:140
void wm_stereo3d_draw_topbottom(wmWindow *win, int view)
Definition wm_stereo.cc:91
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_buffer_release(wmWindow *win)
void wm_window_swap_buffer_acquire(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)
float WM_window_dpi_get_scale(const wmWindow *win)
Definition wm_window.cc:700
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)