compositor-drm: Work around page flip not setting tiling mode on BYT
[platform/upstream/weston.git] / src / animation.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <math.h>
29
30 #include <unistd.h>
31 #include <fcntl.h>
32
33 #include "compositor.h"
34
35 WL_EXPORT void
36 weston_spring_init(struct weston_spring *spring,
37                    double k, double current, double target)
38 {
39         spring->k = k;
40         spring->friction = 400.0;
41         spring->current = current;
42         spring->previous = current;
43         spring->target = target;
44         spring->clip = WESTON_SPRING_OVERSHOOT;
45         spring->min = 0.0;
46         spring->max = 1.0;
47 }
48
49 WL_EXPORT void
50 weston_spring_update(struct weston_spring *spring, uint32_t msec)
51 {
52         double force, v, current, step;
53
54         /* Limit the number of executions of the loop below by ensuring that
55          * the timestamp for last update of the spring is no more than 1s ago.
56          * This handles the case where time moves backwards or forwards in
57          * large jumps.
58          */
59         if (msec - spring->timestamp > 1000) {
60                 weston_log("unexpectedly large timestamp jump (from %u to %u)\n",
61                            spring->timestamp, msec);
62                 spring->timestamp = msec - 1000;
63         }
64
65         step = 0.01;
66         while (4 < msec - spring->timestamp) {
67                 current = spring->current;
68                 v = current - spring->previous;
69                 force = spring->k * (spring->target - current) / 10.0 +
70                         (spring->previous - current) - v * spring->friction;
71
72                 spring->current =
73                         current + (current - spring->previous) +
74                         force * step * step;
75                 spring->previous = current;
76
77                 switch (spring->clip) {
78                 case WESTON_SPRING_OVERSHOOT:
79                         break;
80
81                 case WESTON_SPRING_CLAMP:
82                         if (spring->current > spring->max) {
83                                 spring->current = spring->max;
84                                 spring->previous = spring->max;
85                         } else if (spring->current < 0.0) {
86                                 spring->current = spring->min;
87                                 spring->previous = spring->min;
88                         }
89                         break;
90
91                 case WESTON_SPRING_BOUNCE:
92                         if (spring->current > spring->max) {
93                                 spring->current =
94                                         2 * spring->max - spring->current;
95                                 spring->previous =
96                                         2 * spring->max - spring->previous;
97                         } else if (spring->current < spring->min) {
98                                 spring->current =
99                                         2 * spring->min - spring->current;
100                                 spring->previous =
101                                         2 * spring->min - spring->previous;
102                         }
103                         break;
104                 }
105
106                 spring->timestamp += 4;
107         }
108 }
109
110 WL_EXPORT int
111 weston_spring_done(struct weston_spring *spring)
112 {
113         return fabs(spring->previous - spring->target) < 0.002 &&
114                 fabs(spring->current - spring->target) < 0.002;
115 }
116
117 typedef void (*weston_view_animation_frame_func_t)(struct weston_view_animation *animation);
118
119 struct weston_view_animation {
120         struct weston_view *view;
121         struct weston_animation animation;
122         struct weston_spring spring;
123         struct weston_transform transform;
124         struct wl_listener listener;
125         float start, stop;
126         weston_view_animation_frame_func_t frame;
127         weston_view_animation_frame_func_t reset;
128         weston_view_animation_done_func_t done;
129         void *data;
130         void *private;
131 };
132
133 WL_EXPORT void
134 weston_view_animation_destroy(struct weston_view_animation *animation)
135 {
136         wl_list_remove(&animation->animation.link);
137         wl_list_remove(&animation->listener.link);
138         wl_list_remove(&animation->transform.link);
139         if (animation->reset)
140                 animation->reset(animation);
141         weston_view_geometry_dirty(animation->view);
142         if (animation->done)
143                 animation->done(animation, animation->data);
144         free(animation);
145 }
146
147 static void
148 handle_animation_view_destroy(struct wl_listener *listener, void *data)
149 {
150         struct weston_view_animation *animation =
151                 container_of(listener,
152                              struct weston_view_animation, listener);
153
154         weston_view_animation_destroy(animation);
155 }
156
157 static void
158 weston_view_animation_frame(struct weston_animation *base,
159                             struct weston_output *output, uint32_t msecs)
160 {
161         struct weston_view_animation *animation =
162                 container_of(base,
163                              struct weston_view_animation, animation);
164         struct weston_compositor *compositor =
165                 animation->view->surface->compositor;
166
167         if (base->frame_counter <= 1)
168                 animation->spring.timestamp = msecs;
169
170         weston_spring_update(&animation->spring, msecs);
171
172         if (weston_spring_done(&animation->spring)) {
173                 weston_view_schedule_repaint(animation->view);
174                 weston_view_animation_destroy(animation);
175                 return;
176         }
177
178         if (animation->frame)
179                 animation->frame(animation);
180
181         weston_view_geometry_dirty(animation->view);
182         weston_view_schedule_repaint(animation->view);
183
184         /* The view's output_mask will be zero if its position is
185          * offscreen. Animations should always run but as they are also
186          * run off the repaint cycle, if there's nothing to repaint
187          * the animation stops running. Therefore if we catch this situation
188          * and schedule a repaint on all outputs it will be avoided.
189          */
190         if (animation->view->output_mask == 0)
191                 weston_compositor_schedule_repaint(compositor);
192 }
193
194 static struct weston_view_animation *
195 weston_view_animation_create(struct weston_view *view,
196                              float start, float stop,
197                              weston_view_animation_frame_func_t frame,
198                              weston_view_animation_frame_func_t reset,
199                              weston_view_animation_done_func_t done,
200                              void *data,
201                              void *private)
202 {
203         struct weston_view_animation *animation;
204
205         animation = malloc(sizeof *animation);
206         if (!animation)
207                 return NULL;
208
209         animation->view = view;
210         animation->frame = frame;
211         animation->reset = reset;
212         animation->done = done;
213         animation->data = data;
214         animation->start = start;
215         animation->stop = stop;
216         animation->private = private;
217
218         weston_matrix_init(&animation->transform.matrix);
219         wl_list_insert(&view->geometry.transformation_list,
220                        &animation->transform.link);
221
222         animation->animation.frame = weston_view_animation_frame;
223
224         animation->listener.notify = handle_animation_view_destroy;
225         wl_signal_add(&view->destroy_signal, &animation->listener);
226
227         wl_list_insert(&view->output->animation_list,
228                        &animation->animation.link);
229
230         return animation;
231 }
232
233 static void
234 weston_view_animation_run(struct weston_view_animation *animation)
235 {
236         animation->animation.frame_counter = 0;
237         weston_view_animation_frame(&animation->animation, NULL, 0);
238 }
239
240 static void
241 reset_alpha(struct weston_view_animation *animation)
242 {
243         struct weston_view *view = animation->view;
244
245         view->alpha = animation->stop;
246 }
247
248 static void
249 zoom_frame(struct weston_view_animation *animation)
250 {
251         struct weston_view *es = animation->view;
252         float scale;
253
254         scale = animation->start +
255                 (animation->stop - animation->start) *
256                 animation->spring.current;
257         weston_matrix_init(&animation->transform.matrix);
258         weston_matrix_translate(&animation->transform.matrix,
259                                 -0.5f * es->surface->width,
260                                 -0.5f * es->surface->height, 0);
261         weston_matrix_scale(&animation->transform.matrix, scale, scale, scale);
262         weston_matrix_translate(&animation->transform.matrix,
263                                 0.5f * es->surface->width,
264                                 0.5f * es->surface->height, 0);
265
266         es->alpha = animation->spring.current;
267         if (es->alpha > 1.0)
268                 es->alpha = 1.0;
269 }
270
271 WL_EXPORT struct weston_view_animation *
272 weston_zoom_run(struct weston_view *view, float start, float stop,
273                 weston_view_animation_done_func_t done, void *data)
274 {
275         struct weston_view_animation *zoom;
276
277         zoom = weston_view_animation_create(view, start, stop,
278                                             zoom_frame, reset_alpha,
279                                             done, data, NULL);
280
281         if (zoom == NULL)
282                 return NULL;
283
284         weston_spring_init(&zoom->spring, 300.0, start, stop);
285         zoom->spring.friction = 1400;
286         zoom->spring.previous = start - (stop - start) * 0.03;
287
288         weston_view_animation_run(zoom);
289
290         return zoom;
291 }
292
293 static void
294 fade_frame(struct weston_view_animation *animation)
295 {
296         if (animation->spring.current > 0.999)
297                 animation->view->alpha = 1;
298         else if (animation->spring.current < 0.001 )
299                 animation->view->alpha = 0;
300         else
301                 animation->view->alpha = animation->spring.current;
302 }
303
304 WL_EXPORT struct weston_view_animation *
305 weston_fade_run(struct weston_view *view,
306                 float start, float end, float k,
307                 weston_view_animation_done_func_t done, void *data)
308 {
309         struct weston_view_animation *fade;
310
311         fade = weston_view_animation_create(view, start, end,
312                                             fade_frame, reset_alpha,
313                                             done, data, NULL);
314
315         if (fade == NULL)
316                 return NULL;
317
318         weston_spring_init(&fade->spring, 1000.0, start, end);
319         fade->spring.friction = 4000;
320         fade->spring.previous = start - (end - start) * 0.1;
321
322         view->alpha = start;
323
324         weston_view_animation_run(fade);
325
326         return fade;
327 }
328
329 WL_EXPORT void
330 weston_fade_update(struct weston_view_animation *fade, float target)
331 {
332         fade->spring.target = target;
333         fade->stop = target;
334 }
335
336 static void
337 stable_fade_frame(struct weston_view_animation *animation)
338 {
339         struct weston_view *back_view;
340
341         if (animation->spring.current > 0.999)
342                 animation->view->alpha = 1;
343         else if (animation->spring.current < 0.001 )
344                 animation->view->alpha = 0;
345         else
346                 animation->view->alpha = animation->spring.current;
347
348         back_view = (struct weston_view *) animation->private;
349         back_view->alpha =
350                 (animation->spring.target - animation->view->alpha) /
351                 (1.0 - animation->view->alpha);
352         weston_view_geometry_dirty(back_view);
353 }
354
355 WL_EXPORT struct weston_view_animation *
356 weston_stable_fade_run(struct weston_view *front_view, float start,
357                 struct weston_view *back_view, float end,
358                 weston_view_animation_done_func_t done, void *data)
359 {
360         struct weston_view_animation *fade;
361
362         fade = weston_view_animation_create(front_view, 0, 0,
363                                             stable_fade_frame, NULL,
364                                             done, data, back_view);
365
366         if (fade == NULL)
367                 return NULL;
368
369         weston_spring_init(&fade->spring, 400, start, end);
370         fade->spring.friction = 1150;
371
372         front_view->alpha = start;
373         back_view->alpha = end;
374
375         weston_view_animation_run(fade);
376
377         return fade;
378 }
379
380 static void
381 slide_frame(struct weston_view_animation *animation)
382 {
383         float scale;
384
385         scale = animation->start +
386                 (animation->stop - animation->start) *
387                 animation->spring.current;
388         weston_matrix_init(&animation->transform.matrix);
389         weston_matrix_translate(&animation->transform.matrix, 0, scale, 0);
390 }
391
392 WL_EXPORT struct weston_view_animation *
393 weston_slide_run(struct weston_view *view, float start, float stop,
394                  weston_view_animation_done_func_t done, void *data)
395 {
396         struct weston_view_animation *animation;
397
398         animation = weston_view_animation_create(view, start, stop,
399                                               slide_frame, NULL, done,
400                                               data, NULL);
401         if (!animation)
402                 return NULL;
403
404         weston_spring_init(&animation->spring, 400.0, 0.0, 1.0);
405         animation->spring.friction = 600;
406         animation->spring.clip = WESTON_SPRING_BOUNCE;
407
408         weston_view_animation_run(animation);
409
410         return animation;
411 }
412
413 struct weston_move_animation {
414         int dx;
415         int dy;
416         int reverse;
417         weston_view_animation_done_func_t done;
418 };
419
420 static void
421 move_frame(struct weston_view_animation *animation)
422 {
423         struct weston_move_animation *move = animation->private;
424         float scale;
425         float progress = animation->spring.current;
426
427         if (move->reverse)
428                 progress = 1.0 - progress;
429
430         scale = animation->start +
431                 (animation->stop - animation->start) *
432                 progress;
433         weston_matrix_init(&animation->transform.matrix);
434         weston_matrix_scale(&animation->transform.matrix, scale, scale, 1.0f);
435         weston_matrix_translate(&animation->transform.matrix,
436                                 move->dx * progress, move->dy * progress,
437                                 0);
438 }
439
440 static void
441 move_done(struct weston_view_animation *animation, void *data)
442 {
443         struct weston_move_animation *move = animation->private;
444
445         if (move->done)
446                 move->done(animation, data);
447
448         free(move);
449 }
450
451 WL_EXPORT struct weston_view_animation *
452 weston_move_scale_run(struct weston_view *view, int dx, int dy,
453                       float start, float end, int reverse,
454                       weston_view_animation_done_func_t done, void *data)
455 {
456         struct weston_move_animation *move;
457         struct weston_view_animation *animation;
458
459         move = malloc(sizeof(*move));
460         if (!move)
461                 return NULL;
462         move->dx = dx;
463         move->dy = dy;
464         move->reverse = reverse;
465         move->done = done;
466
467         animation = weston_view_animation_create(view, start, end, move_frame,
468                                                  NULL, move_done, data, move);
469
470         if (animation == NULL)
471                 return NULL;
472
473         weston_spring_init(&animation->spring, 400.0, 0.0, 1.0);
474         animation->spring.friction = 1150;
475
476         weston_view_animation_run(animation);
477
478         return animation;
479 }