1
1

Compare commits

...

10 Commits

Author SHA1 Message Date
Julian Eisel
f652e38b37 Avoid own global variable, use existing DRWManager struct 2020-01-27 16:39:18 +01:00
Julian Eisel
d2de88f47b Only cache framebuffers for layers that aren't always redrawn 2020-01-27 16:13:22 +01:00
Julian Eisel
3085b94595 Get draw-layers to work with multiple viewports 2020-01-27 15:14:53 +01:00
Julian Eisel
56ae8edcd4 Use hash, not list to store and lookup DRWLayer items 2020-01-27 13:08:10 +01:00
Julian Eisel
cb34f2ed3e Fix memory leak when only drawing gizmos 2020-01-27 12:46:14 +01:00
Julian Eisel
175f9310cd Merge branch 'master' into temp-gizmo-decoupled-redraws 2020-01-27 12:24:56 +01:00
Julian Eisel
670413d54b Draw-layers: Get it all to work!
Create the framebuffers for caching viewport rendering results, and
"composite" all layers together once each is drawn. Compositing is a bit
of a big word for this, since we basically just draw all layers on top
of each other with alpha blending.
After talking with Jeroen, we decided to keep things simple for now, we
can add more features (like per-layer color-management) and do small
improvements later.
2020-01-24 17:42:37 +01:00
Julian Eisel
f1579f4724 Merge branch 'master' into temp-gizmo-decoupled-redraws 2020-01-24 11:37:52 +01:00
Julian Eisel
0b7c14a70e Initial introduction of DRWLayer abstraction
Used to wrap different drawing steps, i.e. the main scene drawing,
editor overlays and debug text. Later overlays should get their own
layer.
Right now only the drawing commands are wrapped into per layer
callbacks. The idea is to let each draw into different framebuffers and
to composit them together at the end, so that we can avoid redrawing all
layers if only one needs updating.
2020-01-20 16:23:15 +01:00
Julian Eisel
1053fb9d9d Add separate region redraw tag for UI overlays (gizmos) 2020-01-17 17:47:15 +01:00
19 changed files with 461 additions and 102 deletions

View File

