Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/fuchsia/ScenicWindow.cpp
1693 views
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/async-loop/default.h>
16
#include <lib/fdio/directory.h>
17
#include <lib/fidl/cpp/interface_ptr.h>
18
#include <lib/fidl/cpp/interface_request.h>
19
#include <lib/ui/scenic/cpp/view_token_pair.h>
20
#include <lib/zx/channel.h>
21
#include <zircon/status.h>
22
23
namespace
24
{
25
26
async::Loop *GetDefaultLoop()
27
{
28
static async::Loop *defaultLoop = new async::Loop(&kAsyncLoopConfigNeverAttachToThread);
29
return defaultLoop;
30
}
31
32
zx::channel ConnectToServiceRoot()
33
{
34
zx::channel clientChannel;
35
zx::channel serverChannel;
36
zx_status_t result = zx::channel::create(0, &clientChannel, &serverChannel);
37
ASSERT(result == ZX_OK);
38
result = fdio_service_connect("/svc/.", serverChannel.release());
39
ASSERT(result == ZX_OK);
40
return clientChannel;
41
}
42
43
template <typename Interface>
44
zx_status_t ConnectToService(zx_handle_t serviceRoot, fidl::InterfaceRequest<Interface> request)
45
{
46
ASSERT(request.is_valid());
47
return fdio_service_connect_at(serviceRoot, Interface::Name_, request.TakeChannel().release());
48
}
49
50
template <typename Interface>
51
fidl::InterfacePtr<Interface> ConnectToService(zx_handle_t serviceRoot,
52
async_dispatcher_t *dispatcher)
53
{
54
fidl::InterfacePtr<Interface> result;
55
ConnectToService(serviceRoot, result.NewRequest(dispatcher));
56
return result;
57
}
58
59
} // namespace
60
61
ScenicWindow::ScenicWindow()
62
: mLoop(GetDefaultLoop()),
63
mServiceRoot(ConnectToServiceRoot()),
64
mScenic(
65
ConnectToService<fuchsia::ui::scenic::Scenic>(mServiceRoot.get(), mLoop->dispatcher())),
66
mPresenter(ConnectToService<fuchsia::ui::policy::Presenter>(mServiceRoot.get(),
67
mLoop->dispatcher())),
68
mScenicSession(mScenic.get(), mLoop->dispatcher()),
69
mShape(&mScenicSession),
70
mMaterial(&mScenicSession)
71
{
72
mScenicSession.set_error_handler(fit::bind_member(this, &ScenicWindow::onScenicError));
73
mScenicSession.set_event_handler(fit::bind_member(this, &ScenicWindow::onScenicEvents));
74
mScenicSession.set_on_frame_presented_handler(
75
fit::bind_member(this, &ScenicWindow::onFramePresented));
76
}
77
78
ScenicWindow::~ScenicWindow()
79
{
80
destroy();
81
}
82
83
bool ScenicWindow::initializeImpl(const std::string &name, int width, int height)
84
{
85
// Set up scenic resources.
86
mShape.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
87
mShape.SetMaterial(mMaterial);
88
89
fuchsia::ui::views::ViewToken viewToken;
90
fuchsia::ui::views::ViewHolderToken viewHolderToken;
91
std::tie(viewToken, viewHolderToken) = scenic::NewViewTokenPair();
92
93
// Create view.
94
mView = std::make_unique<scenic::View>(&mScenicSession, std::move(viewToken), name);
95
mView->AddChild(mShape);
96
97
// Present view.
98
mPresenter->PresentOrReplaceView(std::move(viewHolderToken), nullptr);
99
100
mWidth = width;
101
mHeight = height;
102
103
resetNativeWindow();
104
105
// Block until initial view dimensions are known.
106
while (!mHasViewMetrics && !mHasViewProperties && !mLostSession)
107
{
108
mLoop->ResetQuit();
109
mLoop->Run(zx::time::infinite(), true /* once */);
110
}
111
112
return true;
113
}
114
115
void ScenicWindow::disableErrorMessageDialog() {}
116
117
void ScenicWindow::destroy()
118
{
119
while (mInFlightPresents != 0 && !mLostSession)
120
{
121
mLoop->ResetQuit();
122
mLoop->Run();
123
}
124
125
ASSERT(mInFlightPresents == 0 || mLostSession);
126
127
mFuchsiaEGLWindow.reset();
128
}
129
130
void ScenicWindow::resetNativeWindow()
131
{
132
fuchsia::images::ImagePipe2Ptr imagePipe;
133
uint32_t imagePipeId = mScenicSession.AllocResourceId();
134
mScenicSession.Enqueue(
135
scenic::NewCreateImagePipe2Cmd(imagePipeId, imagePipe.NewRequest(mLoop->dispatcher())));
136
zx_handle_t imagePipeHandle = imagePipe.Unbind().TakeChannel().release();
137
138
mMaterial.SetTexture(imagePipeId);
139
mScenicSession.ReleaseResource(imagePipeId);
140
present();
141
142
mFuchsiaEGLWindow.reset(fuchsia_egl_window_create(imagePipeHandle, mWidth, mHeight));
143
}
144
145
EGLNativeWindowType ScenicWindow::getNativeWindow() const
146
{
147
return reinterpret_cast<EGLNativeWindowType>(mFuchsiaEGLWindow.get());
148
}
149
150
EGLNativeDisplayType ScenicWindow::getNativeDisplay() const
151
{
152
return EGL_DEFAULT_DISPLAY;
153
}
154
155
void ScenicWindow::messageLoop()
156
{
157
mLoop->ResetQuit();
158
mLoop->RunUntilIdle();
159
}
160
161
void ScenicWindow::setMousePosition(int x, int y)
162
{
163
UNIMPLEMENTED();
164
}
165
166
bool ScenicWindow::setOrientation(int width, int height)
167
{
168
UNIMPLEMENTED();
169
return false;
170
}
171
172
bool ScenicWindow::setPosition(int x, int y)
173
{
174
UNIMPLEMENTED();
175
return false;
176
}
177
178
bool ScenicWindow::resize(int width, int height)
179
{
180
mWidth = width;
181
mHeight = height;
182
183
fuchsia_egl_window_resize(mFuchsiaEGLWindow.get(), width, height);
184
185
mViewSizeDirty = true;
186
187
updateViewSize();
188
189
return true;
190
}
191
192
void ScenicWindow::setVisible(bool isVisible) {}
193
194
void ScenicWindow::signalTestEvent() {}
195
196
void ScenicWindow::present()
197
{
198
while (mInFlightPresents >= kMaxInFlightPresents && !mLostSession)
199
{
200
mLoop->ResetQuit();
201
mLoop->Run();
202
}
203
204
if (mLostSession)
205
{
206
return;
207
}
208
209
ASSERT(mInFlightPresents < kMaxInFlightPresents);
210
211
++mInFlightPresents;
212
mScenicSession.Present2(0, 0, [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {});
213
}
214
215
void ScenicWindow::onFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info)
216
{
217
mInFlightPresents -= info.presentation_infos.size();
218
ASSERT(mInFlightPresents >= 0);
219
mLoop->Quit();
220
}
221
222
void ScenicWindow::onScenicEvents(std::vector<fuchsia::ui::scenic::Event> events)
223
{
224
for (const auto &event : events)
225
{
226
if (event.is_gfx())
227
{
228
if (event.gfx().is_metrics())
229
{
230
if (event.gfx().metrics().node_id != mShape.id())
231
continue;
232
onViewMetrics(event.gfx().metrics().metrics);
233
}
234
else if (event.gfx().is_view_properties_changed())
235
{
236
if (event.gfx().view_properties_changed().view_id != mView->id())
237
continue;
238
onViewProperties(event.gfx().view_properties_changed().properties);
239
}
240
}
241
}
242
243
if (mViewSizeDirty)
244
{
245
updateViewSize();
246
}
247
}
248
249
void ScenicWindow::onScenicError(zx_status_t status)
250
{
251
WARN() << "OnScenicError: " << zx_status_get_string(status);
252
mLostSession = true;
253
mLoop->Quit();
254
}
255
256
void ScenicWindow::onViewMetrics(const fuchsia::ui::gfx::Metrics &metrics)
257
{
258
mDisplayScaleX = metrics.scale_x;
259
mDisplayScaleY = metrics.scale_y;
260
261
mHasViewMetrics = true;
262
mViewSizeDirty = true;
263
}
264
265
void ScenicWindow::onViewProperties(const fuchsia::ui::gfx::ViewProperties &properties)
266
{
267
float width = properties.bounding_box.max.x - properties.bounding_box.min.x -
268
properties.inset_from_min.x - properties.inset_from_max.x;
269
float height = properties.bounding_box.max.y - properties.bounding_box.min.y -
270
properties.inset_from_min.y - properties.inset_from_max.y;
271
272
mDisplayWidthDips = width;
273
mDisplayHeightDips = height;
274
275
mHasViewProperties = true;
276
mViewSizeDirty = true;
277
}
278
279
void ScenicWindow::updateViewSize()
280
{
281
if (!mViewSizeDirty || !mHasViewMetrics || !mHasViewProperties)
282
{
283
return;
284
}
285
286
mViewSizeDirty = false;
287
288
// Surface size in pixels is
289
// (mWidth, mHeight)
290
//
291
// View size in pixels is
292
// (mDisplayWidthDips * mDisplayScaleX) x (mDisplayHeightDips * mDisplayScaleY)
293
294
float widthDips = mWidth / mDisplayScaleX;
295
float heightDips = mHeight / mDisplayScaleY;
296
297
mShape.SetShape(scenic::Rectangle(&mScenicSession, widthDips, heightDips));
298
mShape.SetTranslation(0.5f * widthDips, 0.5f * heightDips, 0.f);
299
present();
300
}
301
302
// static
303
OSWindow *OSWindow::New()
304
{
305
return new ScenicWindow;
306
}
307
308