diff --git a/test/linux/linux.c b/test/linux/linux.c index 41c7258d4..294e21d47 100644 --- a/test/linux/linux.c +++ b/test/linux/linux.c @@ -23,8 +23,8 @@ extern struct obs_source_info pulse_input; bool obs_module_load(uint32_t obs_version) { - UNUSED_PARAMETER(obs_version); - obs_register_source(&xshm_input); - obs_register_source(&pulse_input); - return true; + UNUSED_PARAMETER(obs_version); + obs_register_source(&xshm_input); + obs_register_source(&pulse_input); + return true; } diff --git a/test/linux/xcursor.c b/test/linux/xcursor.c index 4ac187fbf..cc7c7aa78 100644 --- a/test/linux/xcursor.c +++ b/test/linux/xcursor.c @@ -14,106 +14,99 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include -#include + +#include #include + +#include #include "xcursor.h" -uint32_t *xcursor_pixels(XFixesCursorImage *xc) { - int size = xc->width * xc->height; - uint32_t *pixels = bmalloc(size * 4); - - // pixel data from XFixes is defined as unsigned long ... - // TODO: check why everybody is making a fuss about this - for (int i = 0; i < size; ++i) - pixels[i] = (uint32_t) xc->pixels[i]; - - return pixels; +/* + * Get pixel data for the cursor + * + * XFixes has the data defined as unsigned long, so we can not use memcpy. + * Theres a lot of talk about this in other implementation and they tend to + * be really complicated, but this naive approach seems to work fine ... + */ +static uint32_t *xcursor_pixels(XFixesCursorImage *xc) { + uint_fast32_t size = xc->width * xc->height; + uint32_t *pixels = bmalloc(size * sizeof(uint32_t)); + + for (uint_fast32_t i = 0; i < size; ++i) + pixels[i] = (uint32_t) xc->pixels[i]; + + return pixels; } -void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) { - // get cursor pixel data - uint32_t *pixels = xcursor_pixels(xc); - - // if the cursor has the same size as the last one we can simply update - if (data->tex - && data->last_height == xc->width - && data->last_width == xc->height) { - texture_setimage(data->tex, (void **) pixels, xc->width * 4, False); - } - else { - if (data->tex) - texture_destroy(data->tex); - - data->tex = gs_create_texture( - xc->width, xc->height, - GS_RGBA, 1, - (const void **) &pixels, - GS_DYNAMIC - ); - } - bfree(pixels); - - // set some data - data->last_serial = xc->cursor_serial; - data->last_width = xc->width; - data->last_height = xc->height; +/* + * Create the cursor texture, either by updating if the new cursor has the same + * size or by creating a new texture if the size is different + */ +static void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) { + uint32_t *pixels = xcursor_pixels(xc); + + if (data->tex + && data->last_height == xc->width + && data->last_width == xc->height) { + texture_setimage(data->tex, (void **) pixels, + xc->width * sizeof(uint32_t), False); + } else { + if (data->tex) + texture_destroy(data->tex); + + data->tex = gs_create_texture(xc->width, xc->height, + GS_RGBA, 1, (const void **) &pixels, GS_DYNAMIC); + } + + bfree(pixels); + + data->last_serial = xc->cursor_serial; + data->last_width = xc->width; + data->last_height = xc->height; } xcursor_t *xcursor_init(Display *dpy) { - xcursor_t *data = bmalloc(sizeof(xcursor_t)); - memset(data, 0, sizeof(xcursor_t)); - - data->dpy = dpy; - - // initialize texture so we don't crash - xcursor_tick(data); - - return data; + xcursor_t *data = bmalloc(sizeof(xcursor_t)); + memset(data, 0, sizeof(xcursor_t)); + + data->dpy = dpy; + xcursor_tick(data); + + return data; } void xcursor_destroy(xcursor_t *data) { - if (data->tex) - texture_destroy(data->tex); - bfree(data); + if (data->tex) + texture_destroy(data->tex); + bfree(data); } void xcursor_tick(xcursor_t *data) { - // get cursor data - XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy); - - // update cursor if necessary - if (!data->tex || data->last_serial != xc->cursor_serial) - xcursor_create(data, xc); - - // update cursor position - data->pos_x = -1.0 * (xc->x - xc->xhot); - data->pos_y = -1.0 * (xc->y - xc->yhot); - - XFree(xc); + XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy); + + if (!data->tex || data->last_serial != xc->cursor_serial) + xcursor_create(data, xc); + data->pos_x = -1.0 * (xc->x - xc->xhot); + data->pos_y = -1.0 * (xc->y - xc->yhot); + + XFree(xc); } void xcursor_render(xcursor_t *data) { - // TODO: why do i need effects ? - effect_t effect = gs_geteffect(); - eparam_t image = effect_getparambyname(effect, "image"); - - effect_settexture(effect, image, data->tex); - - gs_matrix_push(); - - // move cursor to the right position - gs_matrix_translate3f( - data->pos_x, - data->pos_y, - 0 - ); - - // blend cursor - gs_enable_blending(True); - gs_blendfunction(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); - gs_draw_sprite(data->tex, 0, 0, 0); - gs_enable_blending(False); - - gs_matrix_pop(); + /* TODO: why do i need effects ? */ + effect_t effect = gs_geteffect(); + eparam_t image = effect_getparambyname(effect, "image"); + + effect_settexture(effect, image, data->tex); + + gs_matrix_push(); + + gs_matrix_translate3f(data->pos_x, data->pos_y, 0); + + gs_enable_blending(True); + gs_blendfunction(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); + gs_draw_sprite(data->tex, 0, 0, 0); + gs_enable_blending(False); + + gs_matrix_pop(); } diff --git a/test/linux/xcursor.h b/test/linux/xcursor.h index 72436f2fb..69dfe4297 100644 --- a/test/linux/xcursor.h +++ b/test/linux/xcursor.h @@ -14,6 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ + #pragma once #include @@ -23,13 +24,13 @@ extern "C" { #endif typedef struct { - Display *dpy; - float pos_x; - float pos_y; - unsigned long last_serial; - unsigned short int last_width; - unsigned short int last_height; - texture_t tex; + Display *dpy; + float pos_x; + float pos_y; + unsigned long last_serial; + unsigned short int last_width; + unsigned short int last_height; + texture_t tex; } xcursor_t; /** @@ -60,4 +61,4 @@ void xcursor_render(xcursor_t *data); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/test/linux/xshm-input.c b/test/linux/xshm-input.c index fb4d59f35..51914c406 100644 --- a/test/linux/xshm-input.c +++ b/test/linux/xshm-input.c @@ -28,191 +28,179 @@ along with this program. If not, see . #define XSHM_DATA(voidptr) struct xshm_data *data = voidptr; struct xshm_data { - Display *dpy; - Window root_window; - uint32_t width, height; - int shm_attached; - XShmSegmentInfo shm_info; - XImage *image; - texture_t texture; - xcursor_t *cursor; + Display *dpy; + Window root_window; + uint32_t width, height; + int shm_attached; + XShmSegmentInfo shm_info; + XImage *image; + texture_t texture; + xcursor_t *cursor; }; -static const char* xshm_input_getname(const char* locale) +static const char* xshm_getname(const char* locale) { - UNUSED_PARAMETER(locale); - return "X11 Shared Memory Screen Input"; + UNUSED_PARAMETER(locale); + return "X11 Shared Memory Screen Input"; } -static void xshm_input_destroy(void *vptr) +static void xshm_destroy(void *vptr) { - XSHM_DATA(vptr); - - if (data) { - gs_entercontext(obs_graphics()); - - texture_destroy(data->texture); - xcursor_destroy(data->cursor); - - gs_leavecontext(); - - // detach xshm - if (data->shm_attached) - XShmDetach(data->dpy, &data->shm_info); - - // detach shared memory - if (data->shm_info.shmaddr != (char *) -1) { - shmdt(data->shm_info.shmaddr); - data->shm_info.shmaddr = (char *) -1; - } - - // remove shared memory - if (data->shm_info.shmid != -1) - shmctl(data->shm_info.shmid, IPC_RMID, NULL); - - // destroy image - if (data->image) - XDestroyImage(data->image); - - // close display - if (data->dpy) - XCloseDisplay(data->dpy); - - bfree(data); - } + XSHM_DATA(vptr); + + if (!data) + return; + + gs_entercontext(obs_graphics()); + + texture_destroy(data->texture); + xcursor_destroy(data->cursor); + + gs_leavecontext(); + + if (data->shm_attached) + XShmDetach(data->dpy, &data->shm_info); + + if (data->shm_info.shmaddr != (char *) -1) { + shmdt(data->shm_info.shmaddr); + data->shm_info.shmaddr = (char *) -1; + } + + if (data->shm_info.shmid != -1) + shmctl(data->shm_info.shmid, IPC_RMID, NULL); + + if (data->image) + XDestroyImage(data->image); + + if (data->dpy) + XCloseDisplay(data->dpy); + + bfree(data); } -static void *xshm_input_create(obs_data_t settings, obs_source_t source) +static void *xshm_create(obs_data_t settings, obs_source_t source) { - UNUSED_PARAMETER(settings); - UNUSED_PARAMETER(source); - - // create data structure - struct xshm_data *data = bmalloc(sizeof(struct xshm_data)); - memset(data, 0, sizeof(struct xshm_data)); - - // try to open display and all the good stuff - data->dpy = XOpenDisplay(NULL); - if (!data->dpy) - goto fail; - - Screen *screen = XDefaultScreenOfDisplay(data->dpy); - data->width = WidthOfScreen(screen); - data->height = HeightOfScreen(screen); - data->root_window = XRootWindowOfScreen(screen); - Visual *visual = DefaultVisualOfScreen(screen); - int depth = DefaultDepthOfScreen(screen); - - // query for shm extension - if (!XShmQueryExtension(data->dpy)) - goto fail; - - // create xshm image - data->image = XShmCreateImage(data->dpy, visual, depth, - ZPixmap, NULL, &data->shm_info, - data->width, data->height); - if (!data->image) - goto fail; - - // create shared memory - data->shm_info.shmid = shmget(IPC_PRIVATE, data->image->bytes_per_line * - data->image->height, IPC_CREAT | 0700); - if (data->shm_info.shmid < 0) - goto fail; - - // attach shared memory - data->shm_info.shmaddr = data->image->data - = (char *) shmat(data->shm_info.shmid, 0, 0); - if (data->shm_info.shmaddr == (char *) -1) - goto fail; - // set shared memory as read only - data->shm_info.readOnly = False; - - // attach shm - if (!XShmAttach(data->dpy, &data->shm_info)) - goto fail; - data->shm_attached = 1; - - // get image - if (!XShmGetImage(data->dpy, data->root_window, data->image, - 0, 0, AllPlanes)) - goto fail; - - // create obs texture - gs_entercontext(obs_graphics()); - data->texture = gs_create_texture(data->width, data->height, GS_BGRA, 1, - (const void**) &data->image->data, - GS_DYNAMIC); - data->cursor = xcursor_init(data->dpy); - gs_leavecontext(); - - if (!data->texture) - goto fail; - - return data; - + UNUSED_PARAMETER(settings); + UNUSED_PARAMETER(source); + + + struct xshm_data *data = bmalloc(sizeof(struct xshm_data)); + memset(data, 0, sizeof(struct xshm_data)); + + data->dpy = XOpenDisplay(NULL); + if (!data->dpy) + goto fail; + + Screen *screen = XDefaultScreenOfDisplay(data->dpy); + data->width = WidthOfScreen(screen); + data->height = HeightOfScreen(screen); + data->root_window = XRootWindowOfScreen(screen); + Visual *visual = DefaultVisualOfScreen(screen); + int depth = DefaultDepthOfScreen(screen); + + if (!XShmQueryExtension(data->dpy)) + goto fail; + + data->image = XShmCreateImage(data->dpy, visual, depth, + ZPixmap, NULL, &data->shm_info, data->width, data->height); + if (!data->image) + goto fail; + + data->shm_info.shmid = shmget(IPC_PRIVATE, + data->image->bytes_per_line * data->image->height, + IPC_CREAT | 0700); + if (data->shm_info.shmid < 0) + goto fail; + + data->shm_info.shmaddr + = data->image->data + = (char *) shmat(data->shm_info.shmid, 0, 0); + if (data->shm_info.shmaddr == (char *) -1) + goto fail; + data->shm_info.readOnly = False; + + + if (!XShmAttach(data->dpy, &data->shm_info)) + goto fail; + data->shm_attached = 1; + + if (!XShmGetImage(data->dpy, data->root_window, data->image, + 0, 0, AllPlanes)) { + goto fail; + } + + + gs_entercontext(obs_graphics()); + data->texture = gs_create_texture(data->width, data->height, + GS_BGRA, 1, (const void**) &data->image->data, GS_DYNAMIC); + data->cursor = xcursor_init(data->dpy); + gs_leavecontext(); + + if (!data->texture) + goto fail; + + return data; + fail: - // clean up and return null - xshm_input_destroy(data); - return NULL; + xshm_destroy(data); + return NULL; } -static void xshm_input_video_tick(void *vptr, float seconds) +static void xshm_video_tick(void *vptr, float seconds) { - UNUSED_PARAMETER(seconds); - XSHM_DATA(vptr); - - gs_entercontext(obs_graphics()); - - // update screen texture - XShmGetImage(data->dpy, data->root_window, data->image, 0, 0, AllPlanes); - texture_setimage(data->texture, (void *) data->image->data, - data->width * 4, False); - - // update mouse cursor - xcursor_tick(data->cursor); - - gs_leavecontext(); + UNUSED_PARAMETER(seconds); + XSHM_DATA(vptr); + + gs_entercontext(obs_graphics()); + + + XShmGetImage(data->dpy, data->root_window, data->image, + 0, 0, AllPlanes); + texture_setimage(data->texture, (void *) data->image->data, + data->width * 4, False); + + xcursor_tick(data->cursor); + + gs_leavecontext(); } -static void xshm_input_video_render(void *vptr, effect_t effect) +static void xshm_video_render(void *vptr, effect_t effect) { - XSHM_DATA(vptr); - - eparam_t image = effect_getparambyname(effect, "image"); - effect_settexture(effect, image, data->texture); - - gs_enable_blending(False); - - gs_draw_sprite(data->texture, 0, 0, 0); - - // render the cursor - xcursor_render(data->cursor); + XSHM_DATA(vptr); + + eparam_t image = effect_getparambyname(effect, "image"); + effect_settexture(effect, image, data->texture); + + gs_enable_blending(False); + + gs_draw_sprite(data->texture, 0, 0, 0); + + xcursor_render(data->cursor); } -static uint32_t xshm_input_getwidth(void *vptr) +static uint32_t xshm_getwidth(void *vptr) { - XSHM_DATA(vptr); - - return texture_getwidth(data->texture); + XSHM_DATA(vptr); + + return texture_getwidth(data->texture); } -static uint32_t xshm_input_getheight(void *vptr) +static uint32_t xshm_getheight(void *vptr) { - XSHM_DATA(vptr); - - return texture_getheight(data->texture); + XSHM_DATA(vptr); + + return texture_getheight(data->texture); } struct obs_source_info xshm_input = { .id = "xshm_input", .type = OBS_SOURCE_TYPE_INPUT, .output_flags = OBS_SOURCE_VIDEO, - .getname = xshm_input_getname, - .create = xshm_input_create, - .destroy = xshm_input_destroy, - .video_tick = xshm_input_video_tick, - .video_render = xshm_input_video_render, - .getwidth = xshm_input_getwidth, - .getheight = xshm_input_getheight + .getname = xshm_getname, + .create = xshm_create, + .destroy = xshm_destroy, + .video_tick = xshm_video_tick, + .video_render = xshm_video_render, + .getwidth = xshm_getwidth, + .getheight = xshm_getheight };