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_server.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_compositor.h"
25 #include "host/libs/wayland/wayland_dmabuf.h"
26 #include "host/libs/wayland/wayland_seat.h"
27 #include "host/libs/wayland/wayland_shell.h"
28 #include "host/libs/wayland/wayland_subcompositor.h"
29 #include "host/libs/wayland/wayland_surface.h"
30 #include "host/libs/wayland/wayland_utils.h"
31 
32 namespace wayland {
33 namespace internal {
34 
35 struct WaylandServerState {
36   struct wl_display* display_ = nullptr;
37 
38   Surface surface_;
39 };
40 
41 }  // namespace internal
42 
WaylandServer(int wayland_socket_fd)43 WaylandServer::WaylandServer(int wayland_socket_fd) {
44   server_thread_ =
45       std::thread(
46           [this, wayland_socket_fd]() {
47             ServerLoop(wayland_socket_fd);
48           });
49 
50   std::unique_lock<std::mutex> lock(server_ready_mutex_);
51   server_ready_cv_.wait(lock, [&]{return server_ready_; });
52 }
53 
~WaylandServer()54 WaylandServer::~WaylandServer() {
55   wl_display_terminate(server_state_->display_);
56   server_thread_.join();
57 }
58 
ServerLoop(int fd)59 void WaylandServer::ServerLoop(int fd) {
60   server_state_.reset(new internal::WaylandServerState());
61 
62   server_state_->display_ = wl_display_create();
63   CHECK(server_state_->display_ != nullptr)
64     << "Failed to start WaylandServer: failed to create display";
65 
66   if (fd < 0) {
67     const char* socket = wl_display_add_socket_auto(server_state_->display_);
68     CHECK(socket != nullptr)
69         << "Failed to start WaylandServer: failed to create socket";
70 
71     LOG(INFO) << "WaylandServer running on socket " << socket;
72   } else {
73     CHECK(wl_display_add_socket_fd(server_state_->display_, fd) == 0)
74         << "Failed to start WaylandServer: failed to use fd " << fd;
75 
76     LOG(INFO) << "WaylandServer running on socket " << fd;
77   }
78 
79   wl_display_init_shm(server_state_->display_);
80 
81   BindCompositorInterface(server_state_->display_, &server_state_->surface_);
82   BindDmabufInterface(server_state_->display_);
83   BindSubcompositorInterface(server_state_->display_);
84   BindSeatInterface(server_state_->display_);
85   BindShellInterface(server_state_->display_);
86 
87   {
88     std::lock_guard<std::mutex> lock(server_ready_mutex_);
89     server_ready_ = true;
90   }
91   server_ready_cv_.notify_one();
92 
93   wl_display_run(server_state_->display_);
94   wl_display_destroy(server_state_->display_);
95 }
96 
OnFrameAfter(uint32_t frame_number,const FrameCallback & frame_callback)97 std::future<void> WaylandServer::OnFrameAfter(
98     uint32_t frame_number,
99     const FrameCallback& frame_callback) {
100   // Wraps the given callback in a callback that can be waited on using
101   // std::future.
102   Surface::FrameCallbackPackaged packaged([&frame_callback](std::uint32_t frame_number,
103                                                    std::uint8_t* frame_pixels){
104     frame_callback(frame_number, frame_pixels);
105   });
106 
107   std::future<void> frame_callback_complete = packaged.get_future();
108 
109   server_state_->surface_.OnFrameAfter(frame_number, std::move(packaged));
110   return frame_callback_complete;
111 }
112 
113 }  // namespace wayland