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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/wayland/server.cc
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d5efe2201f46082e09c20264f02dfa84a46cd8fe
--- /dev/null
+++ b/components/exo/wayland/server.cc
@@ -0,0 +1,534 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/wayland/server.h"
+
+#include <wayland-server-core.h>
+#include <wayland-server-protocol-core.h>
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/cancelable_callback.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/exo/buffer.h"
+#include "components/exo/display.h"
+#include "components/exo/shared_memory.h"
+#include "components/exo/shell_surface.h"
+#include "components/exo/surface.h"
+#include "third_party/skia/include/core/SkRegion.h"
+
+namespace exo {
+namespace wayland {
+namespace {
+
+template <class T>
+T* GetUserDataAs(wl_resource* resource) {
+ return static_cast<T*>(wl_resource_get_user_data(resource));
+}
+
+template <class T>
+scoped_ptr<T> TakeUserDataAs(wl_resource* resource) {
+ scoped_ptr<T> user_data = make_scoped_ptr(GetUserDataAs<T>(resource));
+ wl_resource_set_user_data(resource, nullptr);
+ return user_data.Pass();
+}
+
+template <class T>
+void DestroyUserData(wl_resource* resource) {
+ TakeUserDataAs<T>(resource);
+}
+
+template <class T>
+void SetImplementation(wl_resource* resource,
+ const void* implementation,
+ scoped_ptr<T> user_data) {
+ wl_resource_set_implementation(resource, implementation, user_data.release(),
+ DestroyUserData<T>);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_buffer_interface:
+
+void buffer_destroy(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+const struct wl_buffer_interface buffer_implementation = {buffer_destroy};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_surface_interface:
+
+void surface_destroy(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+void surface_attach(wl_client* client,
+ wl_resource* resource,
+ wl_resource* buffer,
+ int32_t x,
+ int32_t y) {
+ // TODO(reveman): Implement buffer offset support.
+ if (x || y) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ GetUserDataAs<Surface>(resource)
+ ->Attach(buffer ? GetUserDataAs<Buffer>(buffer) : nullptr);
+}
+
+void surface_damage(wl_client* client,
+ wl_resource* resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ GetUserDataAs<Surface>(resource)->Damage(gfx::Rect(x, y, width, height));
+}
+
+void handle_surface_frame_callback(wl_resource* resource,
+ base::TimeTicks frame_time) {
+ if (!frame_time.is_null()) {
+ wl_callback_send_done(resource,
+ (frame_time - base::TimeTicks()).InMilliseconds());
+ // TODO(reveman): Remove this potentially blocking flush and instead watch
+ // the file descriptor to be ready for write without blocking.
+ wl_client_flush(wl_resource_get_client(resource));
+ }
+ wl_resource_destroy(resource);
+}
+
+void surface_frame(wl_client* client,
+ wl_resource* resource,
+ uint32_t callback) {
+ wl_resource* callback_resource =
+ wl_resource_create(client, &wl_callback_interface, 1, callback);
+ if (!callback_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ // base::Unretained is safe as the resource owns the callback.
+ scoped_ptr<base::CancelableCallback<void(base::TimeTicks)>>
+ cancelable_callback(new base::CancelableCallback<void(base::TimeTicks)>(
+ base::Bind(&handle_surface_frame_callback,
+ base::Unretained(callback_resource))));
+
+ GetUserDataAs<Surface>(resource)
+ ->RequestFrameCallback(cancelable_callback->callback());
+
+ SetImplementation(callback_resource, nullptr, cancelable_callback.Pass());
+}
+
+void surface_set_opaque_region(wl_client* client,
+ wl_resource* resource,
+ wl_resource* region_resource) {
+ GetUserDataAs<Surface>(resource)->SetOpaqueRegion(
+ region_resource ? *GetUserDataAs<SkRegion>(region_resource)
+ : SkRegion(SkIRect::MakeEmpty()));
+}
+
+void surface_set_input_region(wl_client* client,
+ wl_resource* resource,
+ wl_resource* region_resource) {
+ NOTIMPLEMENTED();
+}
+
+void surface_commit(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<Surface>(resource)->Commit();
+}
+
+void surface_set_buffer_transform(wl_client* client,
+ wl_resource* resource,
+ int transform) {
+ NOTIMPLEMENTED();
+}
+
+void surface_set_buffer_scale(wl_client* client,
+ wl_resource* resource,
+ int32_t scale) {
+ NOTIMPLEMENTED();
+}
+
+const struct wl_surface_interface surface_implementation = {
+ surface_destroy,
+ surface_attach,
+ surface_damage,
+ surface_frame,
+ surface_set_opaque_region,
+ surface_set_input_region,
+ surface_commit,
+ surface_set_buffer_transform,
+ surface_set_buffer_scale};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_region_interface:
+
+void region_destroy(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+void region_add(wl_client* client,
+ wl_resource* resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ GetUserDataAs<SkRegion>(resource)
+ ->op(SkIRect::MakeXYWH(x, y, width, height), SkRegion::kUnion_Op);
+}
+
+static void region_subtract(wl_client* client,
+ wl_resource* resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ GetUserDataAs<SkRegion>(resource)
+ ->op(SkIRect::MakeXYWH(x, y, width, height), SkRegion::kDifference_Op);
+}
+
+const struct wl_region_interface region_implementation = {
+ region_destroy, region_add, region_subtract};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_compositor_interface:
+
+void compositor_create_surface(wl_client* client,
+ wl_resource* resource,
+ uint32_t id) {
+ scoped_ptr<Surface> surface =
+ GetUserDataAs<Display>(resource)->CreateSurface();
+ DCHECK(surface);
+
+ wl_resource* surface_resource = wl_resource_create(
+ client, &wl_surface_interface, wl_resource_get_version(resource), id);
+ if (!surface_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ SetImplementation(surface_resource, &surface_implementation, surface.Pass());
+}
+
+void compositor_create_region(wl_client* client,
+ wl_resource* resource,
+ uint32_t id) {
+ scoped_ptr<SkRegion> region(new SkRegion);
+
+ wl_resource* region_resource =
+ wl_resource_create(client, &wl_region_interface, 1, id);
+ if (!region_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ SetImplementation(region_resource, &region_implementation, region.Pass());
+}
+
+const struct wl_compositor_interface compositor_implementation = {
+ compositor_create_surface, compositor_create_region};
+
+const uint32_t compositor_version = 3;
+
+void bind_compositor(wl_client* client,
+ void* data,
+ uint32_t version,
+ uint32_t id) {
+ wl_resource* resource =
+ wl_resource_create(client, &wl_compositor_interface,
+ std::min(version, compositor_version), id);
+ if (!resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &compositor_implementation, data,
+ nullptr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_shm_pool_interface:
+
+const struct shm_supported_format {
+ uint32_t shm_format;
+ gfx::BufferFormat buffer_format;
+} shm_supported_formats[] = {
+ {WL_SHM_FORMAT_XBGR8888, gfx::BufferFormat::RGBX_8888},
+ {WL_SHM_FORMAT_ABGR8888, gfx::BufferFormat::RGBA_8888},
+ {WL_SHM_FORMAT_XRGB8888, gfx::BufferFormat::BGRX_8888},
+ {WL_SHM_FORMAT_ARGB8888, gfx::BufferFormat::BGRA_8888}};
+
+void shm_pool_create_buffer(wl_client* client,
+ wl_resource* resource,
+ uint32_t id,
+ int32_t offset,
+ int32_t width,
+ int32_t height,
+ int32_t stride,
+ uint32_t format) {
+ const auto supported_format =
+ std::find_if(shm_supported_formats,
+ shm_supported_formats + arraysize(shm_supported_formats),
+ [format](const shm_supported_format& supported_format) {
+ return supported_format.shm_format == format;
+ });
+ if (supported_format ==
+ (shm_supported_formats + arraysize(shm_supported_formats))) {
+ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
+ "invalid format 0x%x", format);
+ return;
+ }
+
+ if (offset < 0) {
+ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
+ "invalid offset %d", offset);
+ return;
+ }
+
+ scoped_ptr<Buffer> buffer =
+ GetUserDataAs<SharedMemory>(resource)
+ ->CreateBuffer(gfx::Size(width, height),
+ supported_format->buffer_format, offset, stride);
+ if (!buffer) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource* buffer_resource =
+ wl_resource_create(client, &wl_buffer_interface, 1, id);
+ if (!buffer_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ buffer->set_release_callback(
+ base::Bind(&wl_buffer_send_release, base::Unretained(buffer_resource)));
+
+ SetImplementation(buffer_resource, &buffer_implementation, buffer.Pass());
+}
+
+void shm_pool_destroy(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+void shm_pool_resize(wl_client* client, wl_resource* resource, int32_t size) {
+ // Nothing to do here.
+}
+
+const struct wl_shm_pool_interface shm_pool_implementation = {
+ shm_pool_create_buffer, shm_pool_destroy, shm_pool_resize};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_shm_interface:
+
+void shm_create_pool(wl_client* client,
+ wl_resource* resource,
+ uint32_t id,
+ int fd,
+ int32_t size) {
+ scoped_ptr<SharedMemory> shared_memory =
+ GetUserDataAs<Display>(resource)
+ ->CreateSharedMemory(base::FileDescriptor(fd, true), size);
+ if (!shared_memory) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource* shm_pool_resource =
+ wl_resource_create(client, &wl_shm_pool_interface, 1, id);
+ if (!shm_pool_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ SetImplementation(shm_pool_resource, &shm_pool_implementation,
+ shared_memory.Pass());
+}
+
+const struct wl_shm_interface shm_implementation = {shm_create_pool};
+
+void bind_shm(wl_client* client, void* data, uint32_t version, uint32_t id) {
+ wl_resource* resource = wl_resource_create(client, &wl_shm_interface, 1, id);
+ if (!resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &shm_implementation, data, nullptr);
+
+ for (const auto& supported_format : shm_supported_formats)
+ wl_shm_send_format(resource, supported_format.shm_format);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_shell_surface_interface:
+
+void shell_surface_pong(wl_client* client,
+ wl_resource* resource,
+ uint32_t serial) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_move(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat_resource,
+ uint32_t serial) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_resize(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat_resource,
+ uint32_t serial,
+ uint32_t edges) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_set_toplevel(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<ShellSurface>(resource)->SetToplevel();
+}
+
+void shell_surface_set_transient(wl_client* client,
+ wl_resource* resource,
+ wl_resource* parent_resource,
+ int x,
+ int y,
+ uint32_t flags) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_set_fullscreen(wl_client* client,
+ wl_resource* resource,
+ uint32_t method,
+ uint32_t framerate,
+ wl_resource* output_resource) {
+ GetUserDataAs<ShellSurface>(resource)->SetFullscreen(true);
+}
+
+void shell_surface_set_popup(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat_resource,
+ uint32_t serial,
+ wl_resource* parent_resource,
+ int32_t x,
+ int32_t y,
+ uint32_t flags) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_set_maximized(wl_client* client,
+ wl_resource* resource,
+ wl_resource* output_resource) {
+ NOTIMPLEMENTED();
+}
+
+void shell_surface_set_title(wl_client* client,
+ wl_resource* resource,
+ const char* title) {
+ GetUserDataAs<ShellSurface>(resource)
+ ->SetTitle(base::string16(base::ASCIIToUTF16(title)));
+}
+
+void shell_surface_set_class(wl_client* client,
+ wl_resource* resource,
+ const char* clazz) {
+ NOTIMPLEMENTED();
+}
+
+const struct wl_shell_surface_interface shell_surface_implementation = {
+ shell_surface_pong, shell_surface_move,
+ shell_surface_resize, shell_surface_set_toplevel,
+ shell_surface_set_transient, shell_surface_set_fullscreen,
+ shell_surface_set_popup, shell_surface_set_maximized,
+ shell_surface_set_title, shell_surface_set_class};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_shell_interface:
+
+void shell_get_shell_surface(wl_client* client,
+ wl_resource* resource,
+ uint32_t id,
+ wl_resource* surface) {
+ scoped_ptr<ShellSurface> shell_surface =
+ GetUserDataAs<Display>(resource)
+ ->CreateShellSurface(GetUserDataAs<Surface>(surface));
+ if (!shell_surface) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource* shell_surface_resource =
+ wl_resource_create(client, &wl_shell_surface_interface, 1, id);
+ if (!shell_surface_resource) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ SetImplementation(shell_surface_resource, &shell_surface_implementation,
+ shell_surface.Pass());
+}
+
+const struct wl_shell_interface shell_implementation = {
+ shell_get_shell_surface};
+
+void bind_shell(wl_client* client, void* data, uint32_t version, uint32_t id) {
+ wl_resource* resource =
+ wl_resource_create(client, &wl_shell_interface, 1, id);
+ if (!resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(resource, &shell_implementation, data,
+ nullptr);
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// Server, public:
+
+Server::Server(Display* display)
+ : display_(display), wl_display_(wl_display_create()) {
+ wl_global_create(wl_display_.get(), &wl_compositor_interface,
+ compositor_version, display_, bind_compositor);
+ wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm);
+ wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_,
+ bind_shell);
+}
+
+Server::~Server() {}
+
+// static
+scoped_ptr<Server> Server::Create(Display* display) {
+ scoped_ptr<Server> server(new Server(display));
+ int rv = wl_display_add_socket(server->wl_display_.get(), nullptr);
+ DCHECK_EQ(rv, 0) << "wl_display_add_socket failed: " << rv;
+ return server;
+}
+
+bool Server::AddSocket(const std::string name) {
+ DCHECK(!name.empty());
+ return !wl_display_add_socket(wl_display_.get(), name.c_str());
+}
+
+int Server::GetFileDescriptor() const {
+ wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
+ DCHECK(event_loop);
+ return wl_event_loop_get_fd(event_loop);
+}
+
+void Server::Dispatch(base::TimeDelta timeout) {
+ wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get());
+ DCHECK(event_loop);
+ wl_event_loop_dispatch(event_loop, timeout.InMilliseconds());
+}
+
+void Server::Flush() {
+ wl_display_flush_clients(wl_display_.get());
+}
+
+} // namespace wayland
+} // namespace exo
« 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