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

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: remove some ifdefs 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
« no previous file with comments | « components/exo/wayland/server.h ('k') | components/exo/wayland/server_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "components/exo/buffer.h"
16 #include "components/exo/display.h"
17 #include "components/exo/shared_memory.h"
18 #include "components/exo/shell_surface.h"
19 #include "components/exo/surface.h"
20 #include "third_party/skia/include/core/SkRegion.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<SkRegion>(region_resource)
130 : SkRegion(SkIRect::MakeEmpty()));
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<SkRegion>(resource)
180 ->op(SkIRect::MakeXYWH(x, y, width, height), SkRegion::kUnion_Op);
181 }
182
183 static void region_subtract(wl_client* client,
184 wl_resource* resource,
185 int32_t x,
186 int32_t y,
187 int32_t width,
188 int32_t height) {
189 GetUserDataAs<SkRegion>(resource)
190 ->op(SkIRect::MakeXYWH(x, y, width, height), SkRegion::kDifference_Op);
191 }
192
193 const struct wl_region_interface region_implementation = {
194 region_destroy, region_add, region_subtract};
195
196 ////////////////////////////////////////////////////////////////////////////////
197 // wl_compositor_interface:
198
199 void compositor_create_surface(wl_client* client,
200 wl_resource* resource,
201 uint32_t id) {
202 scoped_ptr<Surface> surface =
203 GetUserDataAs<Display>(resource)->CreateSurface();
204 DCHECK(surface);
205
206 wl_resource* surface_resource = wl_resource_create(
207 client, &wl_surface_interface, wl_resource_get_version(resource), id);
208 if (!surface_resource) {
209 wl_resource_post_no_memory(resource);
210 return;
211 }
212
213 SetImplementation(surface_resource, &surface_implementation, surface.Pass());
214 }
215
216 void compositor_create_region(wl_client* client,
217 wl_resource* resource,
218 uint32_t id) {
219 scoped_ptr<SkRegion> region(new SkRegion);
220
221 wl_resource* region_resource =
222 wl_resource_create(client, &wl_region_interface, 1, id);
223 if (!region_resource) {
224 wl_resource_post_no_memory(resource);
225 return;
226 }
227
228 SetImplementation(region_resource, &region_implementation, region.Pass());
229 }
230
231 const struct wl_compositor_interface compositor_implementation = {
232 compositor_create_surface, compositor_create_region};
233
234 const uint32_t compositor_version = 3;
235
236 void bind_compositor(wl_client* client,
237 void* data,
238 uint32_t version,
239 uint32_t id) {
240 wl_resource* resource =
241 wl_resource_create(client, &wl_compositor_interface,
242 std::min(version, compositor_version), id);
243 if (!resource) {
244 wl_client_post_no_memory(client);
245 return;
246 }
247
248 wl_resource_set_implementation(resource, &compositor_implementation, data,
249 nullptr);
250 }
251
252 ////////////////////////////////////////////////////////////////////////////////
253 // wl_shm_pool_interface:
254
255 const struct shm_supported_format {
256 uint32_t shm_format;
257 gfx::BufferFormat buffer_format;
258 } shm_supported_formats[] = {
259 {WL_SHM_FORMAT_XBGR8888, gfx::BufferFormat::RGBX_8888},
260 {WL_SHM_FORMAT_ABGR8888, gfx::BufferFormat::RGBA_8888},
261 {WL_SHM_FORMAT_XRGB8888, gfx::BufferFormat::BGRX_8888},
262 {WL_SHM_FORMAT_ARGB8888, gfx::BufferFormat::BGRA_8888}};
263
264 void shm_pool_create_buffer(wl_client* client,
265 wl_resource* resource,
266 uint32_t id,
267 int32_t offset,
268 int32_t width,
269 int32_t height,
270 int32_t stride,
271 uint32_t format) {
272 const auto supported_format =
273 std::find_if(shm_supported_formats,
274 shm_supported_formats + arraysize(shm_supported_formats),
275 [format](const shm_supported_format& supported_format) {
276 return supported_format.shm_format == format;
277 });
278 if (supported_format ==
279 (shm_supported_formats + arraysize(shm_supported_formats))) {
280 wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
281 "invalid format 0x%x", format);
282 return;
283 }
284
285 if (offset < 0) {
286 wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
287 "invalid offset %d", offset);
288 return;
289 }
290
291 scoped_ptr<Buffer> buffer =
292 GetUserDataAs<SharedMemory>(resource)
293 ->CreateBuffer(gfx::Size(width, height),
294 supported_format->buffer_format, offset, stride);
295 if (!buffer) {
296 wl_resource_post_no_memory(resource);
297 return;
298 }
299
300 wl_resource* buffer_resource =
301 wl_resource_create(client, &wl_buffer_interface, 1, id);
302 if (!buffer_resource) {
303 wl_resource_post_no_memory(resource);
304 return;
305 }
306
307 buffer->set_release_callback(
308 base::Bind(&wl_buffer_send_release, base::Unretained(buffer_resource)));
309
310 SetImplementation(buffer_resource, &buffer_implementation, buffer.Pass());
311 }
312
313 void shm_pool_destroy(wl_client* client, wl_resource* resource) {
314 wl_resource_destroy(resource);
315 }
316
317 void shm_pool_resize(wl_client* client, wl_resource* resource, int32_t size) {
318 // Nothing to do here.
319 }
320
321 const struct wl_shm_pool_interface shm_pool_implementation = {
322 shm_pool_create_buffer, shm_pool_destroy, shm_pool_resize};
323
324 ////////////////////////////////////////////////////////////////////////////////
325 // wl_shm_interface:
326
327 void shm_create_pool(wl_client* client,
328 wl_resource* resource,
329 uint32_t id,
330 int fd,
331 int32_t size) {
332 scoped_ptr<SharedMemory> shared_memory =
333 GetUserDataAs<Display>(resource)
334 ->CreateSharedMemory(base::FileDescriptor(fd, true), size);
335 if (!shared_memory) {
336 wl_resource_post_no_memory(resource);
337 return;
338 }
339
340 wl_resource* shm_pool_resource =
341 wl_resource_create(client, &wl_shm_pool_interface, 1, id);
342 if (!shm_pool_resource) {
343 wl_resource_post_no_memory(resource);
344 return;
345 }
346
347 SetImplementation(shm_pool_resource, &shm_pool_implementation,
348 shared_memory.Pass());
349 }
350
351 const struct wl_shm_interface shm_implementation = {shm_create_pool};
352
353 void bind_shm(wl_client* client, void* data, uint32_t version, uint32_t id) {
354 wl_resource* resource = wl_resource_create(client, &wl_shm_interface, 1, id);
355 if (!resource) {
356 wl_client_post_no_memory(client);
357 return;
358 }
359
360 wl_resource_set_implementation(resource, &shm_implementation, data, nullptr);
361
362 for (const auto& supported_format : shm_supported_formats)
363 wl_shm_send_format(resource, supported_format.shm_format);
364 }
365
366 ////////////////////////////////////////////////////////////////////////////////
367 // wl_shell_surface_interface:
368
369 void shell_surface_pong(wl_client* client,
370 wl_resource* resource,
371 uint32_t serial) {
372 NOTIMPLEMENTED();
373 }
374
375 void shell_surface_move(wl_client* client,
376 wl_resource* resource,
377 wl_resource* seat_resource,
378 uint32_t serial) {
379 NOTIMPLEMENTED();
380 }
381
382 void shell_surface_resize(wl_client* client,
383 wl_resource* resource,
384 wl_resource* seat_resource,
385 uint32_t serial,
386 uint32_t edges) {
387 NOTIMPLEMENTED();
388 }
389
390 void shell_surface_set_toplevel(wl_client* client, wl_resource* resource) {
391 GetUserDataAs<ShellSurface>(resource)->SetToplevel();
392 }
393
394 void shell_surface_set_transient(wl_client* client,
395 wl_resource* resource,
396 wl_resource* parent_resource,
397 int x,
398 int y,
399 uint32_t flags) {
400 NOTIMPLEMENTED();
401 }
402
403 void shell_surface_set_fullscreen(wl_client* client,
404 wl_resource* resource,
405 uint32_t method,
406 uint32_t framerate,
407 wl_resource* output_resource) {
408 GetUserDataAs<ShellSurface>(resource)->SetFullscreen(true);
409 }
410
411 void shell_surface_set_popup(wl_client* client,
412 wl_resource* resource,
413 wl_resource* seat_resource,
414 uint32_t serial,
415 wl_resource* parent_resource,
416 int32_t x,
417 int32_t y,
418 uint32_t flags) {
419 NOTIMPLEMENTED();
420 }
421
422 void shell_surface_set_maximized(wl_client* client,
423 wl_resource* resource,
424 wl_resource* output_resource) {
425 NOTIMPLEMENTED();
426 }
427
428 void shell_surface_set_title(wl_client* client,
429 wl_resource* resource,
430 const char* title) {
431 GetUserDataAs<ShellSurface>(resource)
432 ->SetTitle(base::string16(base::ASCIIToUTF16(title)));
433 }
434
435 void shell_surface_set_class(wl_client* client,
436 wl_resource* resource,
437 const char* clazz) {
438 NOTIMPLEMENTED();
439 }
440
441 const struct wl_shell_surface_interface shell_surface_implementation = {
442 shell_surface_pong, shell_surface_move,
443 shell_surface_resize, shell_surface_set_toplevel,
444 shell_surface_set_transient, shell_surface_set_fullscreen,
445 shell_surface_set_popup, shell_surface_set_maximized,
446 shell_surface_set_title, shell_surface_set_class};
447
448 ////////////////////////////////////////////////////////////////////////////////
449 // wl_shell_interface:
450
451 void shell_get_shell_surface(wl_client* client,
452 wl_resource* resource,
453 uint32_t id,
454 wl_resource* surface) {
455 scoped_ptr<ShellSurface> shell_surface =
456 GetUserDataAs<Display>(resource)
457 ->CreateShellSurface(GetUserDataAs<Surface>(surface));
458 if (!shell_surface) {
459 wl_resource_post_no_memory(resource);
460 return;
461 }
462
463 wl_resource* shell_surface_resource =
464 wl_resource_create(client, &wl_shell_surface_interface, 1, id);
465 if (!shell_surface_resource) {
466 wl_resource_post_no_memory(resource);
467 return;
468 }
469
470 SetImplementation(shell_surface_resource, &shell_surface_implementation,
471 shell_surface.Pass());
472 }
473
474 const struct wl_shell_interface shell_implementation = {
475 shell_get_shell_surface};
476
477 void bind_shell(wl_client* client, void* data, uint32_t version, uint32_t id) {
478 wl_resource* resource =
479 wl_resource_create(client, &wl_shell_interface, 1, id);
480 if (!resource) {
481 wl_client_post_no_memory(client);
482 return;
483 }
484 wl_resource_set_implementation(resource, &shell_implementation, data,
485 nullptr);
486 }
487
488 } // namespace
489
490 ////////////////////////////////////////////////////////////////////////////////
491 // Server, public:
492
493 Server::Server(Display* display)
494 : display_(display), wl_display_(wl_display_create()) {
495 wl_global_create(wl_display_.get(), &wl_compositor_interface,
496 compositor_version, display_, bind_compositor);
497 wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm);
498 wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
499 bind_shell);
500 }
501
502 Server::~Server() {}
503
504 // static
505 scoped_ptr<Server> Server::Create(Display* display) {
506 scoped_ptr<Server> server(new Server(display));
507 int rv = wl_display_add_socket(server->wl_display_.get(), nullptr);
508 DCHECK_EQ(rv, 0) << "wl_display_add_socket failed: " << rv;
509 return server;
510 }
511
512 bool Server::AddSocket(const std::string name) {
513 DCHECK(!name.empty());
514 return !wl_display_add_socket(wl_display_.get(), name.c_str());
515 }
516
517 int Server::GetFileDescriptor() const {
518 wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
519 DCHECK(event_loop);
520 return wl_event_loop_get_fd(event_loop);
521 }
522
523 void Server::Dispatch(base::TimeDelta timeout) {
524 wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
525 DCHECK(event_loop);
526 wl_event_loop_dispatch(event_loop, timeout.InMilliseconds());
527 }
528
529 void Server::Flush() {
530 wl_display_flush_clients(wl_display_.get());
531 }
532
533 } // namespace wayland
534 } // namespace exo
OLDNEW
« no previous file with comments | « components/exo/wayland/server.h ('k') | components/exo/wayland/server_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698