Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-27 11:22:37 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-27 13:14:14 +0300
commite01cadd657c76267266546781703df107c55f83a (patch)
treeaf6685123707af7cce17c74d681dcce378d4bc72 /source/blender/windowmanager/intern/wm_draw.c
parent868c9ac408f75634c75bf4bc0b17c87b79d7af73 (diff)
WM: new offscreen window draw method to replace all existing methods.
For Blender 2.8 we had to be compatible with very old OpenGL versions, and triple buffer was designed to work without offscreen rendering, by copying the the backbuffer to a texture right before swapping. This way we could avoid redrawing unchanged regions by copying them from this texture on the next redraws. Triple buffer used to suffer from poor performance and driver bugs on specific cards, so alternative draw methods remained available. Now that we require newer OpenGL, we can have just a single draw method that draw each region into an offscreen buffer, and then draws those to the screen. This has some advantages: * Poor 3D view performance when using Region Overlap should be solved now, since we can also cache overlapping regions in offscreen buffers. * Page flip, anaglyph and interlace stereo drawing can be a little faster by avoiding a copy to an intermediate texture. * The new 3D view drawing already writes to an offscreen buffer, which we can draw from directly instead of duplicating it to another buffer. * Eventually we will be able to remove depth and stencil buffers from the window and save memory, though at the moment there are still some tools using it so it's not possible yet. * This also fixes a bug with Eevee sampling not progressing with stereo drawing in the 3D viewport. Differential Revision: https://developer.blender.org/D3061
Diffstat (limited to 'source/blender/windowmanager/intern/wm_draw.c')
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c1026
1 files changed, 412 insertions, 614 deletions
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)