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 <[email protected]> > --- > 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 > [email protected] > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