@@ -63,6 +63,7 @@ set(SRC
intern/draw_manager.c
intern/draw_manager_data.c
intern/draw_manager_exec.c
intern/draw_manager_layer.c
intern/draw_manager_profiling.c
intern/draw_manager_shader.c
intern/draw_manager_text.c

View File

@@ -104,6 +104,31 @@ DRWManager DST = {NULL};
static ListBase DRW_engines = {NULL, NULL};
static const DRWLayerType drw_layer_scene_main = {
.poll = NULL,
.may_skip = drw_layer_scene_may_skip,
.draw_layer = drw_layer_scene_draw,
};
static const DRWLayerType drw_layer_editor_overlays = {
.poll = drw_layer_editor_overlays_poll,
.may_skip = NULL,
.draw_layer = drw_layer_editor_overlays_draw,
};
static const DRWLayerType drw_layer_debug_stats = {
.poll = drw_layer_debug_stats_poll,
.may_skip = NULL,
.draw_layer = drw_layer_debug_stats_draw,
};
const DRWLayerType DRW_layer_types[] = {
drw_layer_scene_main,
drw_layer_editor_overlays,
drw_layer_debug_stats,
};
const int DRW_layer_types_count = ARRAY_SIZE(DRW_layer_types);
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
memset(dst, 0x0, offsetof(DRWManager, gl_context));
@@ -1485,44 +1510,20 @@ void DRW_draw_view(const bContext *C)
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
}
/**
* Used for both regular and off-screen drawing.
* Need to reset DST before calling this function
*/
void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
RenderEngineType *engine_type,
ARegion *ar,
View3D *v3d,
GPUViewport *viewport,
const bContext *evil_C)
bool drw_layer_scene_may_skip(void)
{
return ED_region_can_redraw_ui_overlays_only(DST.draw_ctx.ar);
}
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
void drw_layer_scene_draw(void)
{
View3D *v3d = DST.draw_ctx.v3d;
Depsgraph *depsgraph = DST.draw_ctx.depsgraph;
ARegion *ar = DST.draw_ctx.ar;
RenderEngineType *engine_type = DST.draw_ctx.engine_type;
const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
/* Setup viewport */
DST.draw_ctx = (DRWContextState){
.ar = ar,
.rv3d = rv3d,
.v3d = v3d,
.scene = scene,
.view_layer = view_layer,
.obact = OBACT(view_layer),
.engine_type = engine_type,
.depsgraph = depsgraph,
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
drw_context_state_init();
drw_viewport_var_init();
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
/* Check if scene needs to perform the populate loop */
const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
@@ -1532,27 +1533,17 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
const bool do_populate_loop = internal_engine || overlays_on || !draw_type_render ||
gpencil_engine_needed;
/* Get list of enabled engines */
drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
drw_engines_data_validate();
/* Update ubos */
DRW_globals_update();
drw_debug_init();
DRW_hair_init();
/* No framebuffer allowed before drawing. */
BLI_assert(GPU_framebuffer_active_get() == NULL);
/* Init engines */
drw_engines_init();
/* Engine caches create offscreen contexts, which require no framebuffer be set. */
GPU_framebuffer_restore();
/* Cache filling */
{
PROFILE_START(stime);
drw_engines_cache_init();
drw_engines_world_update(scene);
drw_engines_world_update(DST.draw_ctx.scene);
/* Only iterate over objects for internal engines or when overlays are enabled */
if (do_populate_loop) {
@@ -1597,7 +1588,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_draw_callbacks_pre_scene();
if (DST.draw_ctx.evil_C) {
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, ar, REGION_DRAW_PRE_VIEW);
}
drw_engines_draw_scene();
@@ -1625,7 +1616,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
if (DST.draw_ctx.evil_C) {
GPU_depth_test(false);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, ar, REGION_DRAW_POST_VIEW);
GPU_depth_test(true);
/* Callback can be nasty and do whatever they want with the state.
* Don't trust them! */
@@ -1635,43 +1626,112 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
GPU_depth_test(false);
drw_engines_draw_text();
GPU_depth_test(true);
}
if (DST.draw_ctx.evil_C) {
/* needed so gizmo isn't obscured */
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
glDisable(GL_DEPTH_TEST);
DRW_draw_gizmo_3d();
}
bool drw_layer_editor_overlays_poll(void)
{
return DST.draw_ctx.evil_C != NULL;
}
DRW_draw_region_info();
void drw_layer_editor_overlays_draw(void)
{
View3D *v3d = DST.draw_ctx.v3d;
Depsgraph *depsgraph = DST.draw_ctx.depsgraph;
ARegion *ar = DST.draw_ctx.ar;
const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
/* annotations - temporary drawing buffer (screenspace) */
/* XXX: Or should we use a proper draw/overlay engine for this case? */
if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
GPU_depth_test(false);
/* XXX: as scene->gpd is not copied for COW yet */
ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
GPU_depth_test(true);
}
drw_state_set(DRW_STATE_WRITE_COLOR);
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
/* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
* 'DRW_draw_region_info' sets the projection in pixel-space. */
GPU_depth_test(false);
DRW_draw_gizmo_2d();
GPU_depth_test(true);
}
/* needed so gizmo isn't obscured */
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
DRW_draw_gizmo_3d();
}
DRW_draw_region_info();
/* annotations - temporary drawing buffer (screenspace) */
/* XXX: Or should we use a proper draw/overlay engine for this case? */
if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
/* XXX: as scene->gpd is not copied for COW yet */
ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
}
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
/* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
* 'DRW_draw_region_info' sets the projection in pixel-space. */
DRW_draw_gizmo_2d();
}
}
bool drw_layer_debug_stats_poll(void)
{
return G.debug_value > 20 && G.debug_value < 30;
}
void drw_layer_debug_stats_draw(void)
{
DRW_stats_reset();
if (G.debug_value > 20 && G.debug_value < 30) {
GPU_depth_test(false);
/* local coordinate visible rect inside region, to accommodate overlapping ui */
const rcti *rect = ED_region_visible_rect(DST.draw_ctx.ar);
DRW_stats_draw(rect);
GPU_depth_test(true);
}
GPU_depth_test(false);
/* local coordinate visible rect inside region, to accommodate overlapping ui */
const rcti *rect = ED_region_visible_rect(DST.draw_ctx.ar);
DRW_stats_draw(rect);
GPU_depth_test(true);
}
/**
* Used for both regular and off-screen drawing.
* Need to reset DST before calling this function
*/
void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
RenderEngineType *engine_type,
ARegion *ar,
View3D *v3d,
GPUViewport *viewport,
const bContext *evil_C)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
/* Setup viewport */
DST.draw_ctx = (DRWContextState){
.ar = ar,
.rv3d = rv3d,
.v3d = v3d,
.scene = scene,
.view_layer = view_layer,
.obact = OBACT(view_layer),
.engine_type = engine_type,
.depsgraph = depsgraph,
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
drw_context_state_init();
drw_viewport_var_init();
/* Get list of enabled engines */
drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
drw_engines_data_validate();
/* Update ubos */
DRW_globals_update();
drw_debug_init();
DRW_hair_init();
/* No framebuffer allowed before drawing. */
BLI_assert(GPU_framebuffer_active_get() == NULL);
/* Draw scene, scene overlays and editor overlays through layers. */
DRW_layers_draw_combined_cached();
if (WM_draw_region_get_bound_viewport(ar)) {
/* Don't unbind the framebuffer yet in this case and let
@@ -2837,6 +2897,7 @@ void DRW_engines_free(void)
DRW_hair_free();
DRW_shape_cache_free();
DRW_stats_free();
DRW_layers_free();
DRW_globals_free();
DrawEngineType *next;

View File

@@ -429,6 +429,17 @@ typedef struct DRWDebugSphere {
float color[4];
} DRWDebugSphere;
/* ------------- DRAW LAYER ------------ */
typedef struct DRWLayerType {
bool (*poll)(void);
bool (*may_skip)(void);
void (*draw_layer)(void);
} DRWLayerType;
const extern DRWLayerType DRW_layer_types[];
const extern int DRW_layer_types_count;
/* ------------- DRAW MANAGER ------------ */
#define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */
@@ -523,6 +534,10 @@ typedef struct DRWManager {
GPUDrawList *draw_list;
/* Global storage of draw-layers which may cache framebuffers for later reuse. Allows decoupled
* redraws of individual layers. */
GHash *layers_hash; /* DRWLayer * */
/** GPU Resource State: Memory storage between drawing. */
struct {
/* High end GPUs supports up to 32 binds per shader stage.
@@ -575,4 +590,15 @@ GPUBatch *drw_cache_procedural_points_get(void);
GPUBatch *drw_cache_procedural_lines_get(void);
GPUBatch *drw_cache_procedural_triangles_get(void);
void DRW_layers_draw_combined_cached(void);
void DRW_layers_free(void);
/* DRWLayer callbacks */
bool drw_layer_scene_may_skip(void);
void drw_layer_scene_draw(void);
bool drw_layer_editor_overlays_poll(void);
void drw_layer_editor_overlays_draw(void);
bool drw_layer_debug_stats_poll(void);
void drw_layer_debug_stats_draw(void);
#endif /* __DRAW_MANAGER_H__ */

View File

@@ -0,0 +1,246 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright 2020, Blender Foundation.
*/
/** \file
* \ingroup draw
*/
#include <stdio.h>
#include "BLI_alloca.h"
#include "BLI_sys_types.h"
#include "draw_manager.h"
typedef struct DRWLayer {
struct DRWLayer *next, *prev;
const DRWLayerType *type;
struct {
/* Store which viewport this layer was cached for, so we invalidate these buffers if the
* viewport changed. */
const GPUViewport *viewport;
GPUFrameBuffer *framebuffer;
/* The texture attached to the framebuffer containing the actual cache. */
GPUTexture *color;
} cache;
} DRWLayer;
/**
* If a layer never skips redrawing, it doesn't make sense to keep its framebuffer attachements
* cached, they just take up GPU memory.
*/
static bool drw_layer_supports_caching(const DRWLayer *layer)
{
return layer->type->may_skip != NULL;
}
static void drw_layer_recreate_textures(DRWLayer *layer)
{
BLI_assert(drw_layer_supports_caching(layer));
DRW_TEXTURE_FREE_SAFE(layer->cache.color);
DRW_texture_ensure_fullscreen_2d(&layer->cache.color, GPU_RGBA8, 0);
GPU_framebuffer_ensure_config(&layer->cache.framebuffer,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(layer->cache.color)});
}
static DRWLayer *drw_layer_create(const DRWLayerType *type, const GPUViewport *viewport)
{
DRWLayer *layer = MEM_callocN(sizeof(*layer), __func__);
layer->type = type;
if (drw_layer_supports_caching(layer)) {
layer->cache.viewport = viewport;
drw_layer_recreate_textures(layer);
}
return layer;
}
static void drw_layer_free(DRWLayer *layer)
{
DRW_TEXTURE_FREE_SAFE(layer->cache.color);
GPU_FRAMEBUFFER_FREE_SAFE(layer->cache.framebuffer);
MEM_SAFE_FREE(layer);
}
static void drw_layer_free_cb(void *layer)
{
drw_layer_free(layer);
}
static void drw_layer_cache_ensure_updated(DRWLayer *layer)
{
const float *size = DRW_viewport_size_get();
BLI_assert(drw_layer_supports_caching(layer));
BLI_assert(layer->cache.color);
layer->cache.viewport = DST.viewport;
/* Ensure updated texture dimensions. */
if ((GPU_texture_width(layer->cache.color) != size[0]) ||
(GPU_texture_height(layer->cache.color) != size[1])) {
drw_layer_recreate_textures(layer);
}
}
static void drw_layer_draw(const DRWLayer *layer)
{
DRW_state_reset();
layer->type->draw_layer();
}
static bool drw_layer_needs_cache_update(const DRWLayer *layer)
{
const float *size = DRW_viewport_size_get();
BLI_assert(drw_layer_supports_caching(layer));
if ((DST.viewport != layer->cache.viewport) ||
(GPU_texture_width(layer->cache.color) != size[0]) ||
(GPU_texture_height(layer->cache.color) != size[1])) {
/* Always update after viewport changed. */
return true;
}
return layer->type->may_skip() == false;
}
static DRWLayer *drw_layer_for_type_ensure(const DRWLayerType *type)
{
if (DST.layers_hash == NULL) {
DST.layers_hash = BLI_ghash_ptr_new_ex("DRW_layers_hash", DRW_layer_types_count);
}
DRWLayer *layer = BLI_ghash_lookup(DST.layers_hash, type);
if (!layer) {
layer = drw_layer_create(type, DST.viewport);
BLI_ghash_insert(DST.layers_hash, (void *)type, layer);
}
/* Could reinsert layer at tail here, so that the next layer to be drawn is likely first in the
* list (or at least close to the top). Iterating isn't that expensive though. */
return layer;
}
void DRW_layers_free(void)
{
if (DST.layers_hash) {
BLI_ghash_free(DST.layers_hash, NULL, drw_layer_free_cb);
DST.layers_hash = NULL;
}
}
static void drw_layers_textures_draw_alpha_over(GPUTexture *tex)
{
drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
/* Draw as texture for final render (without immediate mode). */
GPUBatch *geom = DRW_cache_fullscreen_quad_get();
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE);
GPU_texture_bind(tex, 0);
float mat[4][4];
unit_m4(mat);
GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
GPU_batch_program_use_begin(geom);
GPU_batch_bind(geom);
GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
GPU_batch_program_use_end(geom);
GPU_texture_unbind(tex);
}
void DRW_layers_draw_combined_cached(void)
{
/* Store if poll succeeded, to avoid calling it twice. */
bool *is_layer_visible = BLI_array_alloca(is_layer_visible, DRW_layer_types_count);
BLI_assert(!DST.layers_hash || (DRW_layer_types_count >= BLI_ghash_len(DST.layers_hash)));
GPU_framebuffer_bind(DST.default_framebuffer);
DRW_clear_background();
/* First pass: Update dirty framebuffers and blit into cache. Skip layers that don't support
* caching, we can avoid the costs of a separate framebuffer (and compositing it) then. */
for (int i = 0; i < DRW_layer_types_count; i++) {
const DRWLayerType *layer_type = &DRW_layer_types[i];
if (layer_type->poll && !layer_type->poll()) {
is_layer_visible[i] = false;
continue;
}
is_layer_visible[i] = true;
DRWLayer *layer = drw_layer_for_type_ensure(layer_type);
if (!drw_layer_supports_caching(layer)) {
/* Layer always redraws -> Skip caching and draw directly into the default framebuffer in
* second pass. */
continue;
}
if (!drw_layer_needs_cache_update(layer)) {
continue;
}
drw_layer_cache_ensure_updated(layer);
DRW_clear_background();
drw_layer_draw(layer);
/* Blit the default framebuffer into the layer framebuffer cache. */
GPU_framebuffer_bind(DST.default_framebuffer);
GPU_framebuffer_blit(DST.default_framebuffer, 0, layer->cache.framebuffer, 0, GPU_COLOR_BIT);
}
BLI_assert(GPU_framebuffer_active_get() == DST.default_framebuffer);
DRW_clear_background();
for (int i = 0; i < DRW_layer_types_count; i++) {
if (!is_layer_visible[i]) {
continue;
}
const DRWLayerType *layer_type = &DRW_layer_types[i];
const DRWLayer *layer = drw_layer_for_type_ensure(layer_type);
if (drw_layer_supports_caching(layer)) {
drw_layers_textures_draw_alpha_over(layer->cache.color);
}
else {
/* Uncached layer, draw directly into default framebuffer. */
BLI_assert(GPU_framebuffer_active_get() == DST.default_framebuffer);
drw_layer_draw(layer);
}
}
GPU_framebuffer_bind(DST.default_framebuffer);
}

View File

@@ -353,7 +353,7 @@ static int gizmo_arrow_modal(bContext *C,
}
/* tag the region for redraw */
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(CTX_wm_region(C));
WM_event_add_mousemove(C);
return OPERATOR_RUNNING_MODAL;

View File

@@ -1086,7 +1086,7 @@ static int gizmo_cage2d_modal(bContext *C,
}
/* tag the region for redraw */
ED_region_tag_redraw(CTX_wm_region(C));
ED_region_tag_redraw_ui_overlays(CTX_wm_region(C));
WM_event_add_mousemove(C);
return OPERATOR_RUNNING_MODAL;

View File

@@ -585,7 +585,7 @@ static int gizmo_cage3d_modal(bContext *C,
}
/* tag the region for redraw */
ED_region_tag_redraw(CTX_wm_region(C));
ED_region_tag_redraw_ui_overlays(CTX_wm_region(C));
WM_event_add_mousemove(C);
return OPERATOR_RUNNING_MODAL;

View File

@@ -303,7 +303,7 @@ static int gizmo_move_modal(bContext *C,
zero_v3(move->prop_co);
}
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
inter->prev.tweak_flag = tweak_flag;

View File

@@ -75,6 +75,9 @@ void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct, bo
void ED_region_tag_redraw_overlay(struct ARegion *ar);
void ED_region_tag_redraw_no_rebuild(struct ARegion *ar);
void ED_region_tag_refresh_ui(struct ARegion *ar);
void ED_region_tag_redraw_ui_overlays(struct ARegion *ar);
bool ED_region_can_redraw_ui_overlays_only(const struct ARegion *ar);
void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
void ED_region_panels_ex(const struct bContext *C,

View File

@@ -658,6 +658,13 @@ void ED_region_tag_refresh_ui(ARegion *ar)
}
}
void ED_region_tag_redraw_ui_overlays(ARegion *ar)
{
if (ar) {
ar->do_draw |= RGN_DRAW_UI_OVERLAYS;
}
}
void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct, bool rebuild)
{
if (ar && !(ar->do_draw & RGN_DRAWING)) {
@@ -727,6 +734,16 @@ void ED_area_tag_refresh(ScrArea *sa)
}
}
/**
* For region draw functions to query if they can safe work by not doing a full-redraw, but only
* redrawing UI overlays (gizmos).
*/
bool ED_region_can_redraw_ui_overlays_only(const ARegion *ar)
{
return (ar->do_draw & RGN_DRAW_UI_OVERLAYS) &&
!(ar->do_draw & (RGN_DRAW | RGN_DRAW_PARTIAL | RGN_DRAW_NO_REBUILD));
}
/* *************************************************************** */
/* use NULL to disable it */

