desktop-shell: Fix black edges on scaled desktop pattern
[profile/ivi/weston-ivi-shell.git] / clients / weston-info.c
1 /*
2  * Copyright © 2012 Philipp Brüschweiler
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 <errno.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <wayland-client.h>
32
33 #include "../shared/os-compatibility.h"
34
35 typedef void (*print_info_t)(void *info);
36 typedef void (*destroy_info_t)(void *info);
37
38 struct global_info {
39         struct wl_list link;
40
41         uint32_t id;
42         uint32_t version;
43         char *interface;
44
45         print_info_t print;
46         destroy_info_t destroy;
47 };
48
49 struct output_mode {
50         struct wl_list link;
51
52         uint32_t flags;
53         int32_t width, height;
54         int32_t refresh;
55 };
56
57 struct output_info {
58         struct global_info global;
59
60         struct wl_output *output;
61
62         struct {
63                 int32_t x, y;
64                 int32_t physical_width, physical_height;
65                 enum wl_output_subpixel subpixel;
66                 enum wl_output_transform output_transform;
67                 char *make;
68                 char *model;
69         } geometry;
70
71         struct wl_list modes;
72 };
73
74 struct shm_format {
75         struct wl_list link;
76
77         uint32_t format;
78 };
79
80 struct shm_info {
81         struct global_info global;
82         struct wl_shm *shm;
83
84         struct wl_list formats;
85 };
86
87 struct seat_info {
88         struct global_info global;
89         struct wl_seat *seat;
90
91         uint32_t capabilities;
92         char *name;
93 };
94
95 struct weston_info {
96         struct wl_display *display;
97         struct wl_registry *registry;
98
99         struct wl_list infos;
100         bool roundtrip_needed;
101 };
102
103 static void *
104 fail_on_null(void *p)
105 {
106         if (p == NULL) {
107                 fprintf(stderr, "%s: out of memory\n", program_invocation_short_name);
108                 exit(EXIT_FAILURE);
109         }
110
111         return p;
112 }
113
114 static void *
115 xmalloc(size_t s)
116 {
117         return fail_on_null(malloc(s));
118 }
119
120 static void *
121 xzalloc(size_t s)
122 {
123         return fail_on_null(calloc(1, s));
124 }
125
126 static char *
127 xstrdup(const char *s)
128 {
129         return fail_on_null(strdup(s));
130 }
131
132 static void
133 print_global_info(void *data)
134 {
135         struct global_info *global = data;
136
137         printf("interface: '%s', version: %u, name: %u\n",
138                global->interface, global->version, global->id);
139 }
140
141 static void
142 init_global_info(struct weston_info *info,
143                  struct global_info *global, uint32_t id,
144                  const char *interface, uint32_t version)
145 {
146         global->id = id;
147         global->version = version;
148         global->interface = xstrdup(interface);
149
150         wl_list_insert(info->infos.prev, &global->link);
151 }
152
153 static void
154 print_output_info(void *data)
155 {
156         struct output_info *output = data;
157         struct output_mode *mode;
158         const char *subpixel_orientation;
159         const char *transform;
160
161         print_global_info(data);
162
163         switch (output->geometry.subpixel) {
164         case WL_OUTPUT_SUBPIXEL_UNKNOWN:
165                 subpixel_orientation = "unknown";
166                 break;
167         case WL_OUTPUT_SUBPIXEL_NONE:
168                 subpixel_orientation = "none";
169                 break;
170         case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
171                 subpixel_orientation = "horizontal rgb";
172                 break;
173         case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
174                 subpixel_orientation = "horizontal bgr";
175                 break;
176         case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
177                 subpixel_orientation = "vertical rgb";
178                 break;
179         case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
180                 subpixel_orientation = "vertical bgr";
181                 break;
182         default:
183                 fprintf(stderr, "unknown subpixel orientation %u\n",
184                         output->geometry.subpixel);
185                 subpixel_orientation = "unexpected value";
186                 break;
187         }
188
189         switch (output->geometry.output_transform) {
190         case WL_OUTPUT_TRANSFORM_NORMAL:
191                 transform = "normal";
192                 break;
193         case WL_OUTPUT_TRANSFORM_90:
194                 transform = "90°";
195                 break;
196         case WL_OUTPUT_TRANSFORM_180:
197                 transform = "180°";
198                 break;
199         case WL_OUTPUT_TRANSFORM_270:
200                 transform = "270°";
201                 break;
202         case WL_OUTPUT_TRANSFORM_FLIPPED:
203                 transform = "flipped";
204                 break;
205         case WL_OUTPUT_TRANSFORM_FLIPPED_90:
206                 transform = "flipped 90°";
207                 break;
208         case WL_OUTPUT_TRANSFORM_FLIPPED_180:
209                 transform = "flipped 180°";
210                 break;
211         case WL_OUTPUT_TRANSFORM_FLIPPED_270:
212                 transform = "flipped 270°";
213                 break;
214         default:
215                 fprintf(stderr, "unknown output transform %u\n",
216                         output->geometry.output_transform);
217                 transform = "unexpected value";
218                 break;
219         }
220
221         printf("\tx: %d, y: %d,\n",
222                output->geometry.x, output->geometry.y);
223         printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
224                output->geometry.physical_width,
225                output->geometry.physical_height);
226         printf("\tmake: '%s', model: '%s',\n",
227                output->geometry.make, output->geometry.model);
228         printf("\tsubpixel_orientation: %s, output_transform: %s,\n",
229                subpixel_orientation, transform);
230
231         wl_list_for_each(mode, &output->modes, link) {
232                 printf("\tmode:\n");
233
234                 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
235                        mode->width, mode->height,
236                        (float) mode->refresh / 1000);
237
238                 printf("\t\tflags:");
239                 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
240                         printf(" current");
241                 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
242                         printf(" preferred");
243                 printf("\n");
244         }
245 }
246
247 static void
248 print_shm_info(void *data)
249 {
250         struct shm_info *shm = data;
251         struct shm_format *format;
252
253         print_global_info(data);
254
255         printf("\tformats:");
256
257         wl_list_for_each(format, &shm->formats, link)
258                 switch (format->format) {
259                 case WL_SHM_FORMAT_ARGB8888:
260                         printf(" ARGB8888");
261                         break;
262                 case WL_SHM_FORMAT_XRGB8888:
263                         printf(" XRGB8888");
264                         break;
265                 case WL_SHM_FORMAT_RGB565:
266                         printf(" RGB565");
267                         break;
268                 default:
269                         printf(" unknown(%08x)", format->format);
270                         break;
271                 }
272
273         printf("\n");
274 }
275
276 static void
277 print_seat_info(void *data)
278 {
279         struct seat_info *seat = data;
280
281         print_global_info(data);
282
283         printf("\tname: %s\n", seat->name);
284         printf("\tcapabilities:");
285
286         if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
287                 printf(" pointer");
288         if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
289                 printf(" keyboard");
290         if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
291                 printf(" touch");
292
293         printf("\n");
294 }
295
296 static void
297 seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
298                          enum wl_seat_capability caps)
299 {
300         struct seat_info *seat = data;
301         seat->capabilities = caps;
302 }
303
304 static void
305 seat_handle_name(void *data, struct wl_seat *wl_seat,
306                  const char *name)
307 {
308         struct seat_info *seat = data;
309         seat->name = xstrdup(name);
310 }
311
312 static const struct wl_seat_listener seat_listener = {
313         seat_handle_capabilities,
314         seat_handle_name,
315 };
316
317 static void
318 destroy_seat_info(void *data)
319 {
320         struct seat_info *seat = data;
321
322         wl_seat_destroy(seat->seat);
323
324         if (seat->name != NULL)
325                 free(seat->name);
326 }
327
328 static void
329 add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
330 {
331         struct seat_info *seat = xzalloc(sizeof *seat);
332
333         init_global_info(info, &seat->global, id, "wl_seat", version);
334         seat->global.print = print_seat_info;
335         seat->global.destroy = destroy_seat_info;
336
337         seat->seat = wl_registry_bind(info->registry,
338                                       id, &wl_seat_interface, 2);
339         wl_seat_add_listener(seat->seat, &seat_listener, seat);
340
341         info->roundtrip_needed = true;
342 }
343
344 static void
345 shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
346 {
347         struct shm_info *shm = data;
348         struct shm_format *shm_format = xzalloc(sizeof *shm_format);
349
350         wl_list_insert(&shm->formats, &shm_format->link);
351         shm_format->format = format;
352 }
353
354 static const struct wl_shm_listener shm_listener = {
355         shm_handle_format,
356 };
357
358 static void
359 destroy_shm_info(void *data)
360 {
361         struct shm_info *shm = data;
362         struct shm_format *format, *tmp;
363
364         wl_list_for_each_safe(format, tmp, &shm->formats, link) {
365                 wl_list_remove(&format->link);
366                 free(format);
367         }
368
369         wl_shm_destroy(shm->shm);
370 }
371
372 static void
373 add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
374 {
375         struct shm_info *shm = xzalloc(sizeof *shm);
376
377         init_global_info(info, &shm->global, id, "wl_shm", version);
378         shm->global.print = print_shm_info;
379         shm->global.destroy = destroy_shm_info;
380
381         wl_list_init(&shm->formats);
382
383         shm->shm = wl_registry_bind(info->registry,
384                                     id, &wl_shm_interface, 1);
385         wl_shm_add_listener(shm->shm, &shm_listener, shm);
386
387         info->roundtrip_needed = true;
388 }
389
390 static void
391 output_handle_geometry(void *data, struct wl_output *wl_output,
392                        int32_t x, int32_t y,
393                        int32_t physical_width, int32_t physical_height,
394                        int32_t subpixel,
395                        const char *make, const char *model,
396                        int32_t output_transform)
397 {
398         struct output_info *output = data;
399
400         output->geometry.x = x;
401         output->geometry.y = y;
402         output->geometry.physical_width = physical_width;
403         output->geometry.physical_height = physical_height;
404         output->geometry.subpixel = subpixel;
405         output->geometry.make = xstrdup(make);
406         output->geometry.model = xstrdup(model);
407         output->geometry.output_transform = output_transform;
408 }
409
410 static void
411 output_handle_mode(void *data, struct wl_output *wl_output,
412                    uint32_t flags, int32_t width, int32_t height,
413                    int32_t refresh)
414 {
415         struct output_info *output = data;
416         struct output_mode *mode = xmalloc(sizeof *mode);
417
418         mode->flags = flags;
419         mode->width = width;
420         mode->height = height;
421         mode->refresh = refresh;
422
423         wl_list_insert(output->modes.prev, &mode->link);
424 }
425
426 static const struct wl_output_listener output_listener = {
427         output_handle_geometry,
428         output_handle_mode,
429 };
430
431 static void
432 destroy_output_info(void *data)
433 {
434         struct output_info *output = data;
435         struct output_mode *mode, *tmp;
436
437         wl_output_destroy(output->output);
438
439         if (output->geometry.make != NULL)
440                 free(output->geometry.make);
441         if (output->geometry.model != NULL)
442                 free(output->geometry.model);
443
444         wl_list_for_each_safe(mode, tmp, &output->modes, link) {
445                 wl_list_remove(&mode->link);
446                 free(mode);
447         }
448 }
449
450 static void
451 add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
452 {
453         struct output_info *output = xzalloc(sizeof *output);
454
455         init_global_info(info, &output->global, id, "wl_output", version);
456         output->global.print = print_output_info;
457         output->global.destroy = destroy_output_info;
458
459         wl_list_init(&output->modes);
460
461         output->output = wl_registry_bind(info->registry, id,
462                                           &wl_output_interface, 1);
463         wl_output_add_listener(output->output, &output_listener,
464                                output);
465
466         info->roundtrip_needed = true;
467 }
468
469 static void
470 destroy_global_info(void *data)
471 {
472 }
473
474 static void
475 add_global_info(struct weston_info *info, uint32_t id,
476                 const char *interface, uint32_t version)
477 {
478         struct global_info *global = xzalloc(sizeof *global);
479
480         init_global_info(info, global, id, interface, version);
481         global->print = print_global_info;
482         global->destroy = destroy_global_info;
483 }
484
485 static void
486 global_handler(void *data, struct wl_registry *registry, uint32_t id,
487                const char *interface, uint32_t version)
488 {
489         struct weston_info *info = data;
490
491         if (!strcmp(interface, "wl_seat"))
492                 add_seat_info(info, id, version);
493         else if (!strcmp(interface, "wl_shm"))
494                 add_shm_info(info, id, version);
495         else if (!strcmp(interface, "wl_output"))
496                 add_output_info(info, id, version);
497         else
498                 add_global_info(info, id, interface, version);
499 }
500
501 static void
502 global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
503 {
504 }
505
506 static const struct wl_registry_listener registry_listener = {
507         global_handler,
508         global_remove_handler
509 };
510
511 static void
512 print_infos(struct wl_list *infos)
513 {
514         struct global_info *info;
515
516         wl_list_for_each(info, infos, link)
517                 info->print(info);
518 }
519
520 static void
521 destroy_info(void *data)
522 {
523         struct global_info *global = data;
524
525         global->destroy(data);
526         wl_list_remove(&global->link);
527         free(global->interface);
528         free(data);
529 }
530
531 static void
532 destroy_infos(struct wl_list *infos)
533 {
534         struct global_info *info, *tmp;
535         wl_list_for_each_safe(info, tmp, infos, link)
536                 destroy_info(info);
537 }
538
539 int
540 main(int argc, char **argv)
541 {
542         struct weston_info info;
543
544         info.display = wl_display_connect(NULL);
545         if (!info.display) {
546                 fprintf(stderr, "failed to create display: %m\n");
547                 return -1;
548         }
549
550         wl_list_init(&info.infos);
551
552         info.registry = wl_display_get_registry(info.display);
553         wl_registry_add_listener(info.registry, &registry_listener, &info);
554
555         do {
556                 info.roundtrip_needed = false;
557                 wl_display_roundtrip(info.display);
558         } while (info.roundtrip_needed);
559
560         print_infos(&info.infos);
561         destroy_infos(&info.infos);
562
563         wl_registry_destroy(info.registry);
564         wl_display_disconnect(info.display);
565
566         return 0;
567 }