Path: blob/main_old/util/fuchsia/ScenicWindow.cpp
1693 views
//1// Copyright 2019 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// ScenicWindow.cpp:6// Implements methods from ScenicWindow7//89#include "util/fuchsia/ScenicWindow.h"1011#include <fuchsia/images/cpp/fidl.h>12#include <fuchsia/ui/views/cpp/fidl.h>13#include <lib/async-loop/cpp/loop.h>14#include <lib/async-loop/default.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>2122namespace23{2425async::Loop *GetDefaultLoop()26{27static async::Loop *defaultLoop = new async::Loop(&kAsyncLoopConfigNeverAttachToThread);28return defaultLoop;29}3031zx::channel ConnectToServiceRoot()32{33zx::channel clientChannel;34zx::channel serverChannel;35zx_status_t result = zx::channel::create(0, &clientChannel, &serverChannel);36ASSERT(result == ZX_OK);37result = fdio_service_connect("/svc/.", serverChannel.release());38ASSERT(result == ZX_OK);39return clientChannel;40}4142template <typename Interface>43zx_status_t ConnectToService(zx_handle_t serviceRoot, fidl::InterfaceRequest<Interface> request)44{45ASSERT(request.is_valid());46return fdio_service_connect_at(serviceRoot, Interface::Name_, request.TakeChannel().release());47}4849template <typename Interface>50fidl::InterfacePtr<Interface> ConnectToService(zx_handle_t serviceRoot,51async_dispatcher_t *dispatcher)52{53fidl::InterfacePtr<Interface> result;54ConnectToService(serviceRoot, result.NewRequest(dispatcher));55return result;56}5758} // namespace5960ScenicWindow::ScenicWindow()61: mLoop(GetDefaultLoop()),62mServiceRoot(ConnectToServiceRoot()),63mScenic(64ConnectToService<fuchsia::ui::scenic::Scenic>(mServiceRoot.get(), mLoop->dispatcher())),65mPresenter(ConnectToService<fuchsia::ui::policy::Presenter>(mServiceRoot.get(),66mLoop->dispatcher())),67mScenicSession(mScenic.get(), mLoop->dispatcher()),68mShape(&mScenicSession),69mMaterial(&mScenicSession)70{71mScenicSession.set_error_handler(fit::bind_member(this, &ScenicWindow::onScenicError));72mScenicSession.set_event_handler(fit::bind_member(this, &ScenicWindow::onScenicEvents));73mScenicSession.set_on_frame_presented_handler(74fit::bind_member(this, &ScenicWindow::onFramePresented));75}7677ScenicWindow::~ScenicWindow()78{79destroy();80}8182bool ScenicWindow::initializeImpl(const std::string &name, int width, int height)83{84// Set up scenic resources.85mShape.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);86mShape.SetMaterial(mMaterial);8788fuchsia::ui::views::ViewToken viewToken;89fuchsia::ui::views::ViewHolderToken viewHolderToken;90std::tie(viewToken, viewHolderToken) = scenic::NewViewTokenPair();9192// Create view.93mView = std::make_unique<scenic::View>(&mScenicSession, std::move(viewToken), name);94mView->AddChild(mShape);9596// Present view.97mPresenter->PresentOrReplaceView(std::move(viewHolderToken), nullptr);9899mWidth = width;100mHeight = height;101102resetNativeWindow();103104// Block until initial view dimensions are known.105while (!mHasViewMetrics && !mHasViewProperties && !mLostSession)106{107mLoop->ResetQuit();108mLoop->Run(zx::time::infinite(), true /* once */);109}110111return true;112}113114void ScenicWindow::disableErrorMessageDialog() {}115116void ScenicWindow::destroy()117{118while (mInFlightPresents != 0 && !mLostSession)119{120mLoop->ResetQuit();121mLoop->Run();122}123124ASSERT(mInFlightPresents == 0 || mLostSession);125126mFuchsiaEGLWindow.reset();127}128129void ScenicWindow::resetNativeWindow()130{131fuchsia::images::ImagePipe2Ptr imagePipe;132uint32_t imagePipeId = mScenicSession.AllocResourceId();133mScenicSession.Enqueue(134scenic::NewCreateImagePipe2Cmd(imagePipeId, imagePipe.NewRequest(mLoop->dispatcher())));135zx_handle_t imagePipeHandle = imagePipe.Unbind().TakeChannel().release();136137mMaterial.SetTexture(imagePipeId);138mScenicSession.ReleaseResource(imagePipeId);139present();140141mFuchsiaEGLWindow.reset(fuchsia_egl_window_create(imagePipeHandle, mWidth, mHeight));142}143144EGLNativeWindowType ScenicWindow::getNativeWindow() const145{146return reinterpret_cast<EGLNativeWindowType>(mFuchsiaEGLWindow.get());147}148149EGLNativeDisplayType ScenicWindow::getNativeDisplay() const150{151return EGL_DEFAULT_DISPLAY;152}153154void ScenicWindow::messageLoop()155{156mLoop->ResetQuit();157mLoop->RunUntilIdle();158}159160void ScenicWindow::setMousePosition(int x, int y)161{162UNIMPLEMENTED();163}164165bool ScenicWindow::setOrientation(int width, int height)166{167UNIMPLEMENTED();168return false;169}170171bool ScenicWindow::setPosition(int x, int y)172{173UNIMPLEMENTED();174return false;175}176177bool ScenicWindow::resize(int width, int height)178{179mWidth = width;180mHeight = height;181182fuchsia_egl_window_resize(mFuchsiaEGLWindow.get(), width, height);183184mViewSizeDirty = true;185186updateViewSize();187188return true;189}190191void ScenicWindow::setVisible(bool isVisible) {}192193void ScenicWindow::signalTestEvent() {}194195void ScenicWindow::present()196{197while (mInFlightPresents >= kMaxInFlightPresents && !mLostSession)198{199mLoop->ResetQuit();200mLoop->Run();201}202203if (mLostSession)204{205return;206}207208ASSERT(mInFlightPresents < kMaxInFlightPresents);209210++mInFlightPresents;211mScenicSession.Present2(0, 0, [](fuchsia::scenic::scheduling::FuturePresentationTimes info) {});212}213214void ScenicWindow::onFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info)215{216mInFlightPresents -= info.presentation_infos.size();217ASSERT(mInFlightPresents >= 0);218mLoop->Quit();219}220221void ScenicWindow::onScenicEvents(std::vector<fuchsia::ui::scenic::Event> events)222{223for (const auto &event : events)224{225if (event.is_gfx())226{227if (event.gfx().is_metrics())228{229if (event.gfx().metrics().node_id != mShape.id())230continue;231onViewMetrics(event.gfx().metrics().metrics);232}233else if (event.gfx().is_view_properties_changed())234{235if (event.gfx().view_properties_changed().view_id != mView->id())236continue;237onViewProperties(event.gfx().view_properties_changed().properties);238}239}240}241242if (mViewSizeDirty)243{244updateViewSize();245}246}247248void ScenicWindow::onScenicError(zx_status_t status)249{250WARN() << "OnScenicError: " << zx_status_get_string(status);251mLostSession = true;252mLoop->Quit();253}254255void ScenicWindow::onViewMetrics(const fuchsia::ui::gfx::Metrics &metrics)256{257mDisplayScaleX = metrics.scale_x;258mDisplayScaleY = metrics.scale_y;259260mHasViewMetrics = true;261mViewSizeDirty = true;262}263264void ScenicWindow::onViewProperties(const fuchsia::ui::gfx::ViewProperties &properties)265{266float width = properties.bounding_box.max.x - properties.bounding_box.min.x -267properties.inset_from_min.x - properties.inset_from_max.x;268float height = properties.bounding_box.max.y - properties.bounding_box.min.y -269properties.inset_from_min.y - properties.inset_from_max.y;270271mDisplayWidthDips = width;272mDisplayHeightDips = height;273274mHasViewProperties = true;275mViewSizeDirty = true;276}277278void ScenicWindow::updateViewSize()279{280if (!mViewSizeDirty || !mHasViewMetrics || !mHasViewProperties)281{282return;283}284285mViewSizeDirty = false;286287// Surface size in pixels is288// (mWidth, mHeight)289//290// View size in pixels is291// (mDisplayWidthDips * mDisplayScaleX) x (mDisplayHeightDips * mDisplayScaleY)292293float widthDips = mWidth / mDisplayScaleX;294float heightDips = mHeight / mDisplayScaleY;295296mShape.SetShape(scenic::Rectangle(&mScenicSession, widthDips, heightDips));297mShape.SetTranslation(0.5f * widthDips, 0.5f * heightDips, 0.f);298present();299}300301// static302OSWindow *OSWindow::New()303{304return new ScenicWindow;305}306307308