View File

@@ -227,7 +227,7 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
if (best.ele) {
ARegion *ar = CTX_wm_region(C);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
// return best.eed ? 0 : -1;
@@ -383,7 +383,7 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index);
ARegion *ar = CTX_wm_region(C);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
// return best.eed ? 0 : -1;

View File

@@ -933,7 +933,7 @@ static int gizmo_ruler_modal(bContext *C,
ruler_info->drag_state_prev.do_thickness = do_thickness;
if (do_draw) {
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
return exit_code;
}
@@ -1187,7 +1187,7 @@ static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent
/* Update the annotation layer. */
view3d_ruler_to_gpencil(C, gzgroup);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
return OPERATOR_FINISHED;
}
}

View File

@@ -276,7 +276,7 @@ static int gizmo2d_modal(bContext *C,
gizmo2d_origin_to_region(ar, origin);
WM_gizmo_set_matrix_location(widget, origin);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
return OPERATOR_RUNNING_MODAL;
}

View File

@@ -1567,7 +1567,7 @@ static int gizmo_modal(bContext *C,
WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
}
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
return OPERATOR_RUNNING_MODAL;
}

View File

@@ -665,19 +665,23 @@ enum {
/** #ARegion.do_draw */
enum {
/* Region must be fully redrawn. */
RGN_DRAW = 1,
RGN_DRAW = (1 << 0),
/* Redraw only part of region, for sculpting and painting to get smoother
* stroke painting on heavy meshes. */
RGN_DRAW_PARTIAL = 2,
RGN_DRAW_PARTIAL = (1 << 1),
/* For outliner, to do faster redraw without rebuilding outliner tree.
* For 3D viewport, to display a new progressive render sample without
* while other buffers and overlays remain unchanged. */
RGN_DRAW_NO_REBUILD = 4,
RGN_DRAW_NO_REBUILD = (1 << 2),
/* Set while region is being drawn. */
RGN_DRAWING = 8,
RGN_DRAWING = (1 << 3),
/* For popups, to refresh UI layout along with drawing. */
RGN_REFRESH_UI = 16,
RGN_REFRESH_UI = (1 << 4),
/* At least UI overlays (currently gizmos only!) should be redrawn. Note that other flags may
still indicate that more than that needs to be redrawn. */
RGN_DRAW_UI_OVERLAYS = (1 << 5),
};
#endif /* __DNA_SCREEN_TYPES_H__ */

View File

@@ -310,7 +310,7 @@ void WM_gizmo_group_remove_by_tool(bContext *C,
if (gzgroup->type == gzgt) {
BLI_assert(gzgroup->parent_gzmap == gzmap);
wm_gizmogroup_free(C, gzgroup);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
}
}
@@ -391,7 +391,7 @@ static int gizmo_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
}
if (redraw) {
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
return OPERATOR_FINISHED;
@@ -924,7 +924,7 @@ wmGizmoGroup *WM_gizmomaptype_group_init_runtime_with_region(wmGizmoMapType *gzm
wm_gizmomap_highlight_set(gzmap, NULL, NULL, 0);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
return gzgroup;
}
@@ -956,7 +956,7 @@ void WM_gizmomaptype_group_unlink(bContext *C,
if (gzgroup->type == gzgt) {
BLI_assert(gzgroup->parent_gzmap == gzmap);
wm_gizmogroup_free(C, gzgroup);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
}
}

View File

@@ -1047,7 +1047,7 @@ bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz
/* tag the region for redraw */
if (C) {
ARegion *ar = CTX_wm_region(C);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
return true;
@@ -1135,7 +1135,7 @@ void wm_gizmomap_modal_set(
WM_cursor_warp(win, UNPACK2(gzmap->gzmap_context.event_xy));
}
}
ED_region_tag_redraw(CTX_wm_region(C));
ED_region_tag_redraw_ui_overlays(CTX_wm_region(C));
WM_event_add_mousemove(C);
}
@@ -1385,7 +1385,7 @@ void WM_gizmoconfig_update(struct Main *bmain)
gzgroup_next = gzgroup->next;
if (gzgroup->tag_remove) {
wm_gizmogroup_free(NULL, gzgroup);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
}
}

View File

@@ -318,7 +318,8 @@ void WM_gizmo_do_msg_notify_tag_refresh(bContext *UNUSED(C),
ARegion *ar = msg_val->owner;
wmGizmoMap *gzmap = msg_val->user_data;
ED_region_tag_redraw(ar);
ED_region_tag_redraw(ar); /* Could possibly avoid full redraw and only tag for UI overlays redraw
in some cases. */
WM_gizmomap_tag_refresh(gzmap);
}

View File

@@ -148,7 +148,7 @@ static void gizmotype_unlink(bContext *C, Main *bmain, wmGizmoType *gzt)
BLI_assert(gzgroup->parent_gzmap == gzmap);
if (gz->type == gzt) {
WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, gz, C);
ED_region_tag_redraw(ar);
ED_region_tag_redraw_ui_overlays(ar);
}
}
}