diff options
38 files changed, 703 insertions, 1052 deletions
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index cc7e8701320..5df49752634 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -535,8 +535,6 @@ class USERPREF_PT_system(Panel): col.separator() - col.label(text="Window Draw Method:") - col.prop(system, "window_draw_method", text="") col.prop(system, "multi_sample", text="") if sys.platform == "linux" and system.multi_sample != 'NONE': col.label(text="Might fail for Mesh editing selection!") diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 69b5e7ea6fe..17cca92c1fc 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -140,6 +140,8 @@ typedef struct ARegionType { void (*exit)(struct wmWindowManager *, struct ARegion *); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); + /* optional, refresh popup before drawing */ + void (*refresh)(const struct bContext *, struct ARegion *); /* snap the size of the region (can be NULL for no snapping). */ int (*snap_size)(const struct ARegion *ar, int size, int axis); /* contextual changes should be handled here */ diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 77f7b5f847e..ece68884f5c 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -184,6 +184,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) newar->manipulator_map = NULL; newar->regiontimer = NULL; newar->headerstr = NULL; + newar->draw_buffer = NULL; /* use optional regiondata callback */ if (ar->regiondata) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c1539d7edf1..3980c860641 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6362,7 +6362,6 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) rv3d->sms = NULL; rv3d->smooth_timer = NULL; rv3d->compositor = NULL; - rv3d->viewport = NULL; } } } @@ -6377,10 +6376,10 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) ar->headerstr = NULL; ar->visible = 0; ar->type = NULL; - ar->swap = 0; ar->do_draw = 0; ar->manipulator_map = NULL; ar->regiontimer = NULL; + ar->draw_buffer = NULL; memset(&ar->drawrct, 0, sizeof(ar->drawrct)); } @@ -6868,10 +6867,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) BLI_listbase_clear(&win->handlers); BLI_listbase_clear(&win->modalhandlers); BLI_listbase_clear(&win->gesture); - BLI_listbase_clear(&win->drawdata); - win->drawmethod = -1; - win->drawfail = 0; win->active = 0; win->cursor = 0; @@ -7388,7 +7384,6 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) sc->regionbase.first = sc->regionbase.last= NULL; sc->context = NULL; sc->active_region = NULL; - sc->swap = 0; sc->preview = direct_link_preview_image(fd, sc->preview); diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index cf76bfdeef5..13bf5426a5d 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -102,10 +102,12 @@ void DRW_draw_render_loop_ex( struct Depsgraph *depsgraph, struct RenderEngineType *engine_type, struct ARegion *ar, struct View3D *v3d, + struct GPUViewport *viewport, const struct bContext *evil_C); void DRW_draw_render_loop( struct Depsgraph *depsgraph, - struct ARegion *ar, struct View3D *v3d); + struct ARegion *ar, struct View3D *v3d, + struct GPUViewport *viewport); void DRW_draw_render_loop_offscreen( struct Depsgraph *depsgraph, struct RenderEngineType *engine_type, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 6550fa19105..6e8f9d50aae 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1041,42 +1041,46 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) Scene *scene = update_ctx->scene; ViewLayer *view_layer = update_ctx->view_layer; - if (rv3d->viewport == NULL) { - return; - } + /* Separate update for each stereo view. */ + for (int view = 0; view < 2; view++) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, view); + if (!viewport) { + continue; + } - /* XXX Really nasty locking. But else this could - * be executed by the material previews thread - * while rendering a viewport. */ - BLI_mutex_lock(&DST.ogl_context_mutex); + /* XXX Really nasty locking. But else this could + * be executed by the material previews thread + * while rendering a viewport. */ + BLI_mutex_lock(&DST.ogl_context_mutex); - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); - DST.viewport = rv3d->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, .object_mode = OB_MODE_OBJECT, - }; + DST.viewport = 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, .object_mode = OB_MODE_OBJECT, + }; - drw_engines_enable(view_layer, engine_type); + drw_engines_enable(view_layer, engine_type); - for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { - DrawEngineType *draw_engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *draw_engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); - if (draw_engine->view_update) { - draw_engine->view_update(data); + if (draw_engine->view_update) { + draw_engine->view_update(data); + } } - } - DST.viewport = NULL; + DST.viewport = NULL; - drw_engines_disable(); + drw_engines_disable(); - BLI_mutex_unlock(&DST.ogl_context_mutex); + BLI_mutex_unlock(&DST.ogl_context_mutex); + } } /** \} */ @@ -1099,28 +1103,34 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id) Depsgraph *depsgraph = update_ctx->depsgraph; Scene *scene = update_ctx->scene; ViewLayer *view_layer = update_ctx->view_layer; - if (rv3d->viewport == NULL) { - return; - } - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - DST.viewport = rv3d->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, .object_mode = OB_MODE_OBJECT, - }; - drw_engines_enable(view_layer, engine_type); - for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { - DrawEngineType *draw_engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); - if (draw_engine->id_update) { - draw_engine->id_update(data, id); + + /* Separate update for each stereo view. */ + for (int view = 0; view < 2; view++) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, view); + if (!viewport) { + continue; + } + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.viewport = 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, .object_mode = OB_MODE_OBJECT, + }; + drw_engines_enable(view_layer, engine_type); + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *draw_engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); + if (draw_engine->id_update) { + draw_engine->id_update(data, id); + } } + DST.viewport = NULL; + drw_engines_disable(); } - DST.viewport = NULL; - drw_engines_disable(); } /** \} */ @@ -1140,10 +1150,11 @@ void DRW_draw_view(const bContext *C) View3D *v3d = CTX_wm_view3d(C); Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, C); + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); } /** @@ -1154,6 +1165,7 @@ void DRW_draw_render_loop_ex( struct Depsgraph *depsgraph, RenderEngineType *engine_type, ARegion *ar, View3D *v3d, + GPUViewport *viewport, const bContext *evil_C) { @@ -1163,7 +1175,7 @@ void DRW_draw_render_loop_ex( DST.draw_ctx.evil_C = evil_C; - DST.viewport = rv3d->viewport; + DST.viewport = viewport; v3d->zbuf = true; /* Setup viewport */ @@ -1298,7 +1310,8 @@ void DRW_draw_render_loop_ex( void DRW_draw_render_loop( struct Depsgraph *depsgraph, - ARegion *ar, View3D *v3d) + ARegion *ar, View3D *v3d, + GPUViewport *viewport) { /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1306,7 +1319,7 @@ void DRW_draw_render_loop( Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); - DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL); + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL); } /* @viewport CAN be NULL, in this case we create one. */ @@ -1316,18 +1329,10 @@ void DRW_draw_render_loop_offscreen( const bool draw_background, GPUOffScreen *ofs, GPUViewport *viewport) { - RegionView3D *rv3d = ar->regiondata; - - /* backup */ - void *backup_viewport = rv3d->viewport; - { - /* backup (_never_ use rv3d->viewport) */ - if (viewport == NULL) { - rv3d->viewport = GPU_viewport_create_from_offscreen(ofs); - } - else { - rv3d->viewport = viewport; - } + /* Create temporary viewport if needed. */ + GPUViewport *render_viewport = viewport; + if (viewport == NULL) { + render_viewport = GPU_viewport_create_from_offscreen(ofs); } GPU_framebuffer_restore(); @@ -1336,17 +1341,13 @@ void DRW_draw_render_loop_offscreen( drw_state_prepare_clean_for_draw(&DST); DST.options.is_image_render = true; DST.options.draw_background = draw_background; - DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL); - - /* restore */ - { - if (viewport == NULL) { - /* don't free data owned by 'ofs' */ - GPU_viewport_clear_from_offscreen(rv3d->viewport); - GPU_viewport_free(rv3d->viewport); - } + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, render_viewport, NULL); - rv3d->viewport = backup_viewport; + /* Free temporary viewport. */ + if (viewport == NULL) { + /* don't free data owned by 'ofs' */ + GPU_viewport_clear_from_offscreen(render_viewport); + GPU_viewport_free(render_viewport); } /* we need to re-bind (annoying!) */ @@ -1516,10 +1517,6 @@ void DRW_draw_select_loop( /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); - /* backup (_never_ use rv3d->viewport) */ - void *backup_viewport = rv3d->viewport; - rv3d->viewport = NULL; - bool use_obedit = false; int obedit_mode = 0; if (obedit != NULL) { @@ -1646,9 +1643,6 @@ void DRW_draw_select_loop( /* Cleanup for selection state */ GPU_viewport_free(viewport); - - /* restore */ - rv3d->viewport = backup_viewport; #endif /* USE_GPU_SELECT */ } @@ -1702,10 +1696,6 @@ void DRW_draw_depth_loop( DRW_opengl_context_enable(); - /* backup (_never_ use rv3d->viewport) */ - void *backup_viewport = rv3d->viewport; - rv3d->viewport = NULL; - /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1802,9 +1792,6 @@ void DRW_draw_depth_loop( gpuPopMatrix(); gpuPopProjectionMatrix(); - - /* restore */ - rv3d->viewport = backup_viewport; } /** \} */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index b4857051c89..b5f1d947076 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -88,7 +88,7 @@ void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_col void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw); void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); -float ED_region_blend_factor(struct ARegion *ar); +float ED_region_blend_alpha(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); int ED_region_snap_size_test(const struct ARegion *ar); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index f84347b97a4..97491d365b7 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -644,7 +644,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w /* prevent drawing outside widget area */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h); + glScissor(rect->xmin, rect->ymin, w, h); #endif glEnable(GL_BLEND); @@ -773,7 +773,7 @@ static void histogram_draw_one( #define HISTOGRAM_TOT_GRID_LINES 4 -void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) +void ui_draw_but_HISTOGRAM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { Histogram *hist = (Histogram *)but->poin; int res = hist->x_resolution; @@ -800,8 +800,8 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) /* need scissor test, histogram can draw outside of boundary */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + (rect.xmin - 1), - ar->winrct.ymin + (rect.ymin - 1), + glScissor((rect.xmin - 1), + (rect.ymin - 1), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); @@ -873,7 +873,7 @@ static void waveform_draw_one(float *waveform, int nbr, const float col[3]) GWN_batch_discard(batch); } -void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) +void ui_draw_but_WAVEFORM(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { Scopes *scopes = (Scopes *)but->poin; GLint scissor[4]; @@ -923,8 +923,8 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), /* need scissor test, waveform can draw outside of boundary */ glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + (rect.xmin - 1), - ar->winrct.ymin + (rect.ymin - 1), + glScissor((rect.xmin - 1), + (rect.ymin - 1), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); @@ -1160,7 +1160,7 @@ static void vectorscope_draw_target(unsigned int pos, float centerx, float cente immEnd(); } -void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) +void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */ Scopes *scopes = (Scopes *)but->poin; @@ -1195,8 +1195,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco /* need scissor test, hvectorscope can draw outside of boundary */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + (rect.xmin - 1), - ar->winrct.ymin + (rect.ymin - 1), + glScissor((rect.xmin - 1), + (rect.ymin - 1), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); @@ -1622,12 +1622,13 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); rcti scissor_new = { - .xmin = ar->winrct.xmin + rect->xmin, - .ymin = ar->winrct.ymin + rect->ymin, - .xmax = ar->winrct.xmin + rect->xmax, - .ymax = ar->winrct.ymin + rect->ymax + .xmin = rect->xmin, + .ymin = rect->ymin, + .xmax = rect->xmax, + .ymax = rect->ymax }; - BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new); + rcti scissor_region = {0, ar->winx, 0, ar->winy}; + BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new); glScissor(scissor_new.xmin, scissor_new.ymin, BLI_rcti_size_x(&scissor_new), @@ -1822,7 +1823,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, const rcti immUnbindProgram(); } -void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) +void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti) { bool ok = false; MovieClipScopes *scopes = (MovieClipScopes *)but->poin; @@ -1843,8 +1844,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc /* need scissor test, preview image can draw outside of boundary */ GLint scissor[4]; glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + (rect.xmin - 1), - ar->winrct.ymin + (rect.ymin - 1), + glScissor((rect.xmin - 1), + (rect.ymin - 1), (rect.xmax + 1) - (rect.xmin - 1), (rect.ymax + 1) - (rect.ymin - 1)); @@ -1881,7 +1882,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc gpuPushMatrix(); /* draw content of pattern area */ - glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, scissor[2], scissor[3]); + glScissor(rect.xmin, rect.ymin, scissor[2], scissor[3]); if (width > 0 && height > 0) { ImBuf *drawibuf = scopes->track_preview; @@ -1898,8 +1899,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc /* draw cross for pixel position */ gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]); - glScissor(ar->winrct.xmin + rect.xmin, - ar->winrct.ymin + rect.ymin, + glScissor(rect.xmin, + rect.ymin, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect)); @@ -1977,13 +1978,15 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol glGetIntegerv(GL_SCISSOR_BOX, scissor); rcti scissor_new = { - .xmin = ar->winrct.xmin + recti->xmin, - .ymin = ar->winrct.ymin + recti->ymin, - .xmax = ar->winrct.xmin + recti->xmax, - .ymax = ar->winrct.ymin + recti->ymax + .xmin = recti->xmin, + .ymin = recti->ymin, + .xmax = recti->xmax, + .ymax = recti->ymax }; - BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new); + rcti scissor_region = {0, ar->winx, 0, ar->winy}; + + BLI_rcti_isect(&scissor_new, &scissor_region, &scissor_new); glScissor(scissor_new.xmin, scissor_new.ymin, BLI_rcti_size_x(&scissor_new), diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index b13d9b0448c..56611627a67 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -300,7 +300,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, /** \name Menu Block Creation * \{ */ -static void ui_block_region_draw(const bContext *C, ARegion *ar) +static void ui_block_region_refresh(const bContext *C, ARegion *ar) { ScrArea *ctx_area = CTX_wm_area(C); ARegion *ctx_region = CTX_wm_region(C); @@ -331,6 +331,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) CTX_wm_area_set((bContext *)C, ctx_area); CTX_wm_region_set((bContext *)C, ctx_region); +} + +static void ui_block_region_draw(const bContext *C, ARegion *ar) +{ + uiBlock *block; for (block = ar->uiblocks.first; block; block = block->next) UI_block_draw(C, block); @@ -660,6 +665,7 @@ uiPopupBlockHandle *ui_popup_block_create( memset(&type, 0, sizeof(ARegionType)); type.draw = ui_block_region_draw; + type.refresh = ui_block_region_refresh; type.regionid = RGN_TYPE_TEMPORARY; ar->type = &type; diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index ade69050622..d284bde6ce6 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -2171,10 +2171,6 @@ void init_userdef_do_versions(void) strcpy(km->idname, "Property Editor"); } } - if (!USER_VERSION_ATLEAST(250, 16)) { - if (U.wmdrawmethod == USER_DRAW_TRIPLE) - U.wmdrawmethod = USER_DRAW_AUTOMATIC; - } if (!USER_VERSION_ATLEAST(252, 3)) { if (U.flag & USER_LMOUSESELECT) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 0f9378d0a41..a17f7ec6255 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1075,18 +1075,16 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar) } /* overlapping regions only in the following restricted cases */ -static bool region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar) +static bool region_is_overlap(ScrArea *sa, ARegion *ar) { if (U.uiflag2 & USER_REGION_OVERLAP) { - if (WM_is_draw_triple(win)) { - if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ)) { - if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) - return 1; - } - else if (sa->spacetype == SPACE_IMAGE) { - if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW)) - return 1; - } + if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ)) { + if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS)) + return 1; + } + else if (sa->spacetype == SPACE_IMAGE) { + if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW)) + return 1; } } @@ -1113,7 +1111,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti alignment = ar->alignment & ~RGN_SPLIT_PREV; /* set here, assuming userpref switching forces to call this again */ - ar->overlap = region_is_overlap(win, sa, ar); + ar->overlap = region_is_overlap(sa, ar); /* clear state flags first */ ar->flag &= ~RGN_FLAG_TOO_SMALL; @@ -2062,14 +2060,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c if (ar->overlap) { /* view should be in pixelspace */ UI_view2d_view_restore(C); - glEnable(GL_BLEND); - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); - immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1); - immUnbindProgram(); - glDisable(GL_BLEND); + + float back[4]; + UI_GetThemeColor4fv((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK, back); + glClearColor(back[3] * back[0], back[3] * back[1], back[3] * back[2], back[3]); + glClear(GL_COLOR_BUFFER_BIT); } else { UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK); @@ -2278,7 +2273,7 @@ void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float /* setup scissor */ glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, + glScissor(rect.xmin, rect.ymin, BLI_rcti_size_x(&rect) + 1, BLI_rcti_size_y(&rect) + 1); glEnable(GL_BLEND); diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 4b388059ca3..fec39ade110 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -438,8 +438,6 @@ void ED_screen_draw_edges(wmWindow *win) ScrArea *sa; - wmWindowViewport(win); - unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index ab58d4c8ebf..c7d1605cbbf 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -908,7 +908,7 @@ void ED_region_exit(bContext *C, ARegion *ar) WM_event_remove_handlers(C, &ar->handlers); WM_event_modal_handler_region_replace(win, ar, NULL); - ar->visible = 0; + WM_draw_region_free(ar); if (ar->headerstr) { MEM_freeN(ar->headerstr); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 7dab2c7c3db..847afb5f9f1 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4207,7 +4207,7 @@ typedef struct RegionAlphaInfo { #define TIMEOUT 0.2f #define TIMESTEP 0.04f -float ED_region_blend_factor(ARegion *ar) +float ED_region_blend_alpha(ARegion *ar) { /* check parent too */ if (ar->regiontimer == NULL && (ar->alignment & RGN_SPLIT_PREV) && ar->prev) { diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index fad35060d72..6875971de24 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1788,7 +1788,7 @@ static void outliner_draw_tree( CLAMP_MIN(mask_x, 0); glGetFloatv(GL_SCISSOR_BOX, scissor); - glScissor(ar->winrct.xmin, ar->winrct.ymin, mask_x, ar->winy); + glScissor(0, 0, mask_x, ar->winy); } // gray hierarchy lines diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 4fb4193517b..1a23dd0feff 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -545,13 +545,6 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) GPU_offscreen_free(rv3d->gpuoffscreen); rv3d->gpuoffscreen = NULL; } - - if (rv3d->viewport) { - DRW_opengl_context_enable(); - GPU_viewport_free(rv3d->viewport); - DRW_opengl_context_disable(); - rv3d->viewport = NULL; - } } static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) @@ -729,11 +722,6 @@ static void view3d_main_region_free(ARegion *ar) if (rv3d->gpuoffscreen) { GPU_offscreen_free(rv3d->gpuoffscreen); } - if (rv3d->viewport) { - DRW_opengl_context_enable(); - GPU_viewport_free(rv3d->viewport); - DRW_opengl_context_disable(); - } MEM_freeN(rv3d); ar->regiondata = NULL; @@ -758,7 +746,6 @@ static void *view3d_main_region_duplicate(void *poin) new->sms = NULL; new->smooth_timer = NULL; new->compositor = NULL; - new->viewport = NULL; return new; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 166684e7230..3bc86a82afd 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1259,19 +1259,8 @@ RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype) void view3d_main_region_draw(const bContext *C, ARegion *ar) { View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = ar->regiondata; - - if (!rv3d->viewport) { - rv3d->viewport = GPU_viewport_create(); - } - GPU_viewport_bind(rv3d->viewport, &ar->winrct); view3d_draw_view(C, ar); - GPU_viewport_unbind(rv3d->viewport); - - rcti rect = ar->winrct; - BLI_rcti_translate(&rect, -ar->winrct.xmin, -ar->winrct.ymin); - GPU_viewport_draw_to_screen(rv3d->viewport, &rect); GPU_free_images_old(); GPU_pass_cache_garbage_collect(); @@ -1279,7 +1268,6 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) v3d->flag |= V3D_INVALID_BACKBUF; } - /* -------------------------------------------------------------------- */ /** \name Offscreen Drawing diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index eecd185aedf..15359dcd6d6 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -266,8 +266,6 @@ static void backdrawview3d( if (rv3d->gpuoffscreen) GPU_offscreen_unbind(rv3d->gpuoffscreen, true); - else - ar->swap = 0; /* mark invalid backbuf for wm draw */ v3d->flag &= ~V3D_INVALID_BACKBUF; diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index c99733ec6da..61dd899f3d9 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -185,6 +185,7 @@ void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs, bool save); void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore); void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); +void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y); int GPU_offscreen_width(const GPUOffScreen *ofs); int GPU_offscreen_height(const GPUOffScreen *ofs); struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs); diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index ca7d5ae7ceb..d63911374ae 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -119,6 +119,8 @@ double *GPU_viewport_cache_time_get(GPUViewport *viewport); void GPU_viewport_tag_update(GPUViewport *viewport); bool GPU_viewport_do_update(GPUViewport *viewport); +GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport); + /* Texture pool */ GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format); diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index 73a1f14b9f6..3f89adfd8a5 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -719,6 +719,24 @@ void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore) } } +void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y) +{ + const int w = GPU_texture_width(ofs->color); + const int h = GPU_texture_height(ofs->color); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object); + GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); + + if (status == GL_FRAMEBUFFER_COMPLETE) { + glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else { + gpu_print_framebuffer_error(status, NULL); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); +} + void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels) { const int w = GPU_texture_width(ofs->color); diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 609aa529872..34dee37001e 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -714,8 +714,6 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_image_desaturate_frag_glsl }, [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_alpha_color_frag_glsl }, - [GPU_SHADER_2D_IMAGE_ALPHA] = { datatoc_gpu_shader_2D_image_vert_glsl, - datatoc_gpu_shader_image_modulate_alpha_frag_glsl }, [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_shuffle_color_frag_glsl }, [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl, diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 5d89bd59277..383ebec5b72 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -38,6 +38,8 @@ #include "BLI_string.h" #include "BLI_mempool.h" +#include "BIF_gl.h" + #include "DNA_vec_types.h" #include "DNA_userdef_types.h" @@ -521,6 +523,10 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect) BLI_assert(w == BLI_rcti_size_x(rect) + 1); BLI_assert(h == BLI_rcti_size_y(rect) + 1); + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / w; + const float halfy = GLA_PIXEL_OFS / h; + float x1 = rect->xmin; float x2 = rect->xmin + w; float y1 = rect->ymin; @@ -531,7 +537,7 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect) GPU_texture_bind(color, 0); glUniform1i(GPU_shader_get_uniform(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), 0.0f, 0.0f, 1.0f, 1.0f); + glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy); glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x1, y1, x2, y2); glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f); @@ -545,6 +551,19 @@ void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) DRW_opengl_context_disable(); } + +GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport) +{ + DefaultFramebufferList *dfbl = viewport->fbl; + + if (dfbl->default_fb) { + DefaultTextureList *dtxl = viewport->txl; + return dtxl->color; + } + + return NULL; +} + static void gpu_viewport_buffers_free( FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len) diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index a127ad0e2ab..18986206b23 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -44,6 +44,7 @@ struct ARegionType; struct PanelType; struct Scene; struct uiLayout; +struct wmDrawBuffer; struct wmTimer; struct wmTooltipState; @@ -75,10 +76,9 @@ typedef struct bScreen { char do_draw_gesture; /* notifier for gesture draw. */ char do_draw_paintcursor; /* notifier for paint cursor draw. */ char do_draw_drag; /* notifier for dragging draw. */ - char swap; /* indicator to survive swap-exchange systems */ char skip_handling; /* set to delay screen handling after switching back from maximized area */ char scrubbing; /* set when scrubbing to avoid some costly updates */ - char pad[2]; + char pad[3]; struct ARegion *active_region; /* active region that has mouse focus */ @@ -308,10 +308,9 @@ typedef struct ARegion { short do_draw; /* private, cached notifier events */ short do_draw_overlay; /* private, cached notifier events */ - short swap; /* private, indicator to survive swap-exchange */ short overlap; /* private, set for indicate drawing overlapped */ short flagfullscreen; /* temporary copy of flag settings for clean fullscreen */ - short pad; + short pad1, pad2; struct ARegionType *type; /* callbacks for this region type */ @@ -325,16 +324,12 @@ typedef struct ARegion { struct wmManipulatorMap *manipulator_map; /* manipulator-map of this region */ struct wmTimer *regiontimer; /* blend in/out */ + struct wmDrawBuffer *draw_buffer; char *headerstr; /* use this string to draw info */ void *regiondata; /* XXX 2.50, need spacedata equivalent? */ } ARegion; -/* swap */ -#define WIN_BACK_OK 1 -#define WIN_FRONT_OK 2 -// #define WIN_EQUAL 3 // UNUSED - /* area->flag */ enum { HEADER_NO_PULLDOWN = (1 << 0), diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 4ef7ce019bb..3973006283d 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -515,9 +515,8 @@ typedef struct UserDef { short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; short manipulator_flag, manipulator_size; - int pad6; + short pad6[3]; short textimeout, texcollectrate; - short wmdrawmethod; /* eWM_DrawMethod */ short dragthreshold; int memcachelimit; int prefetchframes; @@ -797,16 +796,6 @@ typedef enum eOpenGL_SelectOptions { USER_SELECT_USE_SELECT_RENDERMODE = 2 } eOpenGL_SelectOptions; -/* wm draw method. - * UserDef.wmdrawmethod */ -typedef enum eWM_DrawMethod { - USER_DRAW_TRIPLE = 0, - USER_DRAW_OVERLAP = 1, - USER_DRAW_FULL = 2, - USER_DRAW_AUTOMATIC = 3, - USER_DRAW_OVERLAP_FLIP = 4, -} eWM_DrawMethod; - /* text draw options * UserDef.text_render */ typedef enum eText_Draw_Options { diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index cd45407812a..313997082c7 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -154,7 +154,6 @@ typedef struct RegionView3D { float rot_axis[3]; struct GPUFX *compositor; - struct GPUViewport *viewport; } RegionView3D; /* 3D ViewPort Struct */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 8797f4b1fd6..7d7fa5fcf23 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -222,9 +222,6 @@ typedef struct wmWindow { * Currently WIN32, runtime-only data */ struct wmIMEData *ime_data; - int drawmethod, drawfail; /* internal for wm_draw.c only */ - ListBase drawdata; /* internal for wm_draw.c only */ - ListBase queue; /* all events (ghost level events were handled) */ ListBase handlers; /* window+screen handlers, handled last */ ListBase modalhandlers; /* priority handlers, handled first */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index dc8db500f24..f99b4b59f1a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3908,20 +3908,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static const EnumPropertyItem draw_method_items[] = { - {USER_DRAW_AUTOMATIC, "AUTOMATIC", 0, "Automatic", "Automatically set based on graphics card and driver"}, - {USER_DRAW_TRIPLE, "TRIPLE_BUFFER", 0, "Triple Buffer", - "Use a third buffer for minimal redraws at the cost of more memory"}, - {USER_DRAW_OVERLAP, "OVERLAP", 0, "Overlap", - "Redraw all overlapping regions, minimal memory usage but more redraws"}, - {USER_DRAW_OVERLAP_FLIP, "OVERLAP_FLIP", 0, "Overlap Flip", - "Redraw all overlapping regions, minimal memory usage but more redraws " - "(for graphics drivers that do flipping)"}, - {USER_DRAW_FULL, "FULL", 0, "Full", - "Do a full redraw each time, slow, only use for reference or when everything else fails"}, - {0, NULL, 0, NULL, NULL} - }; - static const EnumPropertyItem color_picker_types[] = { {USER_CP_CIRCLE_HSV, "CIRCLE_HSV", 0, "Circle (HSV)", "A circular Hue/Saturation color wheel, with Value slider"}, {USER_CP_CIRCLE_HSL, "CIRCLE_HSL", 0, "Circle (HSL)", "A circular Hue/Saturation color wheel, with Lightness slider"}, @@ -4139,12 +4125,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Texture Collection Rate", "Number of seconds between each run of the GL texture garbage collector"); - prop = RNA_def_property(srna, "window_draw_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "wmdrawmethod"); - RNA_def_property_enum_items(prop, draw_method_items); - RNA_def_property_ui_text(prop, "Window Draw Method", "Drawing method used by the window manager"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - prop = RNA_def_property(srna, "audio_mixing_buffer", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mixbufsize"); RNA_def_property_enum_items(prop, audio_mixing_samples_items); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index de5ce6d211d..c65f1064830 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -68,6 +68,7 @@ struct ScrArea; struct Main; struct bToolDef; struct ViewLayer; +struct GPUViewport; #ifdef WITH_INPUT_NDOF struct wmNDOFMotionData; @@ -139,9 +140,6 @@ struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect); struct wmWindow *WM_window_open_temp(struct bContext *C, int x, int y, int sizex, int sizey, int type); void WM_window_set_dpi(wmWindow *win); - /* returns true if draw method is triple buffer */ -bool WM_is_draw_triple(struct wmWindow *win); - bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test); @@ -562,6 +560,11 @@ void *WM_draw_cb_activate( void WM_draw_cb_exit(struct wmWindow *win, void *handle); void WM_redraw_windows(struct bContext *C); + /* Region drawing */ +void WM_draw_region_free(struct ARegion *ar); +struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *ar, int view); +struct GPUViewport *WM_draw_region_get_bound_viewport(struct ARegion *ar); + void WM_main_playanim(int argc, const char **argv); /* debugging only, convenience function to write on crash */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 5440fd15bef..a0ad3950e6b 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -487,7 +487,6 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) while ((win = BLI_pophead(&wm->windows))) { WM_window_set_active_workspace(win, NULL); /* prevent draw clear to use screen */ - wm_draw_window_clear(win); wm_window_free(C, wm, win); } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index b3e9eaeec45..8524b629cc5 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -50,6 +50,7 @@ #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_screen.h" #include "BKE_scene.h" #include "BKE_workspace.h" @@ -61,7 +62,10 @@ #include "GPU_draw.h" #include "GPU_extensions.h" +#include "GPU_framebuffer.h" #include "GPU_immediate.h" +#include "GPU_matrix.h" +#include "GPU_texture.h" #include "GPU_viewport.h" #include "RE_engine.h" @@ -77,72 +81,113 @@ # include "BKE_subsurf.h" #endif -/* swap */ -#define WIN_NONE_OK 0 -#define WIN_BACK_OK 1 -#define WIN_FRONT_OK 2 -#define WIN_BOTH_OK 3 - -/* ******************* drawing, overlays *************** */ +/* ******************* paint cursor *************** */ static void wm_paintcursor_draw(bContext *C, ARegion *ar) { wmWindowManager *wm = CTX_wm_manager(C); - - if (wm->paintcursors.first) { - wmWindow *win = CTX_wm_window(C); - bScreen *screen = WM_window_get_active_screen(win); - wmPaintCursor *pc; - - if (ar->visible && ar == screen->active_region) { - for (pc = wm->paintcursors.first; pc; pc = pc->next) { - if (pc->poll == NULL || pc->poll(C)) { - ARegion *ar_other = CTX_wm_region(C); - if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { - int x = 0, y = 0; - wm_get_cursor_position(win, &x, &y); - pc->draw(C, - x - ar_other->winrct.xmin, - y - ar_other->winrct.ymin, - pc->customdata); - } - else { - pc->draw(C, - win->eventstate->x - ar_other->winrct.xmin, - win->eventstate->y - ar_other->winrct.ymin, - pc->customdata); - } + wmWindow *win = CTX_wm_window(C); + bScreen *screen = WM_window_get_active_screen(win); + wmPaintCursor *pc; + + if (ar->visible && ar == screen->active_region) { + for (pc = wm->paintcursors.first; pc; pc = pc->next) { + if (pc->poll == NULL || pc->poll(C)) { + /* Prevent drawing outside region. */ + GLint scissor[4]; + glGetIntegerv(GL_SCISSOR_BOX, scissor); + glScissor(ar->winrct.xmin, + ar->winrct.ymin, + BLI_rcti_size_x(&ar->winrct) + 1, + BLI_rcti_size_y(&ar->winrct) + 1); + + if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { + int x = 0, y = 0; + wm_get_cursor_position(win, &x, &y); + pc->draw(C, + x, + y, + pc->customdata); + } + else { + pc->draw(C, + win->eventstate->x, + win->eventstate->y, + pc->customdata); } + + glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } } } } -/* ********************* drawing, swap ****************** */ -static void wm_area_mark_invalid_backbuf(ScrArea *sa) +static bool wm_draw_region_stereo_set(ScrArea *sa, ARegion *ar, eStereoViews sview) { - if (sa->spacetype == SPACE_VIEW3D) - ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF; + /* We could detect better when stereo is actually needed, by inspecting the + * image in the image editor and sequencer. */ + if (ar->regiontype != RGN_TYPE_WINDOW) { + return false; + } + + switch (sa->spacetype) { + case SPACE_IMAGE: + { + SpaceImage *sima = sa->spacedata.first; + sima->iuser.multiview_eye = sview; + return true; + } + case SPACE_VIEW3D: + { + View3D *v3d = sa->spacedata.first; + if (v3d->camera && v3d->camera->type == OB_CAMERA) { + Camera *cam = v3d->camera->data; + CameraBGImage *bgpic = cam->bg_images.first; + v3d->multiview_eye = sview; + if (bgpic) bgpic->iuser.multiview_eye = sview; + return true; + } + return false; + } + case SPACE_NODE: + { + SpaceNode *snode = sa->spacedata.first; + if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ima->eye = sview; + return true; + } + return false; + } + case SPACE_SEQ: + { + SpaceSeq *sseq = sa->spacedata.first; + sseq->multiview_eye = sview; + return true; + } + } + + return false; } -static bool wm_area_test_invalid_backbuf(ScrArea *sa) +/* ********************* drawing ****************** */ + +static void wm_area_mark_invalid_backbuf(ScrArea *sa) { if (sa->spacetype == SPACE_VIEW3D) - return (((View3D *)sa->spacedata.first)->flag & V3D_INVALID_BACKBUF) != 0; - else - return true; + ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF; } static void wm_region_test_render_do_draw(const Scene *scene, struct Depsgraph *depsgraph, ScrArea *sa, ARegion *ar) { /* tag region for redraw from render engine preview running inside of it */ - if (sa->spacetype == SPACE_VIEW3D) { + if (sa->spacetype == SPACE_VIEW3D && ar->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = ar->regiondata; - RenderEngine *engine = (rv3d) ? rv3d->render_engine : NULL; - GPUViewport *viewport = (rv3d) ? rv3d->viewport : NULL; + RenderEngine *engine = rv3d->render_engine; + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { View3D *v3d = sa->spacedata.first; @@ -162,12 +207,9 @@ static void wm_region_test_render_do_draw(const Scene *scene, struct Depsgraph * } } -static void wm_draw_region(bContext *C, ARegion *ar) +static bool wm_region_use_viewport(ScrArea *sa, ARegion *ar) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - CTX_wm_region_set(C, NULL); + return (sa->spacetype == SPACE_VIEW3D && ar->regiontype == RGN_TYPE_WINDOW); } /********************** draw all **************************/ @@ -213,568 +255,356 @@ static void wm_draw_callbacks(wmWindow *win) } } -static void wm_method_draw_full(bContext *C, wmWindow *win) -{ - bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - /* draw area regions */ - ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); +/************************* Region drawing. ******************************** + * + * Each region draws into its own framebuffer, which is then blit on the + * window draw buffer. This helps with fast redrawing if only some regions + * change. It also means we can share a single context for multiple windows, + * so that for example VAOs can be shared between windows. */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - wm_paintcursor_draw(C, ar); - CTX_wm_region_set(C, NULL); +static void wm_draw_region_buffer_free(ARegion *ar) +{ + if (ar->draw_buffer) { + for (int view = 0; view < 2; view++) { + if (ar->draw_buffer->offscreen[view]) { + GPU_offscreen_free(ar->draw_buffer->offscreen[view]); + } + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_free(ar->draw_buffer->viewport[view]); } } - - wm_area_mark_invalid_backbuf(sa); - CTX_wm_area_set(C, NULL); - } - ED_screen_draw_edges(win); - screen->do_draw = false; - wm_draw_callbacks(win); - - /* draw overlapping regions */ - for (ar = screen->regionbase.first; ar; ar = ar->next) { - if (ar->visible) { - CTX_wm_menu_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - CTX_wm_menu_set(C, NULL); - } + MEM_freeN(ar->draw_buffer); + ar->draw_buffer = NULL; } - - if (screen->do_draw_gesture) - wm_gesture_draw(win); } -/****************** draw overlap all **********************/ -/* - redraw marked areas, and anything that overlaps it */ -/* - it also handles swap exchange optionally, assuming */ -/* that on swap no clearing happens and we get back the */ -/* same buffer as we swapped to the front */ - -/* mark area-regions to redraw if overlapped with rect */ -static void wm_flush_regions_down(wmWindow *win, bScreen *screen, rcti *dirty) +static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) { - ARegion *ar; + /* Setup offscreen color texture for drawing. */ + GPUTexture *texture = GPU_offscreen_color_texture(offscreen); - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (BLI_rcti_isect(dirty, &ar->winrct, NULL)) { - ar->do_draw = RGN_DRAW; - memset(&ar->drawrct, 0, sizeof(ar->drawrct)); - ar->swap = WIN_NONE_OK; - } - } - } -} + /* We don't support multisample textures here. */ + BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); -/* mark menu-regions to redraw if overlapped with rect */ -static void wm_flush_regions_up(bScreen *screen, rcti *dirty) -{ - ARegion *ar; - - for (ar = screen->regionbase.first; ar; ar = ar->next) { - if (BLI_rcti_isect(dirty, &ar->winrct, NULL)) { - ar->do_draw = RGN_DRAW; - memset(&ar->drawrct, 0, sizeof(ar->drawrct)); - ar->swap = WIN_NONE_OK; - } - } + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + + /* No mipmaps or filtering. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + /* GL_TEXTURE_BASE_LEVEL = 0 by default */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, 0); } -static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) +static void wm_draw_region_buffer_create(ARegion *ar, bool stereo, bool use_viewport) { - wmWindowManager *wm = CTX_wm_manager(C); - bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - static rcti rect = {0, 0, 0, 0}; - - /* after backbuffer selection draw, we need to redraw */ - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) - if (ar->visible && !wm_area_test_invalid_backbuf(sa)) - ED_region_tag_redraw(ar); + if (ar->draw_buffer) { + if (ar->draw_buffer->stereo != stereo) { + /* Free draw buffer on stereo changes. */ + wm_draw_region_buffer_free(ar); + } + else { + /* Free offscreen buffer on size changes. Viewport auto resizes. */ + GPUOffScreen *offscreen = ar->draw_buffer->offscreen[0]; + if (offscreen && (GPU_offscreen_width(offscreen) != ar->winx || + GPU_offscreen_height(offscreen) != ar->winy)) + { + wm_draw_region_buffer_free(ar); + } + } } - /* flush overlapping regions */ - if (screen->regionbase.first) { - /* flush redraws of area regions up to overlapping regions */ - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) - if (ar->visible && ar->do_draw) - wm_flush_regions_up(screen, &ar->winrct); + if (!ar->draw_buffer) { + if (use_viewport) { + /* Allocate viewport which includes an offscreen buffer with depth + * multisample, etc. */ + ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); + ar->draw_buffer->viewport[0] = GPU_viewport_create(); + ar->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL; } + else { + /* Allocate offscreen buffer if it does not exist. This one has no + * depth or multisample buffers. 3D view creates own buffers with + * the data it needs. */ + GPUOffScreen *offscreen = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); + if (!offscreen) { + return; + } - /* flush between overlapping regions */ - for (ar = screen->regionbase.last; ar; ar = ar->prev) - if (ar->visible && ar->do_draw) - wm_flush_regions_up(screen, &ar->winrct); - - /* flush redraws of overlapping regions down to area regions */ - for (ar = screen->regionbase.last; ar; ar = ar->prev) - if (ar->visible && ar->do_draw) - wm_flush_regions_down(win, screen, &ar->winrct); - } - - /* flush drag item */ - if (rect.xmin != rect.xmax) { - wm_flush_regions_down(win, screen, &rect); - rect.xmin = rect.xmax = 0; - } - if (wm->drags.first) { - /* doesnt draw, fills rect with boundbox */ - wm_drags_draw(C, win, &rect); - } - - /* draw marked area regions */ - ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); + wm_draw_offscreen_texture_parameters(offscreen); - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible) { - if (ar->do_draw) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - wm_paintcursor_draw(C, ar); - CTX_wm_region_set(C, NULL); + GPUOffScreen *offscreen_right = NULL; + if (stereo) { + offscreen_right = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); - if (exchange) - ar->swap = WIN_FRONT_OK; + if (!offscreen_right) { + GPU_offscreen_free(offscreen); + return; } - else if (exchange) { - if (ar->swap == WIN_FRONT_OK) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - wm_paintcursor_draw(C, ar); - CTX_wm_region_set(C, NULL); - ar->swap = WIN_BOTH_OK; - } - else if (ar->swap == WIN_BACK_OK) - ar->swap = WIN_FRONT_OK; - else if (ar->swap == WIN_BOTH_OK) - ar->swap = WIN_BOTH_OK; - } + wm_draw_offscreen_texture_parameters(offscreen_right); } + + ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); + ar->draw_buffer->offscreen[0] = offscreen; + ar->draw_buffer->offscreen[1] = offscreen_right; } - wm_area_mark_invalid_backbuf(sa); - CTX_wm_area_set(C, NULL); + ar->draw_buffer->bound_view = -1; + ar->draw_buffer->stereo = stereo; } +} - /* after area regions so we can do area 'overlay' drawing */ - if (screen->do_draw) { - ED_screen_draw_edges(win); - screen->do_draw = false; - wm_draw_callbacks(win); +static void wm_draw_region_bind(ARegion *ar, int view) +{ + if (!ar->draw_buffer) { + return; + } - if (exchange) - screen->swap = WIN_FRONT_OK; + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct); } - else if (exchange) { - if (screen->swap == WIN_FRONT_OK) { - ED_screen_draw_edges(win); - screen->do_draw = false; - screen->swap = WIN_BOTH_OK; - wm_draw_callbacks(win); - } - else if (screen->swap == WIN_BACK_OK) - screen->swap = WIN_FRONT_OK; - else if (screen->swap == WIN_BOTH_OK) - screen->swap = WIN_BOTH_OK; + else { + GPU_offscreen_bind(ar->draw_buffer->offscreen[view], false); } - /* draw marked overlapping regions */ - for (ar = screen->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->do_draw) { - CTX_wm_menu_set(C, ar); - ED_region_do_draw(C, ar); - ar->do_draw = false; - CTX_wm_menu_set(C, NULL); - } + ar->draw_buffer->bound_view = view; + + /* For now scissor is expected by region drawing, we could disable it + * and do the enable/disable in the specific cases that setup scissor. */ + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, ar->winx, ar->winy); +} + +static void wm_draw_region_unbind(ARegion *ar, int view) +{ + if (!ar->draw_buffer) { + return; } - if (screen->do_draw_gesture) - wm_gesture_draw(win); - - /* needs pixel coords in screen */ - if (wm->drags.first) { - wm_drags_draw(C, win, NULL); + glDisable(GL_SCISSOR_TEST); + + ar->draw_buffer->bound_view = -1; + + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_unbind(ar->draw_buffer->viewport[view]); + } + else { + GPU_offscreen_unbind(ar->draw_buffer->offscreen[view], false); } } -/****************** draw triple buffer ********************/ -/* - area regions are written into a texture, without any */ -/* of the overlapping menus, brushes, gestures. these */ -/* are redrawn each time. */ - -static void wm_draw_triple_free(wmDrawTriple *triple) +static void wm_draw_region_blit(ARegion *ar, int view) { - if (triple) { - glDeleteTextures(1, &triple->bind); - MEM_freeN(triple); + if (!ar->draw_buffer) { + return; + } + + if (ar->draw_buffer->viewport[view]) { + GPU_viewport_draw_to_screen(ar->draw_buffer->viewport[view], &ar->winrct); + } + else { + GPU_offscreen_draw_to_screen(ar->draw_buffer->offscreen[view], ar->winrct.xmin, ar->winrct.ymin); } } -static void wm_draw_triple_fail(bContext *C, wmWindow *win) +GPUTexture *wm_draw_region_texture(ARegion *ar, int view) { - wm_draw_window_clear(win); + if (!ar->draw_buffer) { + return NULL; + } - win->drawfail = true; - wm_method_draw_overlap_all(C, win, 0); + if (ar->draw_buffer->viewport[view]) { + return GPU_viewport_color_texture(ar->draw_buffer->viewport[view]); + } + else { + return GPU_offscreen_color_texture(ar->draw_buffer->offscreen[view]); + } } -static bool wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple) +void wm_draw_region_blend(ARegion *ar, int view, bool blend) { - /* compute texture sizes */ - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); - - /* generate texture names */ - glGenTextures(1, &triple->bind); + if (!ar->draw_buffer) { + return; + } - /* proxy texture is only guaranteed to test for the cases that - * there is only one texture in use, which may not be the case */ - const GLint maxsize = GPU_max_texture_size(); + /* Alpha is always 1, except when blend timer is running. */ + float alpha = ED_region_blend_alpha(ar); + if (alpha <= 0.0f) { + return; + } - if (sizex > maxsize || sizey > maxsize) { - printf("WM: failed to allocate texture for triple buffer drawing " - "(texture too large for graphics card).\n"); - return false; + if (!blend) { + alpha = 1.0f; } /* setup actual texture */ - glBindTexture(GL_TEXTURE_2D, triple->bind); - - /* no mipmaps */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - /* GL_TEXTURE_BASE_LEVEL = 0 by default */ - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, sizex, sizey, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - - glBindTexture(GL_TEXTURE_2D, 0); - - return true; -} - -void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha) -{ - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); + GPUTexture *texture = wm_draw_region_texture(ar, view); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); /* wmOrtho for the screen has this same offset */ - const float ratiox = 1.0f; - const float ratioy = 1.0f; - const float halfx = GLA_PIXEL_OFS / sizex; - const float halfy = GLA_PIXEL_OFS / sizey; - - const int activeTex = 7; /* arbitrary */ - glActiveTexture(GL_TEXTURE0 + activeTex); - glBindTexture(GL_TEXTURE_2D, triple->bind); + const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&ar->winrct) + 1); + const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&ar->winrct) + 1); - float x1 = halfx; - float x2 = ratiox + halfx; - float y1 = halfy; - float y2 = ratioy + halfy; + if (blend) { + /* GL_ONE because regions drawn offscreen have premultiplied alpha. */ + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); GPU_shader_bind(shader); - glUniform1i(GPU_shader_get_uniform(shader, "image"), activeTex); - glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2); - glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), 0.0f, 0.0f, sizex, sizey); + glUniform1i(GPU_shader_get_uniform(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy); + glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), ar->winrct.xmin, ar->winrct.ymin, ar->winrct.xmax + 1, ar->winrct.ymax + 1); glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), alpha, alpha, alpha, alpha); GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4); glBindTexture(GL_TEXTURE_2D, 0); -} - -static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple) -{ - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); - glBindTexture(GL_TEXTURE_2D, triple->bind); - /* what is GL_READ_BUFFER right now? */ - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sizex, sizey); - glBindTexture(GL_TEXTURE_2D, 0); -} - -static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple) -{ - float fac = ED_region_blend_factor(ar); - - /* region blend always is 1, except when blend timer is running */ - if (fac < 1.0f) { - wmViewport(&ar->winrct); - - glEnable(GL_BLEND); - wm_triple_draw_textures(win, triple, 1.0f - fac); + if (blend) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); } } -static void wm_method_draw_triple(bContext *C, wmWindow *win) +GPUViewport *WM_draw_region_get_viewport(ARegion *ar, int view) { - wmWindowManager *wm = CTX_wm_manager(C); - wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first; - bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - bool copytex = false; - - if (drawdata && drawdata->triple) { -#if 0 /* why do we need to clear before overwriting? */ - glClearColor(1, 1, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#endif - - wmWindowViewport(win); - - wm_triple_draw_textures(win, drawdata->triple, 1.0f); + if (!ar->draw_buffer) { + return NULL; } - else { - /* we run it when we start OR when we turn stereo on */ - if (drawdata == NULL) { - drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData"); - BLI_addhead(&win->drawdata, drawdata); - } - drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple"); + return ar->draw_buffer->viewport[view]; +} - if (!wm_triple_gen_textures(win, drawdata->triple)) { - wm_draw_triple_fail(C, win); - return; - } +GPUViewport *WM_draw_region_get_bound_viewport(ARegion *ar) +{ + if (!ar->draw_buffer || ar->draw_buffer->bound_view == -1) { + return NULL; } - /* it means stereo was just turned off */ - /* note: we are removing all drawdatas that are not the first */ - for (dd = drawdata->next; dd; dd = dd_next) { - dd_next = dd->next; - - BLI_remlink(&win->drawdata, dd); - wm_draw_triple_free(dd->triple); - MEM_freeN(dd); - } + int view = ar->draw_buffer->bound_view; + return ar->draw_buffer->viewport[view]; +} - wmDrawTriple *triple = drawdata->triple; +static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) +{ + bScreen *screen = WM_window_get_active_screen(win); - /* draw marked area regions (also global ones) */ + /* Draw screen areas into own frame buffer. */ ED_screen_areas_iter(win, screen, sa) { CTX_wm_area_set(C, sa); - for (ar = sa->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->visible && ar->do_draw) { - if (ar->overlap == false) { - wm_draw_region(C, ar); - copytex = true; + CTX_wm_region_set(C, ar); + bool use_viewport = wm_region_use_viewport(sa, ar); + + if (stereo && wm_draw_region_stereo_set(sa, ar, STEREO_LEFT_ID)) { + wm_draw_region_buffer_create(ar, true, use_viewport); + + for (int view = 0; view < 2; view++) { + eStereoViews sview; + if (view == 0) { + sview = STEREO_LEFT_ID; + } + else { + sview = STEREO_RIGHT_ID; + wm_draw_region_stereo_set(sa, ar, sview); + } + + wm_draw_region_bind(ar, view); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, view); + } } - } - } - - wm_area_mark_invalid_backbuf(sa); - CTX_wm_area_set(C, NULL); - } - - if (copytex) { - wmWindowViewport(win); - - wm_triple_copy_textures(win, triple); - } - - if (wm->paintcursors.first) { - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar == screen->active_region) { - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - - /* make region ready for draw, scissor, pixelspace */ - wmViewport(&ar->winrct); - wm_paintcursor_draw(C, ar); - - CTX_wm_region_set(C, NULL); - CTX_wm_area_set(C, NULL); + else { + wm_draw_region_buffer_create(ar, false, use_viewport); + wm_draw_region_bind(ar, 0); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, 0); } - } - } - - wmWindowViewport(win); - } - /* draw overlapping area regions (always like popups) */ - ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->overlap) { - wm_draw_region(C, ar); - wm_draw_region_blend(win, ar, triple); + ar->do_draw = false; + CTX_wm_region_set(C, NULL); } } + wm_area_mark_invalid_backbuf(sa); CTX_wm_area_set(C, NULL); } - /* after area regions so we can do area 'overlay' drawing */ - ED_screen_draw_edges(win); - WM_window_get_active_screen(win)->do_draw = false; - wm_draw_callbacks(win); - - /* draw floating regions (menus) */ - for (ar = screen->regionbase.first; ar; ar = ar->next) { + /* Draw menus into their own framebuffer. */ + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->visible) { CTX_wm_menu_set(C, ar); + + if (ar->type && ar->type->refresh) { + /* UI code reads the OpenGL state, but we have to + * refresh beforehand in case the menu size changes. */ + wmViewport(&ar->winrct); + ar->type->refresh(C, ar); + } + + wm_draw_region_buffer_create(ar, false, false); + wm_draw_region_bind(ar, 0); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, 0); + ar->do_draw = false; CTX_wm_menu_set(C, NULL); } } - - /* always draw, not only when screen tagged */ - if (win->gesture.first) - wm_gesture_draw(win); - - /* needs pixel coords in screen */ - if (wm->drags.first) { - wm_drags_draw(C, win, NULL); - } } -static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoViews sview) +static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) { wmWindowManager *wm = CTX_wm_manager(C); - wmDrawData *drawdata; - wmDrawTriple *triple_data, *triple_all; bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - int copytex = false; - int id; - - /* we store the triple_data in sequence to triple_all */ - for (id = 0; id < 2; id++) { - drawdata = BLI_findlink(&win->drawdata, (sview * 2) + id); - - if (drawdata && drawdata->triple) { - if (id == 0) { -#if 0 /* why do we need to clear before overwriting? */ - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#endif - - wmWindowViewport(win); - - wm_triple_draw_textures(win, drawdata->triple, 1.0f); - } - } - else { - /* we run it when we start OR when we turn stereo on */ - if (drawdata == NULL) { - drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData"); - BLI_addtail(&win->drawdata, drawdata); - } - - drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple"); - if (!wm_triple_gen_textures(win, drawdata->triple)) { - wm_draw_triple_fail(C, win); - return; - } - } - } - - triple_data = ((wmDrawData *) BLI_findlink(&win->drawdata, sview * 2))->triple; - triple_all = ((wmDrawData *) BLI_findlink(&win->drawdata, (sview * 2) + 1))->triple; + /* Draw into the window framebuffer, in full window coordinates. */ + wmWindowViewport(win); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); - /* draw marked area regions */ + /* Blit non-overlapping area regions. */ ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); - - switch (sa->spacetype) { - case SPACE_IMAGE: - { - SpaceImage *sima = sa->spacedata.first; - sima->iuser.multiview_eye = sview; - break; - } - case SPACE_VIEW3D: - { - View3D *v3d = sa->spacedata.first; - if (v3d->camera && v3d->camera->type == OB_CAMERA) { - Camera *cam = v3d->camera->data; - CameraBGImage *bgpic = cam->bg_images.first; - v3d->multiview_eye = sview; - if (bgpic) bgpic->iuser.multiview_eye = sview; - } - break; - } - case SPACE_NODE: - { - SpaceNode *snode = sa->spacedata.first; - if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) { - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); - ima->eye = sview; + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->visible && ar->overlap == false) { + if (view == -1 && ar->draw_buffer && ar->draw_buffer->stereo) { + /* Stereo drawing from textures. */ + if(win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) { + wm_stereo3d_draw_anaglyph(win, ar); + } + else { + wm_stereo3d_draw_interlace(win, ar); + } } - break; - } - case SPACE_SEQ: - { - SpaceSeq *sseq = sa->spacedata.first; - sseq->multiview_eye = sview; - break; - } - } - - /* draw marked area regions */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->visible && ar->do_draw) { - - if (ar->overlap == false) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - - if (sview == STEREO_RIGHT_ID) - ar->do_draw = false; - - CTX_wm_region_set(C, NULL); - copytex = true; + else { + /* Blit from offscreen buffer. */ + wm_draw_region_blit(ar, 0); } } } - - wm_area_mark_invalid_backbuf(sa); - CTX_wm_area_set(C, NULL); - } - - if (copytex) { - wmWindowViewport(win); - - wm_triple_copy_textures(win, triple_data); } + /* Draw paint cursors. */ if (wm->paintcursors.first) { ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->visible && ar == screen->active_region) { CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); /* make region ready for draw, scissor, pixelspace */ - wmViewport(&ar->winrct); wm_paintcursor_draw(C, ar); CTX_wm_region_set(C, NULL); @@ -786,40 +616,23 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV wmWindowViewport(win); } - /* draw overlapping area regions (always like popups) */ + /* Blend in overlapping area regions */ ED_screen_areas_iter(win, screen, sa) { - CTX_wm_area_set(C, sa); - - for (ar = sa->regionbase.first; ar; ar = ar->next) { + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->visible && ar->overlap) { - CTX_wm_region_set(C, ar); - ED_region_do_draw(C, ar); - if (sview == STEREO_RIGHT_ID) - ar->do_draw = false; - CTX_wm_region_set(C, NULL); - - wm_draw_region_blend(win, ar, triple_data); + wm_draw_region_blend(ar, 0, true); } } - - CTX_wm_area_set(C, NULL); } - /* after area regions so we can do area 'overlay' drawing */ + /* After area regions so we can do area 'overlay' drawing. */ ED_screen_draw_edges(win); - if (sview == STEREO_RIGHT_ID) - screen->do_draw = false; - wm_draw_callbacks(win); - /* draw floating regions (menus) */ - for (ar = screen->regionbase.first; ar; ar = ar->next) { + /* Blend in floating regions (menus). */ + for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->visible) { - CTX_wm_menu_set(C, ar); - ED_region_do_draw(C, ar); - if (sview == STEREO_RIGHT_ID) - ar->do_draw = false; - CTX_wm_menu_set(C, NULL); + wm_draw_region_blend(ar, 0, true); } } @@ -831,10 +644,76 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV if (wm->drags.first) { wm_drags_draw(C, win, NULL); } +} - /* copy the ui + overlays */ - wmWindowViewport(win); - wm_triple_copy_textures(win, triple_all); +static void wm_draw_window(bContext *C, wmWindow *win) +{ + bScreen *screen = WM_window_get_active_screen(win); + bool stereo = WM_stereo3d_enabled(win, false); + + /* Draw area regions into their own framebuffer. This way we can redraw + * the areas that need it, and blit the rest from existing framebuffers. */ + wm_draw_window_offscreen(C, win, stereo); + + /* Now we draw into the window framebuffer, in full window coordinates. */ + if (!stereo) { + /* Regular mono drawing. */ + wm_draw_window_onscreen(C, win, -1); + } + else if(win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + /* For pageflip we simply draw to both back buffers. */ + glDrawBuffer(GL_BACK_LEFT); + wm_draw_window_onscreen(C, win, 0); + glDrawBuffer(GL_BACK_RIGHT); + wm_draw_window_onscreen(C, win, 1); + glDrawBuffer(GL_BACK); + } + else if(ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) { + /* For anaglyph and interlace, we draw individual regions with + * stereo framebuffers using different shaders. */ + wm_draw_window_onscreen(C, win, -1); + } + else { + /* For side-by-side and top-bottom, we need to render each view to an + * an offscreen texture and then draw it. This used to happen for all + * stereo methods, but it's less efficient than drawing directly. */ + const int width = WM_window_pixels_x(win); + const int height = WM_window_pixels_y(win); + GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL); + + if (offscreen) { + GPUTexture *texture = GPU_offscreen_color_texture(offscreen); + wm_draw_offscreen_texture_parameters(offscreen); + + for (int view = 0; view < 2; view++) { + /* Draw view into offscreen buffer. */ + GPU_offscreen_bind(offscreen, false); + wm_draw_window_onscreen(C, win, view); + GPU_offscreen_unbind(offscreen, false); + + /* Draw offscreen buffer to screen. */ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); + + if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) { + wm_stereo3d_draw_sidebyside(win, view); + } + else { + wm_stereo3d_draw_topbottom(win, view); + } + + glBindTexture(GL_TEXTURE_2D, 0); + } + + GPU_offscreen_free(offscreen); + } + else { + /* Still draw something in case of allocation failure. */ + wm_draw_window_onscreen(C, win, 0); + } + } + + screen->do_draw = false; } /****************** main update call **********************/ @@ -842,17 +721,17 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV /* quick test to prevent changing window drawable */ static bool wm_draw_update_test_window(wmWindow *win) { - /*const*/ struct WorkSpace *workspace = WM_window_get_active_workspace(win); - /*const*/ Scene *scene = WM_window_get_active_scene(win); - /*const*/ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene); + struct WorkSpace *workspace = WM_window_get_active_workspace(win); + Scene *scene = WM_window_get_active_scene(win); + ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene); struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - const bScreen *screen = WM_window_get_active_screen(win); + bScreen *screen = WM_window_get_active_screen(win); ARegion *ar; bool do_draw = false; for (ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->do_draw_overlay) { - wm_tag_redraw_overlay(win, ar); + screen->do_draw_paintcursor = true; ar->do_draw_overlay = false; } if (ar->visible && ar->do_draw) @@ -885,44 +764,14 @@ static bool wm_draw_update_test_window(wmWindow *win) return false; } -static int wm_automatic_draw_method(wmWindow *win) -{ - /* We assume all supported GPUs now support triple buffer well. */ - if (win->drawmethod == USER_DRAW_AUTOMATIC) { - return USER_DRAW_TRIPLE; - } - else { - return win->drawmethod; - } -} - -bool WM_is_draw_triple(wmWindow *win) -{ - /* function can get called before this variable is set in drawing code below */ - if (win->drawmethod != U.wmdrawmethod) - win->drawmethod = U.wmdrawmethod; - return (USER_DRAW_TRIPLE == wm_automatic_draw_method(win)); -} - -void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar) +void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(ar)) { - /* for draw triple gestures, paint cursors don't need region redraw */ - if (ar && win) { + if (win) { bScreen *screen = WM_window_get_active_screen(win); - - if (wm_automatic_draw_method(win) != USER_DRAW_TRIPLE) - ED_region_tag_redraw(ar); screen->do_draw_paintcursor = true; } } -void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *ar) -{ - bScreen *screen = WM_window_get_active_screen(win); - screen->do_draw_paintcursor = true; - wm_tag_redraw_overlay(win, ar); -} - void wm_draw_update(bContext *C) { wmWindowManager *wm = CTX_wm_manager(C); @@ -946,10 +795,6 @@ void wm_draw_update(bContext *C) continue; } #endif - if (win->drawmethod != U.wmdrawmethod) { - wm_draw_window_clear(win); - win->drawmethod = U.wmdrawmethod; - } if (wm_draw_update_test_window(win)) { bScreen *screen = WM_window_get_active_screen(win); @@ -963,26 +808,7 @@ void wm_draw_update(bContext *C) ED_screen_set_active_region(C, &win->eventstate->x); ED_screen_ensure_updated(wm, win, screen); - int drawmethod = wm_automatic_draw_method(win); - - if (win->drawfail) - wm_method_draw_overlap_all(C, win, 0); - else if (drawmethod == USER_DRAW_FULL) - wm_method_draw_full(C, win); - else if (drawmethod == USER_DRAW_OVERLAP) - wm_method_draw_overlap_all(C, win, 0); - else if (drawmethod == USER_DRAW_OVERLAP_FLIP) - wm_method_draw_overlap_all(C, win, 1); - else { /* USER_DRAW_TRIPLE */ - if ((WM_stereo3d_enabled(win, false)) == false) { - wm_method_draw_triple(C, win); - } - else { - wm_method_draw_triple_multiview(C, win, STEREO_LEFT_ID); - wm_method_draw_triple_multiview(C, win, STEREO_RIGHT_ID); - wm_method_draw_stereo3d(C, win); - } - } + wm_draw_window(C, win); screen->do_draw_gesture = false; screen->do_draw_paintcursor = false; @@ -995,44 +821,16 @@ void wm_draw_update(bContext *C) } } -void wm_draw_data_free(wmWindow *win) -{ - wmDrawData *dd; - - for (dd = win->drawdata.first; dd; dd = dd->next) { - wm_draw_triple_free(dd->triple); - } - BLI_freelistN(&win->drawdata); -} - -void wm_draw_window_clear(wmWindow *win) +void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar)) { bScreen *screen = WM_window_get_active_screen(win); - ARegion *ar; - - wm_draw_data_free(win); - - /* clear screen swap flags */ - if (screen) { - ED_screen_areas_iter(win, screen, sa) { - for (ar = sa->regionbase.first; ar; ar = ar->next) { - ar->swap = WIN_NONE_OK; - } - } - - screen->swap = WIN_NONE_OK; - } + screen->do_draw = true; } -void wm_draw_region_clear(wmWindow *win, ARegion *ar) +void WM_draw_region_free(ARegion *ar) { - bScreen *screen = WM_window_get_active_screen(win); - int drawmethod = wm_automatic_draw_method(win); - - if (ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP)) - wm_flush_regions_down(win, screen, &ar->winrct); - - screen->do_draw = true; + wm_draw_region_buffer_free(ar); + ar->visible = 0; } void WM_redraw_windows(bContext *C) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 495fac0123e..a64b633b000 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2614,12 +2614,6 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even /* restore cursor (disabled, see wm_dragdrop.c) */ // WM_cursor_modal_restore(win); } - - /* overlap fails otherwise */ - if (screen->do_draw_drag) - if (win->drawmethod == USER_DRAW_OVERLAP) - screen->do_draw = true; - } /* filter out all events of the pie that spawned the last pie unless it's a release event */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index c2331f44056..2c3583a9f02 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -447,12 +447,8 @@ void wm_gesture_draw(wmWindow *win) void wm_gesture_tag_redraw(bContext *C) { - wmWindow *win = CTX_wm_window(C); bScreen *screen = CTX_wm_screen(C); - ARegion *ar = CTX_wm_region(C); if (screen) screen->do_draw_gesture = true; - - wm_tag_redraw_overlay(win, ar); } diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index b52fc4ae213..14093d01695 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -53,35 +53,18 @@ #include "ED_screen.h" #include "GPU_immediate.h" +#include "GPU_framebuffer.h" +#include "GPU_texture.h" #include "WM_api.h" #include "WM_types.h" #include "wm.h" -#include "wm_draw.h" /* wmDrawTriple */ +#include "wm_draw.h" #include "wm_window.h" #include "UI_interface.h" #include "UI_resources.h" -static void wm_method_draw_stereo3d_pageflip(wmWindow *win) -{ - wmDrawData *drawdata; - int view; - - for (view = 0; view < 2; view ++) { - drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); - - if (view == STEREO_LEFT_ID) - glDrawBuffer(GL_BACK_LEFT); - else //STEREO_RIGHT_ID - glDrawBuffer(GL_BACK_RIGHT); - - wm_triple_draw_textures(win, drawdata->triple, 1.0f); - } - - glDrawBuffer(GL_BACK); -} - static GPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type) { switch (interlace_type) { @@ -95,75 +78,60 @@ static GPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType inte } } -static void wm_method_draw_stereo3d_interlace(wmWindow *win) +void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *ar) { bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0; enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type; - wmDrawData *drawdata[2]; - for (int eye = 0; eye < 2; eye++) { - int view = swap ? !eye : eye; - drawdata[eye] = BLI_findlink(&win->drawdata, (view * 2) + 1); - } - - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); - /* wmOrtho for the screen has this same offset */ - float ratiox = 1.0f; - float ratioy = 1.0f; - float halfx = GLA_PIXEL_OFS / sizex; - float halfy = GLA_PIXEL_OFS / sizex; + float halfx = GLA_PIXEL_OFS / ar->winx; + float halfy = GLA_PIXEL_OFS / ar->winy; Gwn_VertFormat *format = immVertexFormat(); unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); - - /* leave GL_TEXTURE0 as the latest bind texture */ - for (int eye = 1; eye >= 0; eye--) { - glActiveTexture(GL_TEXTURE0 + eye); - glBindTexture(GL_TEXTURE_2D, drawdata[eye]->triple->bind); + /* leave GL_TEXTURE0 as the latest active texture */ + for (int view = 1; view >= 0; view--) { + GPUTexture *texture = wm_draw_region_texture(ar, view); + glActiveTexture(GL_TEXTURE0 + view); + glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture)); } - immUniform1i("image_a", 0); - immUniform1i("image_b", 1); + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE); + immUniform1i("image_a", (swap)? 1: 0); + immUniform1i("image_b", (swap)? 0: 1); immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type)); immBegin(GWN_PRIM_TRI_FAN, 4); immAttrib2f(texcoord, halfx, halfy); - immVertex2f(pos, 0.0f, 0.0f); + immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymin); - immAttrib2f(texcoord, ratiox + halfx, halfy); - immVertex2f(pos, sizex, 0.0f); + immAttrib2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymin); - immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); - immVertex2f(pos, sizex, sizey); + immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, ar->winrct.xmax + 1, ar->winrct.ymax + 1); - immAttrib2f(texcoord, halfx, ratioy + halfy); - immVertex2f(pos, 0.0f, sizey); + immAttrib2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, ar->winrct.xmin, ar->winrct.ymax + 1); immEnd(); immUnbindProgram(); - for (int eye = 1; eye >= 0; eye--) { - glActiveTexture(GL_TEXTURE0 + eye); + for (int view = 1; view >= 0; view--) { + glActiveTexture(GL_TEXTURE0 + view); glBindTexture(GL_TEXTURE_2D, 0); } } -static void wm_method_draw_stereo3d_anaglyph(wmWindow *win) +void wm_stereo3d_draw_anaglyph(wmWindow *win, ARegion *ar) { - wmDrawData *drawdata; - int view, bit; + for (int view = 0; view < 2; view ++) { + int bit = view + 1; - for (view = 0; view < 2; view ++) { - drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); - - bit = view + 1; switch (win->stereo3d_format->anaglyph_type) { case S3D_ANAGLYPH_REDCYAN: glColorMask((1&bit) ? GL_TRUE : GL_FALSE, @@ -185,158 +153,104 @@ static void wm_method_draw_stereo3d_anaglyph(wmWindow *win) break; } - wm_triple_draw_textures(win, drawdata->triple, 1.0f); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + wm_draw_region_blend(ar, view, false); } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } -static void wm_method_draw_stereo3d_sidebyside(wmWindow *win) +void wm_stereo3d_draw_sidebyside(wmWindow *win, int view) { - wmDrawData *drawdata; - wmDrawTriple *triple; - int view; - int soffx; bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0; Gwn_VertFormat *format = immVertexFormat(); unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA); - glActiveTexture(GL_TEXTURE0); - - for (view = 0; view < 2; view ++) { - drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); - triple = drawdata->triple; + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); - soffx = WM_window_pixels_x(win) * 0.5f; - if (view == STEREO_LEFT_ID) { - if (!cross_eyed) - soffx = 0; - } - else { //RIGHT_LEFT_ID - if (cross_eyed) - soffx = 0; - } - - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); + int soffx = WM_window_pixels_x(win) * 0.5f; + if (view == STEREO_LEFT_ID) { + if (!cross_eyed) + soffx = 0; + } + else { //RIGHT_LEFT_ID + if (cross_eyed) + soffx = 0; + } - /* wmOrtho for the screen has this same offset */ - const float ratiox = 1.0f; - const float ratioy = 1.0f; - const float halfx = GLA_PIXEL_OFS / sizex; - const float halfy = GLA_PIXEL_OFS / sizey; + const int sizex = WM_window_pixels_x(win); + const int sizey = WM_window_pixels_y(win); - glBindTexture(GL_TEXTURE_2D, triple->bind); + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / sizex; + const float halfy = GLA_PIXEL_OFS / sizex; - immUniform1f("alpha", 1.0f); - immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ - immBegin(GWN_PRIM_TRI_FAN, 4); + immBegin(GWN_PRIM_TRI_FAN, 4); - immAttrib2f(texcoord, halfx, halfy); - immVertex2f(pos, soffx, 0.0f); + immAttrib2f(texcoord, halfx, halfy); + immVertex2f(pos, soffx, 0.0f); - immAttrib2f(texcoord, ratiox + halfx, halfy); - immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); + immAttrib2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f); - immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); - immVertex2f(pos, soffx + (sizex * 0.5f), sizey); + immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, soffx + (sizex * 0.5f), sizey); - immAttrib2f(texcoord, halfx, ratioy + halfy); - immVertex2f(pos, soffx, sizey); + immAttrib2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, soffx, sizey); - immEnd(); - } + immEnd(); - glBindTexture(GL_TEXTURE_2D, 0); immUnbindProgram(); } -static void wm_method_draw_stereo3d_topbottom(wmWindow *win) +void wm_stereo3d_draw_topbottom(wmWindow *win, int view) { - wmDrawData *drawdata; - wmDrawTriple *triple; - int view; - int soffy; - Gwn_VertFormat *format = immVertexFormat(); unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA); - glActiveTexture(GL_TEXTURE0); - - for (view = 0; view < 2; view ++) { - drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1); - triple = drawdata->triple; - - if (view == STEREO_LEFT_ID) { - soffy = WM_window_pixels_y(win) * 0.5f; - } - else { /* STEREO_RIGHT_ID */ - soffy = 0; - } + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE); - const int sizex = WM_window_pixels_x(win); - const int sizey = WM_window_pixels_y(win); + int soffy; + if (view == STEREO_LEFT_ID) { + soffy = WM_window_pixels_y(win) * 0.5f; + } + else { /* STEREO_RIGHT_ID */ + soffy = 0; + } - /* wmOrtho for the screen has this same offset */ - const float ratiox = 1.0f; - const float ratioy = 1.0f; - const float halfx = GLA_PIXEL_OFS / sizex; - const float halfy = GLA_PIXEL_OFS / sizey; + const int sizex = WM_window_pixels_x(win); + const int sizey = WM_window_pixels_y(win); - glBindTexture(GL_TEXTURE_2D, triple->bind); + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / sizex; + const float halfy = GLA_PIXEL_OFS / sizex; - immUniform1f("alpha", 1.0f); - immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */ - immBegin(GWN_PRIM_TRI_FAN, 4); + immBegin(GWN_PRIM_TRI_FAN, 4); - immAttrib2f(texcoord, halfx, halfy); - immVertex2f(pos, 0.0f, soffy); + immAttrib2f(texcoord, halfx, halfy); + immVertex2f(pos, 0.0f, soffy); - immAttrib2f(texcoord, ratiox + halfx, halfy); - immVertex2f(pos, sizex, soffy); + immAttrib2f(texcoord, 1.0f + halfx, halfy); + immVertex2f(pos, sizex, soffy); - immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy); - immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); + immAttrib2f(texcoord, 1.0f + halfx, 1.0f + halfy); + immVertex2f(pos, sizex, soffy + (sizey * 0.5f)); - immAttrib2f(texcoord, halfx, ratioy + halfy); - immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); + immAttrib2f(texcoord, halfx, 1.0f + halfy); + immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f)); - immEnd(); - } + immEnd(); immUnbindProgram(); - glBindTexture(GL_TEXTURE_2D, 0); } -void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win) -{ - switch (win->stereo3d_format->display_mode) { - case S3D_DISPLAY_ANAGLYPH: - wm_method_draw_stereo3d_anaglyph(win); - break; - case S3D_DISPLAY_INTERLACE: - wm_method_draw_stereo3d_interlace(win); - break; - case S3D_DISPLAY_PAGEFLIP: - wm_method_draw_stereo3d_pageflip(win); - break; - case S3D_DISPLAY_SIDEBYSIDE: - wm_method_draw_stereo3d_sidebyside(win); - break; - case S3D_DISPLAY_TOPBOTTOM: - wm_method_draw_stereo3d_topbottom(win); - break; - default: - break; - } -} static bool wm_stereo3d_quadbuffer_supported(void) { diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index f34b5bf9c95..89a12206a66 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -69,6 +69,8 @@ void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct scissor_pad = false; } + int x = drawrct->xmin - winrct->xmin; + int y = drawrct->ymin - winrct->ymin; int width = BLI_rcti_size_x(winrct) + 1; int height = BLI_rcti_size_y(winrct) + 1; @@ -83,8 +85,8 @@ void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct scissor_height += 1; } - glViewport(winrct->xmin, winrct->ymin, width, height); - glScissor(drawrct->xmin, drawrct->ymin, scissor_width, scissor_height); + glViewport(0, 0, width, height); + glScissor(x, y, scissor_width, scissor_height); wmOrtho2_pixelspace(width, height); gpuLoadIdentity(); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 4efca37b921..e0a1f0f14ad 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -228,8 +228,6 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) wm_event_free_all(win); - wm_draw_data_free(win); - wm_ghostwindow_destroy(wm, win); BKE_workspace_instance_hook_free(G.main, win->workspace_hook); @@ -305,10 +303,6 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_la layout_new = duplicate_layout ? ED_workspace_layout_duplicate(workspace, layout_old, win_dst) : layout_old; WM_window_set_active_layout(win_dst, workspace, layout_new); - win_dst->drawmethod = U.wmdrawmethod; - - BLI_listbase_clear(&win_dst->drawdata); - *win_dst->stereo3d_format = *win_src->stereo3d_format; return win_dst; @@ -508,8 +502,6 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) BLI_remlink(&wm->windows, win); - wm_draw_window_clear(win); - CTX_wm_window_set(C, win); /* needed by handlers */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); @@ -826,8 +818,6 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) win->sizex = BLI_rcti_size_x(rect); win->sizey = BLI_rcti_size_y(rect); - win->drawmethod = U.wmdrawmethod; - WM_check(C); if (win->ghostwin) { @@ -1481,7 +1471,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } wm_window_make_drawable(wm, win); - wm_draw_window_clear(win); BKE_icon_changed(screen->id.icon_id); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); @@ -1604,7 +1593,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr CTX_wm_window_set(C, oldWindow); wm_window_make_drawable(wm, win); - wm_draw_window_clear(win); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index b2e8c914fa8..073adef177c 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -31,6 +31,7 @@ #ifndef __WM_H__ #define __WM_H__ +struct ARegion; struct wmWindow; struct ReportList; @@ -82,7 +83,11 @@ void wm_autosave_read(bContext *C, struct ReportList *reports); void wm_autosave_location(char *filepath); /* wm_stereo.c */ -void wm_method_draw_stereo3d(const bContext *C, wmWindow *win); +void wm_stereo3d_draw_interlace(wmWindow *win, struct ARegion *ar); +void wm_stereo3d_draw_anaglyph(wmWindow *win, struct ARegion *ar); +void wm_stereo3d_draw_sidebyside(wmWindow *win, int view); +void wm_stereo3d_draw_topbottom(wmWindow *win, int view); + void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy); int wm_stereo3d_set_exec(bContext *C, wmOperator *op); int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event); diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h index fa3d443e6ae..096d241eb64 100644 --- a/source/blender/windowmanager/wm_draw.h +++ b/source/blender/windowmanager/wm_draw.h @@ -34,29 +34,27 @@ #include "GPU_glew.h" -typedef struct wmDrawTriple { - GLuint bind; -} wmDrawTriple; +struct GPUOffScreen; +struct GPUViewport; +struct GPUTexture; -typedef struct wmDrawData { - struct wmDrawData *next, *prev; - wmDrawTriple *triple; -} wmDrawData; +typedef struct wmDrawBuffer { + struct GPUOffScreen *offscreen[2]; + struct GPUViewport *viewport[2]; + bool stereo; + int bound_view; +} wmDrawBuffer; struct bContext; struct wmWindow; struct ARegion; /* wm_draw.c */ -void wm_draw_update (struct bContext *C); -void wm_draw_window_clear (struct wmWindow *win); -void wm_draw_region_clear (struct wmWindow *win, struct ARegion *ar); +void wm_draw_update(struct bContext *C); +void wm_draw_region_clear(struct wmWindow *win, struct ARegion *ar); +void wm_draw_region_blend(struct ARegion *ar, int view, bool blend); -void wm_tag_redraw_overlay (struct wmWindow *win, struct ARegion *ar); - -void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha); - -void wm_draw_data_free (struct wmWindow *win); +struct GPUTexture *wm_draw_region_texture(struct ARegion *ar, int view); #endif /* __WM_DRAW_H__ */ |