summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2014-09-07 18:58:09 +0800
committerRichard Grenville <[email protected]>2014-09-07 18:58:09 +0800
commite3717f4f7bf3a0a0a015337454f1e381a6e0278f (patch)
tree154628c6c6fc92922281573b424f076b1ff784f5
parent886cdca8a59d0ce17d380560490ea06b9f089aa3 (diff)
downloadtdebase-e3717f4f7bf3a0a0a015337454f1e381a6e0278f.tar.gz
tdebase-e3717f4f7bf3a0a0a015337454f1e381a6e0278f.zip
Misc #204: Add glx_take_screenshot() & others
- Add glx_take_screenshot() for taking a screenshot. With ImageMagick the output data could be viewed in this way: display -size [SCREEN-WIDTH]x[SCREEN-HEIGHT] -depth 8 -flip rgb:[PATH] (#204) - Add D-Bus command `opts_get string:paint_on_overlay_id` to get X Composite overlay window ID. (#204) - Code cleanup.
-rw-r--r--common.h25
-rw-r--r--compton.c24
-rw-r--r--dbus.c5
-rw-r--r--opengl.c84
4 files changed, 109 insertions, 29 deletions
diff --git a/common.h b/common.h
index f9b5d9453..0aa4f18b8 100644
--- a/common.h
+++ b/common.h
@@ -2208,6 +2208,9 @@ glx_render_(session_t *ps, const glx_texture_t *ptex,
void
glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg);
+unsigned char *
+glx_take_screenshot(session_t *ps, int *out_length);
+
#ifdef CONFIG_VSYNC_OPENGL_GLSL
GLuint
glx_create_shader(GLenum shader_type, const char *shader_str);
@@ -2485,6 +2488,28 @@ c2_matchd(session_t *ps, win *w, const c2_lptr_t *condlst,
#endif
/**
+ * @brief Dump the given data to a file.
+ */
+static inline bool
+write_binary_data(const char *path, const unsigned char *data, int length) {
+ if (!data)
+ return false;
+ FILE *f = fopen(path, "wb");
+ if (!f) {
+ printf_errf("(\"%s\"): Failed to open file for writing.", path);
+ return false;
+ }
+ int wrote_len = fwrite(data, sizeof(unsigned char), length, f);
+ fclose(f);
+ if (wrote_len != length) {
+ printf_errf("(\"%s\"): Failed to write all blocks: %d / %d", path,
+ wrote_len, length);
+ return false;
+ }
+ return true;
+}
+
+/**
* @brief Dump raw bytes in HEX format.
*
* @param data pointer to raw data
diff --git a/compton.c b/compton.c
index 330155891..b967372ee 100644
--- a/compton.c
+++ b/compton.c
@@ -1411,6 +1411,20 @@ xr_blur_dst(session_t *ps, Picture tgt_buffer,
return true;
}
+/*
+ * WORK-IN-PROGRESS!
+static void
+xr_take_screenshot(session_t *ps) {
+ XImage *img = XGetImage(ps->dpy, get_tgt_window(ps), 0, 0,
+ ps->root_width, ps->root_height, AllPlanes, XYPixmap);
+ if (!img) {
+ printf_errf("(): Failed to get XImage.");
+ return NULL;
+ }
+ assert(0 == img->xoffset);
+}
+*/
+
/**
* Blur the background of a window.
*/
@@ -7530,6 +7544,16 @@ session_destroy(session_t *ps) {
ps_g = NULL;
}
+/*
+static inline void
+dump_img(session_t *ps) {
+ int len = 0;
+ unsigned char *d = glx_take_screenshot(ps, &len);
+ write_binary_data("/tmp/dump.raw", d, len);
+ free(d);
+}
+*/
+
/**
* Do the actual work.
*
diff --git a/dbus.c b/dbus.c
index 8aec9ea82..874f565ca 100644
--- a/dbus.c
+++ b/dbus.c
@@ -901,6 +901,11 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
cdbus_m_opts_get_do(fork_after_register, cdbus_reply_bool);
cdbus_m_opts_get_do(detect_rounded_corners, cdbus_reply_bool);
cdbus_m_opts_get_do(paint_on_overlay, cdbus_reply_bool);
+ // paint_on_overlay_id: Get ID of the X composite overlay window
+ if (!strcmp("paint_on_overlay_id", target)) {
+ cdbus_reply_uint32(ps, msg, ps->overlay);
+ return true;
+ }
cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool);
cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32);
cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum);
diff --git a/opengl.c b/opengl.c
index 800ebd585..5a98f4e0a 100644
--- a/opengl.c
+++ b/opengl.c
@@ -1442,7 +1442,7 @@ glx_render_(session_t *ps, const glx_texture_t *ptex,
#endif
argb = argb || (GLX_TEXTURE_FORMAT_RGBA_EXT ==
- ps->psglx->fbconfigs[ptex->depth]->texture_fmt);
+ ps->psglx->fbconfigs[ptex->depth]->texture_fmt);
#ifdef CONFIG_VSYNC_OPENGL_GLSL
const bool has_prog = pprogram && pprogram->prog;
#endif
@@ -1754,6 +1754,32 @@ glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg) {
cxfree(rects);
}
+/**
+ * @brief Get tightly packed RGB888 data from GL front buffer.
+ *
+ * Don't expect any sort of decent performance.
+ *
+ * @returns tightly packed RGB888 data of the size of the screen,
+ * to be freed with `free()`
+ */
+unsigned char *
+glx_take_screenshot(session_t *ps, int *out_length) {
+ int length = 3 * ps->root_width * ps->root_height;
+ GLint unpack_align_old = 0;
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_align_old);
+ assert(unpack_align_old > 0);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ unsigned char *buf = cmalloc(length, unsigned char);
+ glReadBuffer(GL_FRONT);
+ glReadPixels(0, 0, ps->root_width, ps->root_height, GL_RGB,
+ GL_UNSIGNED_BYTE, buf);
+ glReadBuffer(GL_BACK);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_align_old);
+ if (out_length)
+ *out_length = sizeof(unsigned char) * length;
+ return buf;
+}
+
#ifdef CONFIG_VSYNC_OPENGL_GLSL
GLuint
glx_create_shader(GLenum shader_type, const char *shader_str) {
@@ -1847,34 +1873,34 @@ glx_create_program_end:
*/
GLuint
glx_create_program_from_str(const char *vert_shader_str,
- const char *frag_shader_str) {
- GLuint vert_shader = 0;
- GLuint frag_shader = 0;
- GLuint prog = 0;
-
- if (vert_shader_str)
- vert_shader = glx_create_shader(GL_VERTEX_SHADER, vert_shader_str);
- if (frag_shader_str)
- frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, frag_shader_str);
-
- {
- GLuint shaders[2];
- int count = 0;
- if (vert_shader)
- shaders[count++] = vert_shader;
- if (frag_shader)
- shaders[count++] = frag_shader;
- assert(count <= sizeof(shaders) / sizeof(shaders[0]));
- if (count)
- prog = glx_create_program(shaders, count);
- }
-
- if (vert_shader)
- glDeleteShader(vert_shader);
- if (frag_shader)
- glDeleteShader(frag_shader);
-
- return prog;
+ const char *frag_shader_str) {
+ GLuint vert_shader = 0;
+ GLuint frag_shader = 0;
+ GLuint prog = 0;
+
+ if (vert_shader_str)
+ vert_shader = glx_create_shader(GL_VERTEX_SHADER, vert_shader_str);
+ if (frag_shader_str)
+ frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, frag_shader_str);
+
+ {
+ GLuint shaders[2];
+ int count = 0;
+ if (vert_shader)
+ shaders[count++] = vert_shader;
+ if (frag_shader)
+ shaders[count++] = frag_shader;
+ assert(count <= sizeof(shaders) / sizeof(shaders[0]));
+ if (count)
+ prog = glx_create_program(shaders, count);
+ }
+
+ if (vert_shader)
+ glDeleteShader(vert_shader);
+ if (frag_shader)
+ glDeleteShader(frag_shader);
+
+ return prog;
}
#endif