compositor-drm: Work around page flip not setting tiling mode on BYT
[platform/upstream/weston.git] / src / zoom.c
1 /*
2  * Copyright © 2012 Scott Moreau
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
27 #include "compositor.h"
28 #include "text-cursor-position-server-protocol.h"
29
30 static void
31 weston_zoom_frame_z(struct weston_animation *animation,
32                 struct weston_output *output, uint32_t msecs)
33 {
34         if (animation->frame_counter <= 1)
35                 output->zoom.spring_z.timestamp = msecs;
36
37         weston_spring_update(&output->zoom.spring_z, msecs);
38
39         if (output->zoom.spring_z.current > output->zoom.max_level)
40                 output->zoom.spring_z.current = output->zoom.max_level;
41         else if (output->zoom.spring_z.current < 0.0)
42                 output->zoom.spring_z.current = 0.0;
43
44         if (weston_spring_done(&output->zoom.spring_z)) {
45                 if (output->zoom.active && output->zoom.level <= 0.0) {
46                         output->zoom.active = 0;
47                         output->disable_planes--;
48                         wl_list_remove(&output->zoom.motion_listener.link);
49                 }
50                 output->zoom.spring_z.current = output->zoom.level;
51                 wl_list_remove(&animation->link);
52                 wl_list_init(&animation->link);
53         }
54
55         output->dirty = 1;
56         weston_output_damage(output);
57 }
58
59 static struct weston_seat *
60 weston_zoom_pick_seat(struct weston_compositor *compositor)
61 {
62         return container_of(compositor->seat_list.next,
63                             struct weston_seat, link);
64 }
65
66
67 static void
68 weston_zoom_frame_xy(struct weston_animation *animation,
69                 struct weston_output *output, uint32_t msecs)
70 {
71         struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
72         wl_fixed_t x, y;
73
74         if (animation->frame_counter <= 1)
75                 output->zoom.spring_xy.timestamp = msecs;
76
77         weston_spring_update(&output->zoom.spring_xy, msecs);
78
79         x = output->zoom.from.x - ((output->zoom.from.x - output->zoom.to.x) *
80                                                 output->zoom.spring_xy.current);
81         y = output->zoom.from.y - ((output->zoom.from.y - output->zoom.to.y) *
82                                                 output->zoom.spring_xy.current);
83
84         output->zoom.current.x = x;
85         output->zoom.current.y = y;
86
87         if (weston_spring_done(&output->zoom.spring_xy)) {
88                 output->zoom.spring_xy.current = output->zoom.spring_xy.target;
89                 output->zoom.current.x = seat->pointer->x;
90                 output->zoom.current.y = seat->pointer->y;
91                 wl_list_remove(&animation->link);
92                 wl_list_init(&animation->link);
93         }
94
95         output->dirty = 1;
96         weston_output_damage(output);
97 }
98
99 static void
100 zoom_area_center_from_pointer(struct weston_output *output,
101                                 wl_fixed_t *x, wl_fixed_t *y)
102 {
103         float level = output->zoom.spring_z.current;
104         wl_fixed_t offset_x = wl_fixed_from_int(output->x);
105         wl_fixed_t offset_y = wl_fixed_from_int(output->y);
106         wl_fixed_t w = wl_fixed_from_int(output->width);
107         wl_fixed_t h = wl_fixed_from_int(output->height);
108
109         *x -= ((((*x - offset_x) / (float) w) - 0.5) * (w * (1.0 - level)));
110         *y -= ((((*y - offset_y) / (float) h) - 0.5) * (h * (1.0 - level)));
111 }
112
113 static void
114 weston_output_update_zoom_transform(struct weston_output *output)
115 {
116         float global_x, global_y;
117         wl_fixed_t x = output->zoom.current.x;
118         wl_fixed_t y = output->zoom.current.y;
119         float trans_min, trans_max;
120         float ratio, level;
121
122         level = output->zoom.spring_z.current;
123         ratio = 1 / level;
124
125         if (!output->zoom.active || level > output->zoom.max_level ||
126             level == 0.0f)
127                 return;
128
129         if (wl_list_empty(&output->zoom.animation_xy.link))
130                 zoom_area_center_from_pointer(output, &x, &y);
131
132         global_x = wl_fixed_to_double(x);
133         global_y = wl_fixed_to_double(y);
134
135         output->zoom.trans_x =
136                 ((((global_x - output->x) / output->width) *
137                 (level * 2)) - level) * ratio;
138         output->zoom.trans_y =
139                 ((((global_y - output->y) / output->height) *
140                 (level * 2)) - level) * ratio;
141
142         trans_max = level * 2 - level;
143         trans_min = -trans_max;
144
145         /* Clip zoom area to output */
146         if (output->zoom.trans_x > trans_max)
147                 output->zoom.trans_x = trans_max;
148         else if (output->zoom.trans_x < trans_min)
149                 output->zoom.trans_x = trans_min;
150         if (output->zoom.trans_y > trans_max)
151                 output->zoom.trans_y = trans_max;
152         else if (output->zoom.trans_y < trans_min)
153                 output->zoom.trans_y = trans_min;
154 }
155
156 static void
157 weston_zoom_transition(struct weston_output *output, wl_fixed_t x, wl_fixed_t y)
158 {
159         if (output->zoom.level != output->zoom.spring_z.current) {
160                 output->zoom.spring_z.target = output->zoom.level;
161                 if (wl_list_empty(&output->zoom.animation_z.link)) {
162                         output->zoom.animation_z.frame_counter = 0;
163                         wl_list_insert(output->animation_list.prev,
164                                 &output->zoom.animation_z.link);
165                 }
166         }
167
168         output->dirty = 1;
169         weston_output_damage(output);
170 }
171
172 WL_EXPORT void
173 weston_output_update_zoom(struct weston_output *output)
174 {
175         struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
176         wl_fixed_t x = seat->pointer->x;
177         wl_fixed_t y = seat->pointer->y;
178
179         zoom_area_center_from_pointer(output, &x, &y);
180
181         if (wl_list_empty(&output->zoom.animation_xy.link)) {
182                 output->zoom.current.x = seat->pointer->x;
183                 output->zoom.current.y = seat->pointer->y;
184         } else {
185                 output->zoom.to.x = x;
186                 output->zoom.to.y = y;
187         }
188
189         weston_zoom_transition(output, x, y);
190         weston_output_update_zoom_transform(output);
191 }
192
193 static void
194 motion(struct wl_listener *listener, void *data)
195 {
196         struct weston_output_zoom *zoom =
197                 container_of(listener, struct weston_output_zoom, motion_listener);
198         struct weston_output *output =
199                 container_of(zoom, struct weston_output, zoom);
200
201         weston_output_update_zoom(output);
202 }
203
204 WL_EXPORT void
205 weston_output_activate_zoom(struct weston_output *output)
206 {
207         struct weston_seat *seat = weston_zoom_pick_seat(output->compositor);
208
209         if (output->zoom.active)
210                 return;
211
212         output->zoom.active = 1;
213         output->disable_planes++;
214         wl_signal_add(&seat->pointer->motion_signal,
215                       &output->zoom.motion_listener);
216 }
217
218 WL_EXPORT void
219 weston_output_init_zoom(struct weston_output *output)
220 {
221         output->zoom.active = 0;
222         output->zoom.increment = 0.07;
223         output->zoom.max_level = 0.95;
224         output->zoom.level = 0.0;
225         output->zoom.trans_x = 0.0;
226         output->zoom.trans_y = 0.0;
227         weston_spring_init(&output->zoom.spring_z, 250.0, 0.0, 0.0);
228         output->zoom.spring_z.friction = 1000;
229         output->zoom.animation_z.frame = weston_zoom_frame_z;
230         wl_list_init(&output->zoom.animation_z.link);
231         weston_spring_init(&output->zoom.spring_xy, 250.0, 0.0, 0.0);
232         output->zoom.spring_xy.friction = 1000;
233         output->zoom.animation_xy.frame = weston_zoom_frame_xy;
234         wl_list_init(&output->zoom.animation_xy.link);
235         output->zoom.motion_listener.notify = motion;
236 }