手機 - PINE64 PinePhone - Sailfish OS - Wayland (Client) - Ping Pong



參考資訊:
https://jan.newmarch.name/Wayland/index.html
https://wayland.freedesktop.org/docs/html/apa.html
https://bugaevc.gitbooks.io/writing-wayland-clients/content/

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <wayland-client.h>
    
#define WIDTH       720
#define HEIGHT      1440
#define STRIDE      (WIDTH * 2)
#define SIZE        (STRIDE * HEIGHT)
#define SHM_NAME    "/tmp/shm"
 
uint16_t *addr = NULL;
struct wl_shm *shm = NULL;
struct wl_buffer *buf = NULL;
struct wl_shell *shell = NULL;
struct wl_display *dis = NULL;
struct wl_surface *surf = NULL;
struct wl_registry *reg = NULL;
struct wl_shm_pool *pool = NULL;
struct wl_callback *frame = NULL;
struct wl_compositor *comp = NULL;
struct wl_shell_surface *shell_surf = NULL;
   
void cb_remove(void *dat, struct wl_registry *reg, uint32_t id);
void cb_redraw(void *dat, struct wl_callback *cb, uint32_t time);
void cb_handle(void *dat, struct wl_registry *reg, uint32_t id, const char *intf, uint32_t ver);
  
static void cb_ping(void *dat, struct wl_shell_surface *shell_surf, uint32_t serial)
{
    wl_shell_surface_pong(shell_surf, serial);
}
  
static void cb_configure(void *dat, struct wl_shell_surface *shell_surf, uint32_t edges, int32_t w, int32_t h)
{
}
  
static void cb_popup_done(void *dat, struct wl_shell_surface *shell_surf)
{
}
  
static const struct wl_shell_surface_listener cb_shell_surf = {
    cb_ping,
    cb_configure,
    cb_popup_done
};
  
const struct wl_callback_listener cb_frame = {
    cb_redraw
};
   
struct wl_registry_listener cb_global = {
    .global = cb_handle,
    .global_remove = cb_remove
};
    
void cb_redraw(void *dat, struct wl_callback *cb, uint32_t time)
{
    static int cnt = 0;
    wl_callback_destroy(frame);
    wl_surface_damage(surf, 0, 0, WIDTH, HEIGHT);
   
    int x = 0, y = 0;
    uint16_t *p = addr;
    uint16_t col[] = {0xf800, 0x7e0, 0x1f};
    for (y = 0; y < HEIGHT; y++) {
        for (x = 0; x < WIDTH; x++) {
            *p++ = col[cnt % 3];
        }
    }
    cnt+= 1;
   
    frame = wl_surface_frame(surf);
    wl_surface_attach(surf, buf, 0, 0);
    wl_callback_add_listener(frame, &cb_frame, NULL);
    wl_surface_commit(surf);
}
   
void cb_handle(void *dat, struct wl_registry *reg, uint32_t id, const char *intf, uint32_t ver)
{
    if (strcmp(intf, "wl_compositor") == 0) {
        comp = wl_registry_bind(reg, id, &wl_compositor_interface, 1);
    }
    else if (strcmp(intf, "wl_shm") == 0) {
        shm = wl_registry_bind(reg, id, &wl_shm_interface, 1);
    }
    else if (strcmp(intf, "wl_shell") == 0) {
        shell = wl_registry_bind(reg, id, &wl_shell_interface, 1);
    }
}
    
void cb_remove(void *dat, struct wl_registry *reg, uint32_t id)
{
}
   
int main(int argc, char **argv)
{
    int fd = -1;
   
    dis = wl_display_connect(NULL);
    reg = wl_display_get_registry(dis);
   
    wl_registry_add_listener(reg, &cb_global, NULL);
    wl_display_dispatch(dis);
    wl_display_roundtrip(dis);
    surf = wl_compositor_create_surface(comp);
    shell_surf = wl_shell_get_shell_surface(shell, surf);
    wl_shell_surface_set_toplevel(shell_surf);
 
    unlink(SHM_NAME);
    fd = open(SHM_NAME, O_RDWR | O_EXCL | O_CREAT);
    ftruncate(fd, SIZE);
   
    addr = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    pool = wl_shm_create_pool(shm, fd, SIZE);
    buf = wl_shm_pool_create_buffer(pool, 0, WIDTH, HEIGHT, STRIDE, WL_SHM_FORMAT_RGB565);
    wl_shm_pool_destroy(pool);
  
    wl_shell_surface_set_toplevel(shell_surf);
    wl_shell_surface_add_listener(shell_surf, &cb_shell_surf, NULL);
  
    frame = wl_surface_frame(surf);
    wl_callback_add_listener(frame, &cb_frame, NULL);
   
    wl_surface_attach(surf, buf, 0, 0);
    wl_surface_commit(surf);
  
    while (1) {
        wl_display_dispatch(dis);
    }
   
    wl_callback_destroy(frame);
    wl_shell_surface_destroy(shell_surf);
    wl_shell_destroy(shell);
    wl_surface_destroy(surf);
    wl_buffer_destroy(buf);
    wl_shm_destroy(shm);
    wl_compositor_destroy(comp);
    wl_registry_destroy(reg);
    wl_display_disconnect(dis);
    munmap(addr, SIZE);
    close(fd);
    unlink(SHM_NAME);
    return 0;
}

編譯、執行

$ gcc main.c -o main -lwayland-client
$ ./main