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.
This commit is contained in:
parent
c5f45c8e3c
commit
8c88b4d6f1
25
src/common.h
25
src/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);
|
||||
|
@ -2484,6 +2487,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.
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
76
src/opengl.c
76
src/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;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
{
|
||||
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);
|
||||
if (vert_shader)
|
||||
glDeleteShader(vert_shader);
|
||||
if (frag_shader)
|
||||
glDeleteShader(frag_shader);
|
||||
|
||||
return prog;
|
||||
return prog;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue