blob: 404002536a67cc3df87b5c143d18000725e172c0 [file] [log] [blame]
/*
*
* Copyright (c) 2021 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "loader_service.h"
#include <fcntl.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.vulkan.loader/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/io.h>
#include <lib/fidl/llcpp/connect_service.h>
#include <lib/service/llcpp/service.h>
#include <stdio.h>
#include <string.h>
#include <threads.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include "loader.h"
#include "log.h"
static fidl::WireSyncClient<fuchsia_vulkan_loader::Loader> vulkan_loader_svc;
static zx_handle_t device_fs = ZX_HANDLE_INVALID;
static int manifest_fs_fd = -1;
void connect_to_vulkan_loader_svc() {
auto svc = service::OpenServiceRoot();
auto client_end = service::ConnectAt<fuchsia_vulkan_loader::Loader>(*svc);
if (!client_end.is_ok()) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"connect_to_vulkan_loader_svc: Failed to connect to loader service: %s", client_end.status_string());
return;
}
auto client = fidl::BindSyncClient(std::move(*client_end));
auto feature_result = client->GetSupportedFeatures();
fuchsia_vulkan_loader::wire::Features features;
if (!feature_result.ok()) {
loader_log(nullptr, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
"connect_to_vulkan_loader_svc: Failed to get supported features, error \"%s\".",
feature_result.error().lossy_description());
return;
}
features = feature_result->features;
constexpr fuchsia_vulkan_loader::wire::Features kMandatoryFeatures =
fuchsia_vulkan_loader::wire::Features::kConnectToDeviceFs | fuchsia_vulkan_loader::wire::Features::kConnectToManifestFs |
fuchsia_vulkan_loader::wire::Features::kGet;
if ((features & kMandatoryFeatures) != kMandatoryFeatures) {
loader_log(nullptr, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "connect_to_vulkan_loader_svc: Missing mandatory feature 0x%x",
kMandatoryFeatures & ~features);
return;
}
zx::channel device_fs_client;
{
zx::channel device_fs_server;
zx_status_t status = zx::channel::create(0, &device_fs_server, &device_fs_client);
if (status != ZX_OK) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "connect_to_vulkan_loader_svc: Failed to create channel: %s",
zx_status_get_string(status));
return;
}
auto result = client->ConnectToDeviceFs(std::move(device_fs_server));
if (!result.ok()) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"connect_to_vulkan_loader_svc: Failed to connect to device fs: %s", result.status_string());
return;
}
}
{
zx::channel manifest_fs_client;
zx::channel manifest_fs_server;
zx_status_t status = zx::channel::create(0, &manifest_fs_server, &manifest_fs_client);
if (status != ZX_OK) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "connect_to_vulkan_loader_svc: Failed to create channel: %s",
zx_status_get_string(status));
return;
}
// Wait for idle so clients will be sure that any existing ICDs will be completely available.
auto result = client->ConnectToManifestFs(fuchsia_vulkan_loader::wire::ConnectToManifestOptions::kWaitForIdle,
std::move(manifest_fs_server));
if (!result.ok()) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"connect_to_vulkan_loader_svc: Failed to connect to manifest fs: %s", result.status_string());
return;
}
status = fdio_fd_create(manifest_fs_client.release(), &manifest_fs_fd);
if (status != ZX_OK) {
loader_log(nullptr, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"connect_to_vulkan_loader_svc: Failed to create manifest fs fd: %s", zx_status_get_string(status));
return;
}
}
vulkan_loader_svc = std::move(client);
device_fs = device_fs_client.release();
}
static once_flag svc_connect_once_flag = ONCE_FLAG_INIT;
fidl::WireSyncClient<fuchsia_vulkan_loader::Loader>& get_vulkan_loader_service() {
call_once(&svc_connect_once_flag, connect_to_vulkan_loader_svc);
return vulkan_loader_svc;
}
zx_handle_t get_device_fs() {
call_once(&svc_connect_once_flag, connect_to_vulkan_loader_svc);
return device_fs;
}
int get_manifest_fs_fd(void) {
call_once(&svc_connect_once_flag, connect_to_vulkan_loader_svc);
return manifest_fs_fd;
}