1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "host/libs/wayland/wayland_compositor.h"
18
19 #include <android-base/logging.h>
20
21 #include <wayland-server-core.h>
22 #include <wayland-server-protocol.h>
23
24 #include "host/libs/wayland/wayland_surface.h"
25 #include "host/libs/wayland/wayland_utils.h"
26
27 namespace wayland {
28 namespace {
29
region_destroy(wl_client *,wl_resource * region_resource)30 void region_destroy(wl_client*, wl_resource* region_resource) {
31 LOG(VERBOSE) << __FUNCTION__
32 << " region=" << region_resource;
33
34 wl_resource_destroy(region_resource);
35 }
36
region_add(wl_client *,wl_resource * region_resource,int32_t x,int32_t y,int32_t w,int32_t h)37 void region_add(wl_client*,
38 wl_resource* region_resource,
39 int32_t x,
40 int32_t y,
41 int32_t w,
42 int32_t h) {
43 LOG(VERBOSE) << __FUNCTION__
44 << " region=" << region_resource
45 << " x=" << x
46 << " y=" << y
47 << " w=" << w
48 << " h=" << h;
49
50 Surface::Region* region = GetUserData<Surface::Region>(region_resource);
51 region->x = x;
52 region->y = y;
53 region->w = w;
54 region->h = h;
55 }
56
region_subtract(wl_client *,wl_resource * region_resource,int32_t x,int32_t y,int32_t w,int32_t h)57 void region_subtract(wl_client*,
58 wl_resource* region_resource,
59 int32_t x,
60 int32_t y,
61 int32_t w,
62 int32_t h) {
63 LOG(VERBOSE) << __FUNCTION__
64 << " region=" << region_resource
65 << " x=" << x
66 << " y=" << y
67 << " w=" << w
68 << " h=" << h;
69 }
70
71 const struct wl_region_interface region_implementation = {
72 .destroy = region_destroy,
73 .add = region_add,
74 .subtract = region_subtract,
75 };
76
surface_destroy(wl_client *,wl_resource * surface)77 void surface_destroy(wl_client*, wl_resource* surface) {
78 LOG(VERBOSE) << __FUNCTION__
79 << " surface=" << surface;
80 }
81
surface_attach(wl_client *,wl_resource * surface,wl_resource * buffer,int32_t x,int32_t y)82 void surface_attach(wl_client*,
83 wl_resource* surface,
84 wl_resource* buffer,
85 int32_t x,
86 int32_t y) {
87 LOG(VERBOSE) << __FUNCTION__
88 << " surface=" << surface
89 << " buffer=" << buffer
90 << " x=" << x
91 << " y=" << y;
92
93 GetUserData<Surface>(surface)->Attach(buffer);
94 }
95
surface_damage(wl_client *,wl_resource * surface_resource,int32_t x,int32_t y,int32_t w,int32_t h)96 void surface_damage(wl_client*,
97 wl_resource* surface_resource,
98 int32_t x,
99 int32_t y,
100 int32_t w,
101 int32_t h) {
102 LOG(VERBOSE) << __FUNCTION__
103 << " surface=" << surface_resource
104 << " x=" << x
105 << " y=" << y
106 << " w=" << w
107 << " h=" << h;
108 }
109
surface_frame(wl_client *,wl_resource * surface,uint32_t)110 void surface_frame(wl_client*, wl_resource* surface, uint32_t) {
111 LOG(VERBOSE) << " surface=" << surface;
112 }
113
surface_set_opaque_region(wl_client *,wl_resource * surface_resource,wl_resource * region_resource)114 void surface_set_opaque_region(wl_client*,
115 wl_resource* surface_resource,
116 wl_resource* region_resource) {
117 LOG(VERBOSE) << __FUNCTION__
118 << " surface=" << surface_resource
119 << " region=" << region_resource;
120
121 Surface* surface = GetUserData<Surface>(surface_resource);
122 Surface::Region* region = GetUserData<Surface::Region>(region_resource);
123
124 surface->SetRegion(*region);
125 }
126
surface_set_input_region(wl_client *,wl_resource * surface_resource,wl_resource * region_resource)127 void surface_set_input_region(wl_client*,
128 wl_resource* surface_resource,
129 wl_resource* region_resource) {
130 LOG(VERBOSE) << __FUNCTION__
131 << " surface=" << surface_resource
132 << " region=" << region_resource;
133 }
134
surface_commit(wl_client *,wl_resource * surface_resource)135 void surface_commit(wl_client*, wl_resource* surface_resource) {
136 LOG(VERBOSE) << __FUNCTION__
137 << " surface=" << surface_resource;
138
139 GetUserData<Surface>(surface_resource)->Commit();
140 }
141
surface_set_buffer_transform(wl_client *,wl_resource * surface_resource,int32_t transform)142 void surface_set_buffer_transform(wl_client*,
143 wl_resource* surface_resource,
144 int32_t transform) {
145 LOG(VERBOSE) << __FUNCTION__
146 << " surface=" << surface_resource
147 << " transform=" << transform;
148 }
149
surface_set_buffer_scale(wl_client *,wl_resource * surface_resource,int32_t scale)150 void surface_set_buffer_scale(wl_client*,
151 wl_resource* surface_resource,
152 int32_t scale) {
153 LOG(VERBOSE) << __FUNCTION__
154 << " surface=" << surface_resource
155 << " scale=" << scale;
156 }
157
surface_damage_buffer(wl_client *,wl_resource * surface_resource,int32_t x,int32_t y,int32_t w,int32_t h)158 void surface_damage_buffer(wl_client*,
159 wl_resource* surface_resource,
160 int32_t x,
161 int32_t y,
162 int32_t w,
163 int32_t h) {
164 LOG(VERBOSE) << __FUNCTION__
165 << " surface=" << surface_resource
166 << " x=" << x
167 << " y=" << y
168 << " w=" << w
169 << " h=" << h;
170 }
171
172 const struct wl_surface_interface surface_implementation = {
173 .destroy = surface_destroy,
174 .attach = surface_attach,
175 .damage = surface_damage,
176 .frame = surface_frame,
177 .set_opaque_region = surface_set_opaque_region,
178 .set_input_region = surface_set_input_region,
179 .commit = surface_commit,
180 .set_buffer_transform = surface_set_buffer_transform,
181 .set_buffer_scale = surface_set_buffer_scale,
182 .damage_buffer = surface_damage_buffer,
183 };
184
surface_destroy_resource_callback(struct wl_resource *)185 void surface_destroy_resource_callback(struct wl_resource*) {}
186
compositor_create_surface(wl_client * client,wl_resource * compositor,uint32_t id)187 void compositor_create_surface(wl_client* client,
188 wl_resource* compositor,
189 uint32_t id) {
190 LOG(VERBOSE) << __FUNCTION__
191 << " compositor=" << compositor
192 << " id=" << id;
193
194 // Wayland seems to use a single global id space for all objects.
195 static std::atomic<std::uint32_t> sNextDisplayId{0};
196 uint32_t display_id = sNextDisplayId++;
197
198 Surfaces* surfaces = GetUserData<Surfaces>(compositor);
199 Surface* surface = surfaces->GetOrCreateSurface(display_id);
200
201 wl_resource* surface_resource = wl_resource_create(
202 client, &wl_surface_interface, wl_resource_get_version(compositor), id);
203
204 wl_resource_set_implementation(surface_resource, &surface_implementation,
205 surface, surface_destroy_resource_callback);
206 }
207
compositor_create_region(wl_client * client,wl_resource * compositor,uint32_t id)208 void compositor_create_region(wl_client* client,
209 wl_resource* compositor,
210 uint32_t id) {
211 LOG(VERBOSE) << __FUNCTION__
212 << " compositor=" << compositor
213 << " id=" << id;
214
215 std::unique_ptr<Surface::Region> region(new Surface::Region());
216
217 wl_resource* region_resource = wl_resource_create(
218 client, &wl_region_interface, 1, id);
219
220 wl_resource_set_implementation(region_resource, ®ion_implementation,
221 region.release(),
222 DestroyUserData<Surface::Region>);
223 }
224
225 const struct wl_compositor_interface compositor_implementation = {
226 .create_surface = compositor_create_surface,
227 .create_region = compositor_create_region,
228 };
229
230 constexpr const uint32_t kCompositorVersion = 3;
231
compositor_destroy_resource_callback(struct wl_resource *)232 void compositor_destroy_resource_callback(struct wl_resource*) {}
233
bind_compositor(wl_client * client,void * data,uint32_t version,uint32_t id)234 void bind_compositor(wl_client* client,
235 void* data,
236 uint32_t version,
237 uint32_t id) {
238 wl_resource* resource =
239 wl_resource_create(client, &wl_compositor_interface,
240 std::min(version, kCompositorVersion), id);
241
242 wl_resource_set_implementation(resource, &compositor_implementation, data,
243 compositor_destroy_resource_callback);
244 }
245
246 } // namespace
247
BindCompositorInterface(wl_display * display,Surfaces * surfaces)248 void BindCompositorInterface(wl_display* display, Surfaces* surfaces) {
249 wl_global_create(display, &wl_compositor_interface, kCompositorVersion,
250 surfaces, bind_compositor);
251 }
252
253 } // namespace wayland
254