blob: f504c73a916b80efc175ad84c93a78ceccd0e37e [file] [log] [blame]
Jonny Lamb92d90f22013-11-26 18:19:48 +01001/*
2 * Copyright © 2008 Kristian Høgsberg
3 * Copyright © 2013 Collabora, Ltd.
4 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -07005 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
Jonny Lamb92d90f22013-11-26 18:19:48 +010011 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -070012 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Jonny Lamb92d90f22013-11-26 18:19:48 +010023 */
24
Andrew Wedgbury9cd661e2014-04-07 12:40:35 +010025#include "config.h"
26
Jonny Lamb92d90f22013-11-26 18:19:48 +010027#include <stdio.h>
28#include <string.h>
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020029#include <assert.h>
Jonny Lamb92d90f22013-11-26 18:19:48 +010030#include <cairo.h>
31
32#include <linux/input.h>
33
34#include "window.h"
Pekka Paalanen73511002016-04-15 16:53:41 +030035#include "viewporter-client-protocol.h"
Jonny Lamb92d90f22013-11-26 18:19:48 +010036
37#define BUFFER_SCALE 2
38static const int BUFFER_WIDTH = 421 * BUFFER_SCALE;
39static const int BUFFER_HEIGHT = 337 * BUFFER_SCALE;
40static const int SURFACE_WIDTH = 55 * 4;
41static const int SURFACE_HEIGHT = 77 * 4;
42static const double RECT_X = 21 * BUFFER_SCALE; /* buffer coords */
43static const double RECT_Y = 25 * BUFFER_SCALE;
44static const double RECT_W = 55 * BUFFER_SCALE;
45static const double RECT_H = 77 * BUFFER_SCALE;
46
47struct box {
48 struct display *display;
49 struct window *window;
50 struct widget *widget;
51 int width, height;
52
Pekka Paalanen73511002016-04-15 16:53:41 +030053 struct wp_viewporter *viewporter;
54 struct wp_viewport *viewport;
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020055
56 enum {
57 MODE_NO_VIEWPORT,
58 MODE_SRC_ONLY,
59 MODE_DST_ONLY,
60 MODE_SRC_DST
61 } mode;
Jonny Lamb92d90f22013-11-26 18:19:48 +010062};
63
64static void
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020065set_my_viewport(struct box *box)
66{
67 wl_fixed_t src_x, src_y, src_width, src_height;
68 int32_t dst_width = SURFACE_WIDTH;
69 int32_t dst_height = SURFACE_HEIGHT;
70
71 if (box->mode == MODE_NO_VIEWPORT)
72 return;
73
74 /* Cut the green border in half, take white border fully in,
75 * and black border fully out. The borders are 1px wide in buffer.
76 *
77 * The gl-renderer uses linear texture sampling, this means the
78 * top and left edges go to 100% green, bottom goes to 50% blue/black,
79 * right edge has thick white sliding to 50% red.
80 */
81 src_x = wl_fixed_from_double((RECT_X + 0.5) / BUFFER_SCALE);
82 src_y = wl_fixed_from_double((RECT_Y + 0.5) / BUFFER_SCALE);
83 src_width = wl_fixed_from_double((RECT_W - 0.5) / BUFFER_SCALE);
84 src_height = wl_fixed_from_double((RECT_H - 0.5) / BUFFER_SCALE);
85
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020086 switch (box->mode){
87 case MODE_SRC_ONLY:
Pekka Paalanen73511002016-04-15 16:53:41 +030088 wp_viewport_set_source(box->viewport, src_x, src_y,
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020089 src_width, src_height);
90 break;
91 case MODE_DST_ONLY:
Pekka Paalanen73511002016-04-15 16:53:41 +030092 wp_viewport_set_destination(box->viewport,
Pekka Paalanen2d9d6892014-03-14 14:38:18 +020093 dst_width, dst_height);
94 break;
95 case MODE_SRC_DST:
Pekka Paalanen73511002016-04-15 16:53:41 +030096 wp_viewport_set_source(box->viewport, src_x, src_y,
97 src_width, src_height);
98 wp_viewport_set_destination(box->viewport,
99 dst_width, dst_height);
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200100 break;
101 default:
102 assert(!"not reached");
103 }
104}
105
106static void
Jonny Lamb92d90f22013-11-26 18:19:48 +0100107resize_handler(struct widget *widget,
108 int32_t width, int32_t height, void *data)
109{
110 struct box *box = data;
111
Eric Engestromd962be12016-04-02 17:03:15 +0100112 /* Don't resize me */
Jonny Lamb92d90f22013-11-26 18:19:48 +0100113 widget_set_size(box->widget, box->width, box->height);
114}
115
116static void
117redraw_handler(struct widget *widget, void *data)
118{
119 struct box *box = data;
120 cairo_surface_t *surface;
121 cairo_t *cr;
122
123 surface = window_get_surface(box->window);
124 if (surface == NULL ||
125 cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
126 fprintf(stderr, "failed to create cairo egl surface\n");
127 return;
128 }
129
130 cr = cairo_create(surface);
131 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
132 cairo_set_line_width(cr, 1.0);
133 cairo_translate(cr, RECT_X, RECT_Y);
134
135 /* red background */
136 cairo_set_source_rgba(cr, 255, 0, 0, 255);
137 cairo_paint(cr);
138
139 /* blue box */
140 cairo_set_source_rgba(cr, 0, 0, 255, 255);
141 cairo_rectangle(cr, 0, 0, RECT_W, RECT_H);
142 cairo_fill(cr);
143
144 /* black border outside the box */
145 cairo_set_source_rgb(cr, 0, 0, 0);
146 cairo_move_to(cr, 0, RECT_H + 0.5);
147 cairo_line_to(cr, RECT_W, RECT_H + 0.5);
148 cairo_stroke(cr);
149
150 /* white border inside the box */
151 cairo_set_source_rgb(cr, 1, 1, 1);
152 cairo_move_to(cr, RECT_W - 0.5, 0);
153 cairo_line_to(cr, RECT_W - 0.5, RECT_H);
154 cairo_stroke(cr);
155
156 /* the green border on inside the box, to be split half by crop */
157 cairo_set_source_rgb(cr, 0, 1, 0);
158 cairo_move_to(cr, 0.5, RECT_H);
159 cairo_line_to(cr, 0.5, 0);
160 cairo_move_to(cr, 0, 0.5);
161 cairo_line_to(cr, RECT_W, 0.5);
162 cairo_stroke(cr);
163
164 cairo_destroy(cr);
165
166 /* TODO: buffer_transform */
167
168 cairo_surface_destroy(surface);
169}
170
171static void
172global_handler(struct display *display, uint32_t name,
173 const char *interface, uint32_t version, void *data)
174{
175 struct box *box = data;
Jonny Lamb92d90f22013-11-26 18:19:48 +0100176
Pekka Paalanen73511002016-04-15 16:53:41 +0300177 if (strcmp(interface, "wp_viewporter") == 0) {
178 box->viewporter = display_bind(display, name,
179 &wp_viewporter_interface, 1);
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200180
Pekka Paalanen73511002016-04-15 16:53:41 +0300181 box->viewport = wp_viewporter_get_viewport(box->viewporter,
Jonny Lamb92d90f22013-11-26 18:19:48 +0100182 widget_get_wl_surface(box->widget));
183
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200184 set_my_viewport(box);
Jonny Lamb92d90f22013-11-26 18:19:48 +0100185 }
186}
187
188static void
189button_handler(struct widget *widget,
190 struct input *input, uint32_t time,
191 uint32_t button, enum wl_pointer_button_state state, void *data)
192{
193 struct box *box = data;
194
195 if (button != BTN_LEFT)
196 return;
197
198 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
199 window_move(box->window, input,
200 display_get_serial(box->display));
201 }
202}
203
204static void
205touch_down_handler(struct widget *widget, struct input *input,
206 uint32_t serial, uint32_t time, int32_t id,
207 float x, float y, void *data)
208{
209 struct box *box = data;
210 window_move(box->window, input,
211 display_get_serial(box->display));
212}
213
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200214static void
215usage(const char *progname)
216{
217 fprintf(stderr, "Usage: %s [mode]\n"
218 "where 'mode' is one of\n"
219 " -b\tset both src and dst in viewport (default)\n"
220 " -d\tset only dst in viewport\n"
221 " -s\tset only src in viewport\n"
222 " -n\tdo not set viewport at all\n\n",
223 progname);
224
225 fprintf(stderr, "Expected output with output_scale=1:\n");
226
227 fprintf(stderr, "Mode -n:\n"
228 " window size %dx%d px\n"
229 " Red box with a blue box in the upper left part.\n"
230 " The blue box has white right edge, black bottom edge,\n"
231 " and thin green left and top edges that can really\n"
232 " be seen only when zoomed in.\n\n",
233 BUFFER_WIDTH / BUFFER_SCALE, BUFFER_HEIGHT / BUFFER_SCALE);
234
235 fprintf(stderr, "Mode -b:\n"
236 " window size %dx%d px\n"
237 " Blue box with green top and left edge,\n"
238 " thick white right edge with a hint of red,\n"
239 " and a hint of black in bottom edge.\n\n",
240 SURFACE_WIDTH, SURFACE_HEIGHT);
241
242 fprintf(stderr, "Mode -s:\n"
243 " window size %.0fx%.0f px\n"
244 " The same as mode -b, but scaled a lot smaller.\n\n",
245 RECT_W / BUFFER_SCALE, RECT_H / BUFFER_SCALE);
246
247 fprintf(stderr, "Mode -d:\n"
248 " window size %dx%d px\n"
249 " This is horizontally squashed version of the -n mode.\n\n",
250 SURFACE_WIDTH, SURFACE_HEIGHT);
251}
252
Jonny Lamb92d90f22013-11-26 18:19:48 +0100253int
254main(int argc, char *argv[])
255{
256 struct box box;
257 struct display *d;
258 struct timeval tv;
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200259 int i;
Jonny Lamb92d90f22013-11-26 18:19:48 +0100260
Pekka Paalanen2d9d6892014-03-14 14:38:18 +0200261 box.mode = MODE_SRC_DST;
262
263 for (i = 1; i < argc; i++) {
264 if (strcmp("-s", argv[i]) == 0)
265 box.mode = MODE_SRC_ONLY;
266 else if (strcmp("-d", argv[i]) == 0)
267 box.mode = MODE_DST_ONLY;
268 else if (strcmp("-b", argv[i]) == 0)
269 box.mode = MODE_SRC_DST;
270 else if (strcmp("-n", argv[i]) == 0)
271 box.mode = MODE_NO_VIEWPORT;
272 else {
273 usage(argv[0]);
274 exit(1);
275 }
276 }
277
Bill Spitzak0fc37862014-08-08 13:00:00 -0700278 d = display_create(&argc, argv);
279 if (d == NULL) {
280 fprintf(stderr, "failed to create display: %m\n");
281 return -1;
282 }
283
Jonny Lamb92d90f22013-11-26 18:19:48 +0100284 gettimeofday(&tv, NULL);
285 srandom(tv.tv_usec);
286
287 box.width = BUFFER_WIDTH / BUFFER_SCALE;
288 box.height = BUFFER_HEIGHT / BUFFER_SCALE;
289 box.display = d;
290 box.window = window_create(d);
291 box.widget = window_add_widget(box.window, &box);
292 window_set_title(box.window, "Scaler Test Box");
293 window_set_buffer_scale(box.window, BUFFER_SCALE);
294
295 widget_set_resize_handler(box.widget, resize_handler);
296 widget_set_redraw_handler(box.widget, redraw_handler);
297 widget_set_button_handler(box.widget, button_handler);
298 widget_set_default_cursor(box.widget, CURSOR_HAND1);
299 widget_set_touch_down_handler(box.widget, touch_down_handler);
300
301 window_schedule_resize(box.window, box.width, box.height);
302
303 display_set_user_data(box.display, &box);
304 display_set_global_handler(box.display, global_handler);
305
306 display_run(d);
307
vivek31732f72014-05-15 18:58:16 +0530308 widget_destroy(box.widget);
Jonny Lamb92d90f22013-11-26 18:19:48 +0100309 window_destroy(box.window);
vivek31732f72014-05-15 18:58:16 +0530310 display_destroy(d);
311
Jonny Lamb92d90f22013-11-26 18:19:48 +0100312 return 0;
313}