diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-06-29 10:48:51 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-06-29 11:21:53 +0300 |
commit | f021635bd5311bff28d44989f2fc14d3e37215a8 (patch) | |
tree | 70bbaabd9208743d6a79bf14a1adef0b42dcbc6d | |
parent | 71086995a552d41be361e49e7c3f3cfbfffa4dac (diff) |
WM: support window context override
This makes it possible to take a screenshot from any window in Python.
-rw-r--r-- | source/blender/editors/screen/screendump.c | 50 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 44 |
3 files changed, 53 insertions, 43 deletions
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 3b763c7d47a..e5552314a6e 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -43,8 +43,6 @@ #include "BKE_main.h" #include "BKE_report.h" -#include "BIF_gl.h" - #include "RNA_access.h" #include "RNA_define.h" @@ -63,59 +61,25 @@ typedef struct ScreenshotData { ImageFormatData im_format; } ScreenshotData; -static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *rect) -{ - int i; - - glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glFinish(); - - /* clear alpha, it is not set to a meaningful value in opengl */ - for (i = 0, rect += 3; i < w * h; i++, rect += 4) { - *rect = 255; - } -} - -/* get shot from frontbuffer */ -static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy) -{ - wmWindow *win = CTX_wm_window(C); - int x = 0, y = 0; - unsigned int *dumprect = NULL; - - x = 0; - y = 0; - *dumpsx = WM_window_pixels_x(win); - *dumpsy = WM_window_pixels_y(win); - - if (*dumpsx && *dumpsy) { - - dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect"); - glReadBuffer(GL_FRONT); - screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char *)dumprect); - glReadBuffer(GL_BACK); - } - - return dumprect; -} - /* call from both exec and invoke */ static int screenshot_data_create(bContext *C, wmOperator *op) { - unsigned int *dumprect; - int dumpsx, dumpsy; + int dumprect_size[2]; + + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); /* do redraw so we don't show popups/menus */ WM_redraw_windows(C); - dumprect = screenshot(C, &dumpsx, &dumpsy); + uint *dumprect = WM_window_pixels_read(wm, win, dumprect_size); if (dumprect) { ScreenshotData *scd = MEM_callocN(sizeof(ScreenshotData), "screenshot"); ScrArea *sa = CTX_wm_area(C); - scd->dumpsx = dumpsx; - scd->dumpsy = dumpsy; + scd->dumpsx = dumprect_size[0]; + scd->dumpsy = dumprect_size[1]; scd->dumprect = dumprect; if (sa) { scd->crop = sa->totrct; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 61b3b8aa2a2..d4fbbd1ecff 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -105,6 +105,8 @@ void WM_init_opengl(struct Main *bmain); void WM_check(struct bContext *C); void WM_reinit_gizmomap_all(struct Main *bmain); +uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]); + int WM_window_pixels_x(const struct wmWindow *win); int WM_window_pixels_y(const struct wmWindow *win); void WM_window_rect_calc(const struct wmWindow *win, struct rcti *r_rect); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 7558468c3b5..ea3596a2143 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1937,6 +1937,50 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Window Screen Shot Utility + * + * Include here since it can involve low level buffer switching. + * + * \{ */ + +uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2]) +{ + bool setup_context = wm->windrawable != win; + + if (setup_context) { + GHOST_ActivateWindowDrawingContext(win->ghostwin); + GPU_context_active_set(win->gpuctx); + } + + r_size[0] = WM_window_pixels_x(win); + r_size[1] = WM_window_pixels_y(win); + const uint rect_len = r_size[0] * r_size[1]; + uint *rect = MEM_mallocN(sizeof(*rect) * rect_len, __func__); + + glReadBuffer(GL_FRONT); + glReadPixels(0, 0, r_size[0], r_size[1], GL_RGBA, GL_UNSIGNED_BYTE, rect); + glFinish(); + glReadBuffer(GL_BACK); + + if (setup_context) { + if (wm->windrawable) { + GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin); + GPU_context_active_set(wm->windrawable->gpuctx); + } + } + + /* Clear alpha, it is not set to a meaningful value in OpenGL. */ + uchar *cp = (uchar *)rect; + uint i; + for (i = 0, cp += 3; i < rect_len; i++, cp += 4) { + *cp = 0xff; + } + return (uint *)rect; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Initial Window State API * \{ */ |