[Bf-blender-cvs] [f021635bd53] master: WM: support window context override

Campbell Barton noreply at git.blender.org
Sat Jun 29 10:22:50 CEST 2019


Commit: f021635bd5311bff28d44989f2fc14d3e37215a8
Author: Campbell Barton
Date:   Sat Jun 29 17:48:51 2019 +1000
Branches: master
https://developer.blender.org/rBf021635bd5311bff28d44989f2fc14d3e37215a8

WM: support window context override

This makes it possible to take a screenshot from any window in Python.

===================================================================

M	source/blender/editors/screen/screendump.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

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
@@ -1936,6 +1936,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
  * \{ */



More information about the Bf-blender-cvs mailing list