[PATCH weston 03/11] Prepare smoke for multitouch support

Kristian Høgsberg hoegsberg at gmail.com
Thu Nov 8 09:08:20 PST 2012


On Wed, Nov 07, 2012 at 05:51:37PM +1100, Daniel Stone wrote:
> Split motion tracking out into separate handlers so we can have one per
> touch.

Not sure about this one... doesn't this recompute the entire thing
once per touch point?  Shouldn't we just inject some randomness per
touch point (like what smoke_motion_handler() does) and then still
only recompute once per frame... or are you trying to do something
else?

Kristian

> Signed-off-by: Daniel Stone <daniel at fooishbar.org>
> ---
>  clients/smoke.c |  155 +++++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 110 insertions(+), 45 deletions(-)
> 
> diff --git a/clients/smoke.c b/clients/smoke.c
> index 80b8c58..42540d0 100644
> --- a/clients/smoke.c
> +++ b/clients/smoke.c
> @@ -37,9 +37,18 @@ struct smoke {
>  	struct window *window;
>  	struct widget *widget;
>  	int width, height;
> -	int current;
>  	uint32_t time;
> +	struct wl_list motion_list;
> +};
> +
> +struct motion {
> +	struct smoke *smoke;
> +	int is_pointer;
> +	uint32_t touch_id;
> +	int current;
> +	int active;
>  	struct { float *d, *u, *v; } b[2];
> +	struct wl_list link;
>  };
>  
>  static void diffuse(struct smoke *smoke, uint32_t time,
> @@ -142,12 +151,14 @@ static void project(struct smoke *smoke, uint32_t time,
>  	}
>  }
>  
> -static void render(struct smoke *smoke, cairo_surface_t *surface)
> +static int render(struct smoke *smoke, struct motion *motion,
> +		  cairo_surface_t *surface)
>  {
>  	unsigned char *dest;
>  	int x, y, width, height, stride;
>  	float *s;
>  	uint32_t *d, c, a;
> +	int ret = 0;
>  
>  	dest = cairo_image_surface_get_data(surface);
>  	width = cairo_image_surface_get_width(surface);
> @@ -155,7 +166,7 @@ static void render(struct smoke *smoke, cairo_surface_t *surface)
>  	stride = cairo_image_surface_get_stride(surface);
>  
>  	for (y = 1; y < height - 1; y++) {
> -		s = smoke->b[smoke->current].d + y * smoke->height;
> +		s = motion->b[motion->current].d + y * smoke->height;
>  		d = (uint32_t *) (dest + y * stride);
>  		for (x = 1; x < width - 1; x++) {
>  			c = (int) (s[x] * 800);
> @@ -165,8 +176,12 @@ static void render(struct smoke *smoke, cairo_surface_t *surface)
>  			if (a < 0x33)
>  				a = 0x33;
>  			d[x] = (a << 24) | (c << 16) | (c << 8) | c;
> +			if (c != 0)
> +				ret = 1;
>  		}
>  	}
> +
> +	return ret;
>  }
>  
>  static void
> @@ -185,60 +200,78 @@ static const struct wl_callback_listener listener = {
>  	frame_callback,
>  };
>  
> -static void
> -redraw_handler(struct widget *widget, void *data)
> +static int
> +do_redraw(struct motion *motion, cairo_surface_t *surface)
>  {
> -	struct smoke *smoke = data;
> +	struct smoke *smoke = motion->smoke;
>  	uint32_t time = smoke->time;
> -	struct wl_callback *callback;
> -	cairo_surface_t *surface;
>  
> -	diffuse(smoke, time / 30, smoke->b[0].u, smoke->b[1].u);
> -	diffuse(smoke, time / 30, smoke->b[0].v, smoke->b[1].v);
> +	diffuse(smoke, time / 30, motion->b[0].u, motion->b[1].u);
> +	diffuse(smoke, time / 30, motion->b[0].v, motion->b[1].v);
>  	project(smoke, time / 30,
> -		smoke->b[1].u, smoke->b[1].v,
> -		smoke->b[0].u, smoke->b[0].v);
> +		motion->b[1].u, motion->b[1].v,
> +		motion->b[0].u, motion->b[0].v);
>  	advect(smoke, time / 30,
> -	       smoke->b[1].u, smoke->b[1].v,
> -	       smoke->b[1].u, smoke->b[0].u);
> +	       motion->b[1].u, motion->b[1].v,
> +	       motion->b[1].u, motion->b[0].u);
>  	advect(smoke, time / 30,
> -	       smoke->b[1].u, smoke->b[1].v,
> -	       smoke->b[1].v, smoke->b[0].v);
> +	       motion->b[1].u, motion->b[1].v,
> +	       motion->b[1].v, motion->b[0].v);
>  	project(smoke, time / 30,
> -		smoke->b[0].u, smoke->b[0].v,
> -		smoke->b[1].u, smoke->b[1].v);
> +		motion->b[0].u, motion->b[0].v,
> +		motion->b[1].u, motion->b[1].v);
>  
> -	diffuse(smoke, time / 30, smoke->b[0].d, smoke->b[1].d);
> +	diffuse(smoke, time / 30, motion->b[0].d, motion->b[1].d);
>  	advect(smoke, time / 30,
> -	       smoke->b[0].u, smoke->b[0].v,
> -	       smoke->b[1].d, smoke->b[0].d);
> +	       motion->b[0].u, motion->b[0].v,
> +	       motion->b[1].d, motion->b[0].d);
>  
> -	surface = window_get_surface(smoke->window);
> +	return render(smoke, motion, surface);
> +}
>  
> -	render(smoke, surface);
> +static void
> +redraw_handler(struct widget *widget, void *data)
> +{
> +	struct wl_callback *callback;
> +	struct smoke *smoke = data;
> +	struct motion *motion, *tmp;
> +	cairo_surface_t *surface = window_get_surface(smoke->window);
> +	int did_redraw = 0;
> +
> +	wl_list_for_each_safe(motion, tmp, &smoke->motion_list, link) {
> +		if (do_redraw(motion, surface)) {
> +			did_redraw = 1;
> +			continue;
> +		}
>  
> -	window_damage(smoke->window, 0, 0, smoke->width, smoke->height);
> +		if (motion->active == 0) {
> +			wl_list_remove(&motion->link);
> +			free(motion);
> +		}
> +	}
>  
>  	cairo_surface_destroy(surface);
>  
> +	if (!did_redraw)
> +		return;
> +
> +	window_damage(smoke->window, 0, 0, smoke->width, smoke->height);
>  	callback = wl_surface_frame(window_get_wl_surface(smoke->window));
>  	wl_callback_add_listener(callback, &listener, smoke);
>  	wl_surface_commit(window_get_wl_surface(smoke->window));
>  }
>  
> -static int
> -smoke_motion_handler(struct widget *widget, struct input *input,
> -		     uint32_t time, float x, float y, void *data)
> +static void
> +handle_motion(struct motion *motion, float x, float y)
>  {
> -	struct smoke *smoke = data;
>  	int i, i0, i1, j, j0, j1, k, d = 5;
>  
>  	if (x - d < 1)
>  		i0 = 1;
>  	else
>  		i0 = x - d;
> -	if (i0 + 2 * d > smoke->width - 1)
> -		i1 = smoke->width - 1;
> +	if (i0 + 2 * d > motion->smoke->width - 1)
> +		i1 = motion->smoke->width - 1;
>  	else
>  		i1 = i0 + 2 * d;
>  
> @@ -246,18 +279,35 @@ smoke_motion_handler(struct widget *widget, struct input *input,
>  		j0 = 1;
>  	else
>  		j0 = y - d;
> -	if (j0 + 2 * d > smoke->height - 1)
> -		j1 = smoke->height - 1;
> +	if (j0 + 2 * d > motion->smoke->height - 1)
> +		j1 = motion->smoke->height - 1;
>  	else
>  		j1 = j0 + 2 * d;
>  
>  	for (i = i0; i < i1; i++)
>  		for (j = j0; j < j1; j++) {
> -			k = j * smoke->width + i;
> -			smoke->b[0].u[k] += 256 - (random() & 512);
> -			smoke->b[0].v[k] += 256 - (random() & 512);
> -			smoke->b[0].d[k] += 1;
> +			k = j * motion->smoke->width + i;
> +			motion->b[0].u[k] += 256 - (random() & 512);
> +			motion->b[0].v[k] += 256 - (random() & 512);
> +			motion->b[0].d[k] += 1;
> +		}
> +
> +	window_schedule_redraw(motion->smoke->window);
> +}
> +
> +static int
> +smoke_motion_handler(struct widget *widget, struct input *input,
> +		     uint32_t time, float x, float y, void *data)
> +{
> +	struct smoke *smoke = data;
> +	struct motion *motion;
> +
> +	wl_list_for_each(motion, &smoke->motion_list, link) {
> +		if (motion->is_pointer) {
> +			handle_motion(motion, x, y);
> +			break;
>  		}
> +	}
>  
>  	return CURSOR_HAND1;
>  }
> @@ -272,12 +322,29 @@ resize_handler(struct widget *widget,
>  	widget_set_size(smoke->widget, smoke->width, smoke->height);
>  }
>  
> +static void
> +init_motion(struct smoke *smoke, struct motion *motion)
> +{
> +	int size;
> +
> +	motion->current = 0;
> +	size = smoke->height * smoke->width;
> +	motion->b[0].d = calloc(size, sizeof(float));
> +	motion->b[0].u = calloc(size, sizeof(float));
> +	motion->b[0].v = calloc(size, sizeof(float));
> +	motion->b[1].d = calloc(size, sizeof(float));
> +	motion->b[1].u = calloc(size, sizeof(float));
> +	motion->b[1].v = calloc(size, sizeof(float));
> +	motion->smoke = smoke;
> +	wl_list_insert(&smoke->motion_list, &motion->link);
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  	struct timespec ts;
>  	struct smoke smoke;
> +	struct motion pointer_motion;
>  	struct display *d;
> -	int size;
>  
>  	d = display_create(argc, argv);
>  	if (d == NULL) {
> @@ -290,20 +357,18 @@ int main(int argc, char *argv[])
>  	smoke.display = d;
>  	smoke.window = window_create(d);
>  	smoke.widget = window_add_widget(smoke.window, &smoke);
> +	wl_list_init(&smoke.motion_list);
>  	window_set_title(smoke.window, "smoke");
>  
>  	window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM);
>  	clock_gettime(CLOCK_MONOTONIC, &ts);
>  	srandom(ts.tv_nsec);
>  
> -	smoke.current = 0;
> -	size = smoke.height * smoke.width;
> -	smoke.b[0].d = calloc(size, sizeof(float));
> -	smoke.b[0].u = calloc(size, sizeof(float));
> -	smoke.b[0].v = calloc(size, sizeof(float));
> -	smoke.b[1].d = calloc(size, sizeof(float));
> -	smoke.b[1].u = calloc(size, sizeof(float));
> -	smoke.b[1].v = calloc(size, sizeof(float));
> +	wl_list_init(&pointer_motion.link);
> +	pointer_motion.is_pointer = 1;
> +	pointer_motion.touch_id = 0;
> +	pointer_motion.active = 1;
> +	init_motion(&smoke, &pointer_motion);
>  
>  	widget_set_motion_handler(smoke.widget, smoke_motion_handler);
>  	widget_set_resize_handler(smoke.widget, resize_handler);
> -- 
> 1.7.10.4
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list