blob: 88738a206ad3ca0a0626e26ee44764581c34436d [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 "src/graphics/bin/opencl_loader/loader.h"
fidl::ProtocolHandler<fuchsia_opencl_loader::Loader> LoaderImpl::GetHandler(
LoaderApp* app, async_dispatcher_t* dispatcher) {
return [=](fidl::ServerEnd<fuchsia_opencl_loader::Loader> server_end) {
std::unique_ptr<LoaderImpl> impl(new LoaderImpl(app));
auto binding = fidl::BindServer(dispatcher, std::move(server_end), std::move(impl));
};
}
LoaderImpl::~LoaderImpl() { app_->RemoveObserver(this); }
zx::result<> LoaderImpl::Add(component::OutgoingDirectory& outgoing_dir, LoaderApp* app,
async_dispatcher_t* dispatcher) {
return outgoing_dir.AddUnmanagedProtocol<fuchsia_opencl_loader::Loader>(
GetHandler(app, dispatcher));
}
// LoaderApp::Observer implementation.
void LoaderImpl::OnIcdListChanged(LoaderApp* app) {
auto it = callbacks_.begin();
while (it != callbacks_.end()) {
std::optional<zx::vmo> vmo = app->GetMatchingIcd(it->first);
if (!vmo) {
++it;
} else {
it->second.Reply(*std::move(vmo));
it = callbacks_.erase(it);
}
}
if (!waiting_for_callbacks()) {
app_->RemoveObserver(this);
}
}
// fuchsia::opencl::loader::Loader impl
void LoaderImpl::Get(GetRequest& request, GetCompleter::Sync& completer) {
AddCallback(std::move(request.name()), completer.ToAsync());
}
void LoaderImpl::ConnectToDeviceFs(ConnectToDeviceFsRequest& request,
ConnectToDeviceFsCompleter::Sync& completer) {
app_->ServeDeviceFs(fidl::ServerEnd<fuchsia_io::Directory>{std::move(request.channel())});
}
void LoaderImpl::ConnectToManifestFs(ConnectToManifestFsRequest& request,
ConnectToManifestFsCompleter::Sync& completer) {
auto server_end = fidl::ServerEnd<fuchsia_io::Directory>{std::move(request.channel())};
if (!(request.options() & fuchsia_opencl_loader::ConnectToManifestOptions::kWaitForIdle) ||
!app_->HavePendingActions()) {
app_->ServeManifestFs(std::move(server_end));
return;
}
bool was_waiting_for_callbacks = waiting_for_callbacks();
connect_manifest_handles_.push_back(std::move(server_end));
if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
app_->AddObserver(this);
}
}
void LoaderImpl::GetSupportedFeatures(GetSupportedFeaturesCompleter::Sync& completer) {
constexpr fuchsia_opencl_loader::Features kFeatures =
fuchsia_opencl_loader::Features::kConnectToDeviceFs | fuchsia_opencl_loader::Features::kGet;
completer.Reply(kFeatures);
}
void LoaderImpl::AddCallback(std::string name, GetCompleter::Async completer) {
bool was_waiting_for_callbacks = waiting_for_callbacks();
std::optional<zx::vmo> vmo = app_->GetMatchingIcd(name);
if (vmo) {
completer.Reply(*std::move(vmo));
return;
}
callbacks_.emplace_back(std::move(name), std::move(completer));
if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
app_->AddObserver(this);
}
}