1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ScenicWindow.cpp:
7 // Implements methods from ScenicWindow
8 //
9
10 #include "util/fuchsia/ScenicWindow.h"
11
12 #include <fuchsia/images/cpp/fidl.h>
13 #include <fuchsia/ui/views/cpp/fidl.h>
14 #include <lib/async-loop/cpp/loop.h>
15 #include <lib/fdio/directory.h>
16 #include <lib/fidl/cpp/interface_ptr.h>
17 #include <lib/fidl/cpp/interface_request.h>
18 #include <lib/ui/scenic/cpp/view_token_pair.h>
19 #include <lib/zx/channel.h>
20 #include <zircon/status.h>
21
22 #include "common/debug.h"
23
24 namespace
25 {
26
GetDefaultLoop()27 async::Loop *GetDefaultLoop()
28 {
29 static async::Loop *defaultLoop = new async::Loop(&kAsyncLoopConfigAttachToThread);
30 return defaultLoop;
31 }
32
ConnectToServiceRoot()33 zx::channel ConnectToServiceRoot()
34 {
35 zx::channel clientChannel;
36 zx::channel serverChannel;
37 zx_status_t result = zx::channel::create(0, &clientChannel, &serverChannel);
38 ASSERT(result == ZX_OK);
39 result = fdio_service_connect("/svc/.", serverChannel.release());
40 ASSERT(result == ZX_OK);
41 return clientChannel;
42 }
43
44 template <typename Interface>
ConnectToService(zx_handle_t serviceRoot,fidl::InterfaceRequest<Interface> request)45 zx_status_t ConnectToService(zx_handle_t serviceRoot, fidl::InterfaceRequest<Interface> request)
46 {
47 ASSERT(request.is_valid());
48 return fdio_service_connect_at(serviceRoot, Interface::Name_, request.TakeChannel().release());
49 }
50
51 template <typename Interface>
ConnectToService(zx_handle_t serviceRoot)52 fidl::InterfacePtr<Interface> ConnectToService(zx_handle_t serviceRoot)
53 {
54 fidl::InterfacePtr<Interface> result;
55 ConnectToService(serviceRoot, result.NewRequest());
56 return result;
57 }
58
59 } // namespace
60
ScenicWindow()61 ScenicWindow::ScenicWindow()
62 : mLoop(GetDefaultLoop()),
63 mServiceRoot(ConnectToServiceRoot()),
64 mScenic(ConnectToService<fuchsia::ui::scenic::Scenic>(mServiceRoot.get())),
65 mPresenter(ConnectToService<fuchsia::ui::policy::Presenter>(mServiceRoot.get())),
66 mScenicSession(mScenic.get()),
67 mShape(&mScenicSession),
68 mMaterial(&mScenicSession)
69 {}
70
~ScenicWindow()71 ScenicWindow::~ScenicWindow()
72 {
73 destroy();
74 }
75
initialize(const std::string & name,int width,int height)76 bool ScenicWindow::initialize(const std::string &name, int width, int height)
77 {
78 // Set up scenic resources.
79 mShape.SetShape(scenic::Rectangle(&mScenicSession, width, height));
80 mShape.SetMaterial(mMaterial);
81
82 fuchsia::ui::views::ViewToken viewToken;
83 fuchsia::ui::views::ViewHolderToken viewHolderToken;
84 std::tie(viewToken, viewHolderToken) = scenic::NewViewTokenPair();
85
86 // Create view.
87 mView = std::make_unique<scenic::View>(&mScenicSession, std::move(viewToken), name);
88 mView->AddChild(mShape);
89 mScenicSession.Present(0, [](fuchsia::images::PresentationInfo info) {});
90
91 // Present view.
92 mPresenter->PresentView(std::move(viewHolderToken), nullptr);
93
94 mWidth = width;
95 mHeight = height;
96
97 resetNativeWindow();
98
99 return true;
100 }
101
destroy()102 void ScenicWindow::destroy()
103 {
104 mFuchsiaEGLWindow.reset();
105 }
106
resetNativeWindow()107 void ScenicWindow::resetNativeWindow()
108 {
109 fuchsia::images::ImagePipePtr imagePipe;
110 uint32_t imagePipeId = mScenicSession.AllocResourceId();
111 mScenicSession.Enqueue(scenic::NewCreateImagePipeCmd(imagePipeId, imagePipe.NewRequest()));
112 mMaterial.SetTexture(imagePipeId);
113 mScenicSession.ReleaseResource(imagePipeId);
114 mScenicSession.Present(0, [](fuchsia::images::PresentationInfo info) {});
115
116 mFuchsiaEGLWindow.reset(
117 fuchsia_egl_window_create(imagePipe.Unbind().TakeChannel().release(), mWidth, mHeight));
118 }
119
getNativeWindow() const120 EGLNativeWindowType ScenicWindow::getNativeWindow() const
121 {
122 return reinterpret_cast<EGLNativeWindowType>(mFuchsiaEGLWindow.get());
123 }
124
getNativeDisplay() const125 EGLNativeDisplayType ScenicWindow::getNativeDisplay() const
126 {
127 return EGL_DEFAULT_DISPLAY;
128 }
129
messageLoop()130 void ScenicWindow::messageLoop()
131 {
132 mLoop->Run(zx::deadline_after({}), true /* once */);
133 }
134
setMousePosition(int x,int y)135 void ScenicWindow::setMousePosition(int x, int y)
136 {
137 UNIMPLEMENTED();
138 }
139
setPosition(int x,int y)140 bool ScenicWindow::setPosition(int x, int y)
141 {
142 UNIMPLEMENTED();
143 return false;
144 }
145
resize(int width,int height)146 bool ScenicWindow::resize(int width, int height)
147 {
148 mWidth = width;
149 mHeight = height;
150
151 fuchsia_egl_window_resize(mFuchsiaEGLWindow.get(), width, height);
152
153 return true;
154 }
155
setVisible(bool isVisible)156 void ScenicWindow::setVisible(bool isVisible) {}
157
signalTestEvent()158 void ScenicWindow::signalTestEvent() {}
159
OnScenicEvents(std::vector<fuchsia::ui::scenic::Event> events)160 void ScenicWindow::OnScenicEvents(std::vector<fuchsia::ui::scenic::Event> events)
161 {
162 UNIMPLEMENTED();
163 }
164
OnScenicError(zx_status_t status)165 void ScenicWindow::OnScenicError(zx_status_t status)
166 {
167 WARN() << "OnScenicError: " << zx_status_get_string(status);
168 }
169
170 // static
New()171 OSWindow *OSWindow::New()
172 {
173 return new ScenicWindow;
174 }
175