Przeglądaj źródła

changed to kernel formatting and added some more documentation

fryshorts 12 lat temu
rodzic
commit
ce9db65695
4 zmienionych plików z 238 dodań i 256 usunięć
  1. 4 4
      test/linux/linux.c
  2. 78 85
      test/linux/xcursor.c
  3. 9 8
      test/linux/xcursor.h
  4. 147 159
      test/linux/xshm-input.c

+ 4 - 4
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;
 }

+ 78 - 85
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 <http://www.gnu.org/licenses/>.
 */
-#include <stdlib.h>
-#include <stdio.h>
+
+#include <stdint.h>
 #include <X11/extensions/Xfixes.h>
+
+#include <util/bmem.h>
 #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();
 }

+ 9 - 8
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 <http://www.gnu.org/licenses/>.
 */
+
 #pragma once
 
 #include <obs.h>
@@ -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
+#endif

+ 147 - 159
test/linux/xshm-input.c

@@ -28,191 +28,179 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #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
 };