Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: components/exo/wayland/server.cc

Issue 1412093006: components: Add Exosphere component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix build issues and remove wayland_bindings.h Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/exo/wayland/server.h"
6
7 #include <wayland-server-core.h>
8 #include <wayland-server-protocol-core.h>
9
10 #include <algorithm>
11
12 #include "base/bind.h"
13 #include "base/cancelable_callback.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "cc/base/region.h"
16 #include "components/exo/buffer.h"
17 #include "components/exo/display.h"
18 #include "components/exo/shared_memory.h"
19 #include "components/exo/shell_surface.h"
20 #include "components/exo/surface.h"
21
22 namespace exo {
23 namespace wayland {
24 namespace {
25
26 template <class T>
27 T* GetUserDataAs(wl_resource* resource) {
28 return static_cast<T*>(wl_resource_get_user_data(resource));
29 }
30
31 template <class T>
32 scoped_ptr<T> TakeUserDataAs(wl_resource* resource) {
33 scoped_ptr<T> user_data = make_scoped_ptr(GetUserDataAs<T>(resource));
34 wl_resource_set_user_data(resource, nullptr);
35 return user_data.Pass();
36 }
37
38 template <class T>
39 void DestroyUserData(wl_resource* resource) {
40 TakeUserDataAs<T>(resource);
41 }
42
43 template <class T>
44 void SetImplementation(wl_resource* resource,
45 const void* implementation,
46 scoped_ptr<T> user_data) {
47 wl_resource_set_implementation(resource, implementation, user_data.release(),
48 DestroyUserData<T>);
49 }
50
51 ////////////////////////////////////////////////////////////////////////////////
52 // wl_buffer_interface:
53
54 void buffer_destroy(wl_client* client, wl_resource* resource) {
55 wl_resource_destroy(resource);
56 }
57
58 const struct wl_buffer_interface buffer_implementation = {buffer_destroy};
59
60 ////////////////////////////////////////////////////////////////////////////////
61 // wl_surface_interface:
62
63 void surface_destroy(wl_client* client, wl_resource* resource) {
64 wl_resource_destroy(resource);
65 }
66
67 void surface_attach(wl_client* client,
68 wl_resource* resource,
69 wl_resource* buffer,
70 int32_t x,
71 int32_t y) {
72 // TODO(reveman): Implement buffer offset support.
73 if (x || y) {
74 wl_resource_post_no_memory(resource);
75 return;
76 }
77
78 GetUserDataAs<Surface>(resource)
79 ->Attach(buffer ? GetUserDataAs<Buffer>(buffer) : nullptr);
80 }
81
82 void surface_damage(wl_client* client,
83 wl_resource* resource,
84 int32_t x,
85 int32_t y,
86 int32_t width,
87 int32_t height) {
88 GetUserDataAs<Surface>(resource)->Damage(gfx::Rect(x, y, width, height));
89 }
90
91 void handle_surface_frame_callback(wl_resource* resource,
92 base::TimeTicks frame_time) {
93 if (!frame_time.is_null()) {
94 wl_callback_send_done(resource,
95 (frame_time - base::TimeTicks()).InMilliseconds());
96 // TODO(reveman): Remove this potentially blocking flush and instead watch
97 // the file descriptor to be ready for write without blocking.
98 wl_client_flush(wl_resource_get_client(resource));
99 }
100 wl_resource_destroy(resource);
101 }
102
103 void surface_frame(wl_client* client,
104 wl_resource* resource,
105 uint32_t callback) {
106 wl_resource* callback_resource =
107 wl_resource_create(client, &wl_callback_interface, 1, callback);
108 if (!callback_resource) {
109 wl_resource_post_no_memory(resource);
110 return;
111 }
112
113 // base::Unretained is safe as the resource owns the callback.
114 scoped_ptr<base::CancelableCallback<void(base::TimeTicks)>>
115 cancelable_callback(new base::CancelableCallback<void(base::TimeTicks)>(
116 base::Bind(&handle_surface_frame_callback,
117 base::Unretained(callback_resource))));
118
119 GetUserDataAs<Surface>(resource)
120 ->RequestFrameCallback(cancelable_callback->callback());
121
122 SetImplementation(callback_resource, nullptr, cancelable_callback.Pass());
123 }
124
125 void surface_set_opaque_region(wl_client* client,
126 wl_resource* resource,
127 wl_resource* region_resource) {
128 GetUserDataAs<Surface>(resource)->SetOpaqueRegion(
129 region_resource ? *GetUserDataAs<cc::Region>(region_resource)
130 : cc::Region());
131 }
132
133 void surface_set_input_region(wl_client* client,
134 wl_resource* resource,
135 wl_resource* region_resource) {
136 NOTIMPLEMENTED();
137 }
138
139 void surface_commit(wl_client* client, wl_resource* resource) {
140 GetUserDataAs<Surface>(resource)->Commit();
141 }
142
143 void surface_set_buffer_transform(wl_client* client,
144 wl_resource* resource,
145 int transform) {
146 NOTIMPLEMENTED();
147 }
148
149 void surface_set_buffer_scale(wl_client* client,
150 wl_resource* resource,
151 int32_t scale) {
152 NOTIMPLEMENTED();
153 }
154
155 const struct wl_surface_interface surface_implementation = {
156 surface_destroy,
157 surface_attach,
158 surface_damage,
159 surface_frame,
160 surface_set_opaque_region,
161 surface_set_input_region,
162 surface_commit,
163 surface_set_buffer_transform,
164 surface_set_buffer_scale};
165
166 ////////////////////////////////////////////////////////////////////////////////
167 // wl_region_interface:
168
169 void region_destroy(wl_client* client, wl_resource* resource) {
170 wl_resource_destroy(resource);
171 }
172
173 void region_add(wl_client* client,
174 wl_resource* resource,
175 int32_t x,
176 int32_t y,
177 int32_t width,
178 int32_t height) {
179 GetUserDataAs<cc::Region>(resource)->Union(gfx::Rect(x, y, width, height));
180 }
181
182 static void region_subtract(wl_client* client,
183 wl_resource* resource,
184 int32_t x,
185 int32_t y,
186 int32_t width,
187 int32_t height) {
188 GetUserDataAs<cc::Region>(resource)->Subtract(gfx::Rect(x, y, width, height));
189 }
190
191 const struct wl_region_interface region_implementation = {
192 region_destroy, region_add, region_subtract};
193
194 ////////////////////////////////////////////////////////////////////////////////
195 // wl_compositor_interface:
196
197 void compositor_create_surface(wl_client* client,
198 wl_resource* resource,
199 uint32_t id) {
200 scoped_ptr<Surface> surface =
201 GetUserDataAs<Display>(resource)->CreateSurface();
202 DCHECK(surface);
203
204 wl_resource* surface_resource = wl_resource_create(
205 client, &wl_surface_interface, wl_resource_get_version(resource), id);
206 if (!surface_resource) {
207 wl_resource_post_no_memory(resource);
208 return;
209 }
210
211 SetImplementation(surface_resource, &surface_implementation, surface.Pass());
212 }
213
214 void compositor_create_region(wl_client* client,
215 wl_resource* resource,
216 uint32_t id) {
217 scoped_ptr<cc::Region> region(new cc::Region);
218
219 wl_resource* region_resource =
220 wl_resource_create(client, &wl_region_interface, 1, id);
221 if (!region_resource) {
222 wl_resource_post_no_memory(resource);
223 return;
224 }
225
226 SetImplementation(region_resource, &region_implementation, region.Pass());
227 }
228
229 const struct wl_compositor_interface compositor_implementation = {
230 compositor_create_surface, compositor_create_region};
231
232 const uint32_t compositor_version = 3;
233
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, compositor_version), id);
241 if (!resource) {
242 wl_client_post_no_memory(client);
243 return;
244 }
245
246 wl_resource_set_implementation(resource, &compositor_implementation, data,
247 nullptr);
248 }
249
250 ////////////////////////////////////////////////////////////////////////////////
251 // wl_shm_pool_interface:
252
253 const struct shm_supported_format {
254 uint32_t shm_format;
255 gfx::BufferFormat buffer_format;
256 } shm_supported_formats[] = {
257 {WL_SHM_FORMAT_XBGR8888, gfx::BufferFormat::RGBX_8888},
258 {WL_SHM_FORMAT_ABGR8888, gfx::BufferFormat::RGBA_8888},
259 {WL_SHM_FORMAT_XRGB8888, gfx::BufferFormat::BGRX_8888},
260 {WL_SHM_FORMAT_ARGB8888, gfx::BufferFormat::BGRA_8888}};
261
262 void shm_pool_create_buffer(wl_client* client,
263 wl_resource* resource,
264 uint32_t id,
265 int32_t offset,
266 int32_t width,
267 int32_t height,
268 int32_t stride,
269 uint32_t format) {
270 const auto supported_format =
271 std::find_if(shm_supported_formats,
272 shm_supported_formats + arraysize(shm_supported_formats),
273 [format](const shm_supported_format& supported_format) {
274 return supported_format.shm_format == format;
275 });
276 if (supported_format ==
277 (shm_supported_formats + arraysize(shm_supported_formats))) {
278 wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
279 "invalid format 0x%x", format);
280 return;
281 }
282
283 if (offset < 0) {
284 wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
285 "invalid offset %d", offset);
286 return;
287 }
288
289 scoped_ptr<Buffer> buffer =
290 GetUserDataAs<SharedMemory>(resource)
291 ->CreateBuffer(gfx::Size(width, height),
292 supported_format->buffer_format, offset, stride);
293 if (!buffer) {
294 wl_resource_post_no_memory(resource);
295 return;
296 }
297
298 wl_resource* buffer_resource =
299 wl_resource_create(client, &wl_buffer_interface, 1, id);
300 if (!buffer_resource) {
301 wl_resource_post_no_memory(resource);
302 return;
303 }
304
305 buffer->set_release_callback(
306 base::Bind(&wl_buffer_send_release, base::Unretained(buffer_resource)));
307
308 SetImplementation(buffer_resource, &buffer_implementation, buffer.Pass());
309 }
310
311 void shm_pool_destroy(wl_client* client, wl_resource* resource) {
312 wl_resource_destroy(resource);
313 }
314
315 void shm_pool_resize(wl_client* client, wl_resource* resource, int32_t size) {
316 // Nothing to do here.
317 }
318
319 const struct wl_shm_pool_interface shm_pool_implementation = {
320 shm_pool_create_buffer, shm_pool_destroy, shm_pool_resize};
321
322 ////////////////////////////////////////////////////////////////////////////////
323 // wl_shm_interface:
324
325 void shm_create_pool(wl_client* client,
326 wl_resource* resource,
327 uint32_t id,
328 int fd,
329 int32_t size) {
330 scoped_ptr<SharedMemory> shared_memory =
331 GetUserDataAs<Display>(resource)
332 ->CreateSharedMemory(base::FileDescriptor(fd, true), size);
333 if (!shared_memory) {
334 wl_resource_post_no_memory(resource);
335 return;
336 }
337
338 wl_resource* shm_pool_resource =
339 wl_resource_create(client, &wl_shm_pool_interface, 1, id);
340 if (!shm_pool_resource) {
341 wl_resource_post_no_memory(resource);
342 return;
343 }
344
345 SetImplementation(shm_pool_resource, &shm_pool_implementation,
346 shared_memory.Pass());
347 }
348
349 const struct wl_shm_interface shm_implementation = {shm_create_pool};
350
351 void bind_shm(wl_client* client, void* data, uint32_t version, uint32_t id) {
352 wl_resource* resource = wl_resource_create(client, &wl_shm_interface, 1, id);
353 if (!resource) {
354 wl_client_post_no_memory(client);
355 return;
356 }
357
358 wl_resource_set_implementation(resource, &shm_implementation, data, nullptr);
359
360 for (const auto& supported_format : shm_supported_formats)
361 wl_shm_send_format(resource, supported_format.shm_format);
362 }
363
364 ////////////////////////////////////////////////////////////////////////////////
365 // wl_shell_surface_interface:
366
367 void shell_surface_pong(wl_client* client,
368 wl_resource* resource,
369 uint32_t serial) {
370 NOTIMPLEMENTED();
371 }
372
373 void shell_surface_move(wl_client* client,
374 wl_resource* resource,
375 wl_resource* seat_resource,
376 uint32_t serial) {
377 NOTIMPLEMENTED();
378 }
379
380 void shell_surface_resize(wl_client* client,
381 wl_resource* resource,
382 wl_resource* seat_resource,
383 uint32_t serial,
384 uint32_t edges) {
385 NOTIMPLEMENTED();
386 }
387
388 void shell_surface_set_toplevel(wl_client* client, wl_resource* resource) {
389 GetUserDataAs<ShellSurface>(resource)->SetToplevel();
390 }
391
392 void shell_surface_set_transient(wl_client* client,
393 wl_resource* resource,
394 wl_resource* parent_resource,
395 int x,
396 int y,
397 uint32_t flags) {
398 NOTIMPLEMENTED();
399 }
400
401 void shell_surface_set_fullscreen(wl_client* client,
402 wl_resource* resource,
403 uint32_t method,
404 uint32_t framerate,
405 wl_resource* output_resource) {
406 GetUserDataAs<ShellSurface>(resource)->SetFullscreen(true);
407 }
408
409 void shell_surface_set_popup(wl_client* client,
410 wl_resource* resource,
411 wl_resource* seat_resource,
412 uint32_t serial,
413 wl_resource* parent_resource,
414 int32_t x,
415 int32_t y,
416 uint32_t flags) {
417 NOTIMPLEMENTED();
418 }
419
420 void shell_surface_set_maximized(wl_client* client,
421 wl_resource* resource,
422 wl_resource* output_resource) {
423 NOTIMPLEMENTED();
424 }
425
426 void shell_surface_set_title(wl_client* client,
427 wl_resource* resource,
428 const char* title) {
429 GetUserDataAs<ShellSurface>(resource)
430 ->SetTitle(base::string16(base::ASCIIToUTF16(title)));
431 }
432
433 void shell_surface_set_class(wl_client* client,
434 wl_resource* resource,
435 const char* clazz) {
436 NOTIMPLEMENTED();
437 }
438
439 const struct wl_shell_surface_interface shell_surface_implementation = {
440 shell_surface_pong, shell_surface_move,
441 shell_surface_resize, shell_surface_set_toplevel,
442 shell_surface_set_transient, shell_surface_set_fullscreen,
443 shell_surface_set_popup, shell_surface_set_maximized,
444 shell_surface_set_title, shell_surface_set_class};
445
446 ////////////////////////////////////////////////////////////////////////////////
447 // wl_shell_interface:
448
449 void shell_get_shell_surface(wl_client* client,
450 wl_resource* resource,
451 uint32_t id,
452 wl_resource* surface) {
453 scoped_ptr<ShellSurface> shell_surface =
454 GetUserDataAs<Display>(resource)
455 ->CreateShellSurface(GetUserDataAs<Surface>(surface));
456 if (!shell_surface) {
457 wl_resource_post_no_memory(resource);
458 return;
459 }
460
461 wl_resource* shell_surface_resource =
462 wl_resource_create(client, &wl_shell_surface_interface, 1, id);
463 if (!shell_surface_resource) {
464 wl_resource_post_no_memory(resource);
465 return;
466 }
467
468 SetImplementation(shell_surface_resource, &shell_surface_implementation,
469 shell_surface.Pass());
470 }
471
472 const struct wl_shell_interface shell_implementation = {
473 shell_get_shell_surface};
474
475 void bind_shell(wl_client* client, void* data, uint32_t version, uint32_t id) {
476 wl_resource* resource =
477 wl_resource_create(client, &wl_shell_interface, 1, id);
478 if (!resource) {
479 wl_client_post_no_memory(client);
480 return;
481 }
482 wl_resource_set_implementation(resource, &shell_implementation, data,
483 nullptr);
484 }
485
486 } // namespace
487
488 ////////////////////////////////////////////////////////////////////////////////
489 // Server, public:
490
491 Server::Server(Display* display)
492 : display_(display), wl_display_(wl_display_create()) {
493 wl_global_create(wl_display_.get(), &wl_compositor_interface,
494 compositor_version, display_, bind_compositor);
495 wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm);
496 wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
497 bind_shell);
498 }
499
500 Server::~Server() {}
501
502 // static
503 scoped_ptr<Server> Server::Create(Display* display) {
504 scoped_ptr<Server> server(new Server(display));
505 int rv = wl_display_add_socket(server->wl_display_.get(), nullptr);
506 DCHECK_EQ(rv, 0) << "wl_display_add_socket failed: " << rv;
507 return server;
508 }
509
510 bool Server::AddSocket(const std::string name) {
511 DCHECK(!name.empty());
512 return !wl_display_add_socket(wl_display_.get(), name.c_str());
513 }
514
515 int Server::GetFileDescriptor() const {
516 wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
517 DCHECK(event_loop);
518 return wl_event_loop_get_fd(event_loop);
519 }
520
521 void Server::Dispatch(base::TimeDelta timeout) {
522 wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
523 DCHECK(event_loop);
524 wl_event_loop_dispatch(event_loop, timeout.InMilliseconds());
525 }
526
527 void Server::Flush() {
528 wl_display_flush_clients(wl_display_.get());
529 }
530
531 } // namespace wayland
532 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698