blob: 1dd49745dbfc7626ca87d143579d7e0a6fd89155 [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/vulkan_loader/loader.h"
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
LoaderImpl::~LoaderImpl() { app_->RemoveObserver(this); }
// static
void LoaderImpl::Add(LoaderApp* app, const std::shared_ptr<sys::OutgoingDirectory>& outgoing) {
outgoing->AddPublicService(fidl::InterfaceRequestHandler<fuchsia::vulkan::loader::Loader>(
[app](fidl::InterfaceRequest<fuchsia::vulkan::loader::Loader> request) {
auto impl = std::make_unique<LoaderImpl>(app);
LoaderImpl* impl_ptr = impl.get();
impl_ptr->bindings_.AddBinding(std::move(impl), std::move(request), nullptr);
}));
}
// 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(*std::move(vmo));
it = callbacks_.erase(it);
}
}
if (!app->HavePendingActions()) {
for (auto& handle : connect_manifest_handles_) {
app_->ServeManifestFs(std::move(handle));
}
connect_manifest_handles_.clear();
}
if (!waiting_for_callbacks()) {
app_->RemoveObserver(this);
}
}
// fuchsia::vulkan::loader::Loader impl
void LoaderImpl::Get(std::string name, GetCallback callback) {
AddCallback(std::move(name), std::move(callback));
}
void LoaderImpl::ConnectToDeviceFs(zx::channel channel) { app_->ServeDeviceFs(std::move(channel)); }
void LoaderImpl::ConnectToManifestFs(fuchsia::vulkan::loader::ConnectToManifestOptions options,
zx::channel channel) {
if (!(options & fuchsia::vulkan::loader::ConnectToManifestOptions::WAIT_FOR_IDLE) ||
!app_->HavePendingActions()) {
app_->ServeManifestFs(std::move(channel));
return;
}
bool was_waiting_for_callbacks = waiting_for_callbacks();
connect_manifest_handles_.push_back(std::move(channel));
if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
app_->AddObserver(this);
}
}
void LoaderImpl::GetSupportedFeatures(GetSupportedFeaturesCallback callback) {
fuchsia::vulkan::loader::Features features =
fuchsia::vulkan::loader::Features::CONNECT_TO_DEVICE_FS |
fuchsia::vulkan::loader::Features::GET |
fuchsia::vulkan::loader::Features::CONNECT_TO_MANIFEST_FS;
callback(features);
}
void LoaderImpl::AddCallback(std::string name, fit::function<void(zx::vmo)> callback) {
bool was_waiting_for_callbacks = waiting_for_callbacks();
std::optional<zx::vmo> vmo = app_->GetMatchingIcd(name);
if (vmo) {
callback(*std::move(vmo));
return;
}
callbacks_.emplace_back(std::make_pair(std::move(name), std::move(callback)));
if (waiting_for_callbacks() && !was_waiting_for_callbacks) {
app_->AddObserver(this);
}
}