diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index eb364c35091..3dc5ec0ebce 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -64,7 +64,7 @@ void ED_region_panels(const struct bContext *C, struct ARegion *ar, int verti void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); -void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float alpha); +void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index a1cfc6f91a7..7bb00429eaf 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -223,6 +223,8 @@ void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float r_size[2]); +bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d, + struct ARegion *ar, struct rcti *rect); void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index eb52c06d08f..555e123be97 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1856,11 +1856,12 @@ int ED_area_headersize(void) return (int)(1.3f * UI_UNIT_Y); } -void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) +void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4]) { const int header_height = UI_UNIT_Y; uiStyle *style = UI_GetStyleDraw(); int fontid = style->widget.uifont_id; + GLint scissor[4]; rcti rect; /* background box */ @@ -1873,9 +1874,14 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) rect.ymax = BLI_rcti_size_y(&ar->winrct); + /* setup scissor */ + glGetIntegerv(GL_SCISSOR_BOX, scissor); + glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, + BLI_rcti_size_x(&rect), BLI_rcti_size_y(&rect)); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, alpha); + glColor4fv(fill_color); glRecti(rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1); glDisable(GL_BLEND); @@ -1888,6 +1894,9 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX); BLF_disable(fontid, BLF_CLIPPING); + + /* restore scissor as it was before */ + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 1d2ea8d7305..8fd2c4420f7 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -244,8 +244,10 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) strcpy(str, "Locked"); } - if (str[0]) - ED_region_info_draw(ar, str, block, 0.6f); + if (str[0]) { + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.6f}; + ED_region_info_draw(ar, str, block, fill_color); + } } static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index be325478722..ba12543ff50 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -87,7 +87,8 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, rr = BKE_image_acquire_renderresult(scene, ima); if (rr && rr->text) { - ED_region_info_draw(ar, rr->text, 1, 0.25); + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; + ED_region_info_draw(ar, rr->text, 1, fill_color); } BKE_image_release_renderresult(scene, ima); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 0475724e463..c4229428cd7 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2926,15 +2926,57 @@ static void draw_viewport_fps(Scene *scene, rcti *rect) static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit); -static bool view3d_main_area_do_render_draw(const bContext *C) +static bool view3d_main_area_do_render_draw(Scene *scene) { - Scene *scene = CTX_data_scene(C); RenderEngineType *type = RE_engines_find(scene->r.engine); return (type && type->view_update && type->view_draw); } -static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, const bool draw_border) +bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + rctf viewborder; + bool use_border; + + /* test if there is a 3d view rendering */ + if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene)) + return false; + + /* test if there is a border render */ + if (rv3d->persp == RV3D_CAMOB) + use_border = (scene->r.mode & R_BORDER) != 0; + else + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + + if (!use_border) + return false; + + /* compute border */ + if (rv3d->persp == RV3D_CAMOB) { + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + rect->xmin = CLAMPIS(ar->winrct.xmin + rect->xmin, ar->winrct.xmin, ar->winrct.xmax); + rect->ymin = CLAMPIS(ar->winrct.ymin + rect->ymin, ar->winrct.ymin, ar->winrct.ymax); + rect->xmax = CLAMPIS(ar->winrct.xmin + rect->xmax, ar->winrct.xmin, ar->winrct.xmax); + rect->ymax = CLAMPIS(ar->winrct.ymin + rect->ymax, ar->winrct.ymin, ar->winrct.ymax); + + return true; +} + +static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, bool clip_border, rcti *border_rect) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -2967,39 +3009,12 @@ static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, const b /* background draw */ ED_region_pixelspace(ar); - if (draw_border) { + if (clip_border) { /* for border draw, we only need to clear a subset of the 3d view */ - rctf viewborder; - rcti cliprct; - - if (rv3d->persp == RV3D_CAMOB) { - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false); - - cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - cliprct.xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - cliprct.ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); - } - else { - cliprct.xmin = v3d->render_border.xmin * ar->winx; - cliprct.xmax = v3d->render_border.xmax * ar->winx; - cliprct.ymin = v3d->render_border.ymin * ar->winy; - cliprct.ymax = v3d->render_border.ymax * ar->winy; - } - - cliprct.xmin += ar->winrct.xmin; - cliprct.xmax += ar->winrct.xmin; - cliprct.ymin += ar->winrct.ymin; - cliprct.ymax += ar->winrct.ymin; - - cliprct.xmin = CLAMPIS(cliprct.xmin, ar->winrct.xmin, ar->winrct.xmax); - cliprct.ymin = CLAMPIS(cliprct.ymin, ar->winrct.ymin, ar->winrct.ymax); - cliprct.xmax = CLAMPIS(cliprct.xmax, ar->winrct.xmin, ar->winrct.xmax); - cliprct.ymax = CLAMPIS(cliprct.ymax, ar->winrct.ymin, ar->winrct.ymax); - - if (cliprct.xmax > cliprct.xmin && cliprct.ymax > cliprct.ymin) { + if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) { glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(cliprct.xmin, cliprct.ymin, BLI_rcti_size_x(&cliprct), BLI_rcti_size_y(&cliprct)); + glScissor(border_rect->xmin, border_rect->ymin, + BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect)); } else { return false; @@ -3021,7 +3036,7 @@ static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, const b if (v3d->flag & V3D_DISPBGPICS) view3d_draw_bgpic(scene, ar, v3d, true, true); - if (draw_border) { + if (clip_border) { /* restore scissor as it was before */ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } @@ -3029,12 +3044,31 @@ static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, const b return true; } -static void view3d_main_area_draw_engine_info(RegionView3D *rv3d, ARegion *ar) +static void view3d_main_area_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border) { + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; + if (!rv3d->render_engine || !rv3d->render_engine->text) return; + + if (render_border) { + /* draw darkened background color. no alpha because border render does + * partial redraw and will not redraw the area behind this info bar */ + float alpha = 1.0f - fill_color[3]; + + if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) { + Camera *ca = v3d->camera->data; - ED_region_info_draw(ar, rv3d->render_engine->text, 1, 0.25); + if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT)) + alpha *= (1.0f - ca->passepartalpha); + } + + UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); + mul_v3_fl(fill_color, alpha); + fill_color[3] = 1.0f; + } + + ED_region_info_draw(ar, rv3d->render_engine->text, 1, fill_color); } /* @@ -3384,7 +3418,7 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const } -static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const char *grid_unit) +static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const char *grid_unit, bool render_border) { wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); @@ -3431,7 +3465,7 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha } if (rv3d->render_engine) { - view3d_main_area_draw_engine_info(rv3d, ar); + view3d_main_area_draw_engine_info(v3d, rv3d, ar, render_border); return; } @@ -3462,17 +3496,17 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); const char *grid_unit = NULL; - bool draw_border = false; + rcti border_rect; + bool render_border, clip_border; - if (rv3d->persp == RV3D_CAMOB) - draw_border = (scene->r.mode & R_BORDER) != 0; - else - draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + /* if we only redraw render border area, skip opengl draw and also + * don't do scissor because it's already set */ + render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect); + clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect)); /* draw viewport using opengl */ - if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { + if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); #ifdef DEBUG_DRAW bl_debug_draw(); @@ -3482,9 +3516,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) /* draw viewport using external renderer */ if (v3d->drawtype == OB_RENDER) - view3d_main_area_draw_engine(C, ar, draw_border); + view3d_main_area_draw_engine(C, ar, clip_border, &border_rect); - view3d_main_area_draw_info(C, ar, grid_unit); + view3d_main_area_draw_info(C, ar, grid_unit, render_border); v3d->flag |= V3D_INVALID_BACKBUF; } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index e437d7c0958..396c827fe25 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -53,6 +53,7 @@ #include "GHOST_C-api.h" +#include "ED_view3d.h" #include "ED_screen.h" #include "GPU_draw.h" @@ -125,14 +126,24 @@ static int wm_area_test_invalid_backbuf(ScrArea *sa) return 1; } -static void wm_region_test_render_do_draw(ScrArea *sa, ARegion *ar) +static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion *ar) { + /* tag region for redraw from render engine preview running inside of it */ if (sa->spacetype == SPACE_VIEW3D) { RegionView3D *rv3d = ar->regiondata; RenderEngine *engine = (rv3d) ? rv3d->render_engine : NULL; if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { - ar->do_draw = TRUE; + Scene *scene = screen->scene; + View3D *v3d = sa->spacedata.first; + rcti border_rect; + + /* do partial redraw when possible */ + if (ED_view3d_calc_render_border(scene, v3d, ar, &border_rect)) + ED_region_tag_redraw_partial(ar, &border_rect); + else + ED_region_tag_redraw(ar); + engine->flag &= ~RE_ENGINE_DO_DRAW; } } @@ -710,7 +721,7 @@ static int wm_draw_update_test_window(wmWindow *win) for (sa = win->screen->areabase.first; sa; sa = sa->next) { for (ar = sa->regionbase.first; ar; ar = ar->next) { - wm_region_test_render_do_draw(sa, ar); + wm_region_test_render_do_draw(win->screen, sa, ar); if (ar->swinid && ar->do_draw) do_draw = TRUE;