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