[guest] Fuchsia: open magma device

Reviewed-by: Aaron Ruby <aruby@blackberry.com>
Acked-by: Yonggang Luo <luoyonggang@gmail.com>
Acked-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
C Stout
2024-02-25 09:55:09 -08:00
committed by Marge Bot
parent a7b61ee151
commit 36d09f70ce
3 changed files with 165 additions and 9 deletions

View File

@@ -16,6 +16,8 @@
#pragma once
#include <lib/magma/magma.h>
#include "VirtGpu.h"
class FuchsiaVirtGpuBlob : public std::enable_shared_from_this<FuchsiaVirtGpuBlob>,
@@ -46,7 +48,7 @@ class FuchsiaVirtGpuBlobMapping : public VirtGpuBlobMapping {
class FuchsiaVirtGpuDevice : public VirtGpuDevice {
public:
FuchsiaVirtGpuDevice(enum VirtGpuCapset capset);
FuchsiaVirtGpuDevice(enum VirtGpuCapset capset, magma_device_t device);
~FuchsiaVirtGpuDevice();
int64_t getDeviceHandle(void) override;
@@ -58,4 +60,7 @@ class FuchsiaVirtGpuDevice : public VirtGpuDevice {
VirtGpuBlobPtr importBlob(const struct VirtGpuExternalHandle& handle) override;
int execBuffer(struct VirtGpuExecBuffer& execbuffer, const VirtGpuBlob* blob) override;
private:
magma_device_t device_;
};

View File

@@ -15,18 +15,22 @@
*/
#include <cutils/log.h>
#include <stdlib.h>
#include <os_dirent.h>
#include <services/service_connector.h>
#include <unistd.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include "FuchsiaVirtGpu.h"
FuchsiaVirtGpuDevice::FuchsiaVirtGpuDevice(enum VirtGpuCapset capset) : VirtGpuDevice(capset) {}
FuchsiaVirtGpuDevice::FuchsiaVirtGpuDevice(enum VirtGpuCapset capset, magma_device_t device)
: VirtGpuDevice(capset), device_(device) {}
FuchsiaVirtGpuDevice::~FuchsiaVirtGpuDevice() {}
FuchsiaVirtGpuDevice::~FuchsiaVirtGpuDevice() { magma_device_release(device_); }
int64_t FuchsiaVirtGpuDevice::getDeviceHandle(void) {
ALOGE("%s: unimplemented", __func__);
return 0;
}
int64_t FuchsiaVirtGpuDevice::getDeviceHandle(void) { return device_; }
VirtGpuBlobPtr FuchsiaVirtGpuDevice::createBlob(const struct VirtGpuCreateBlob& blobCreate) {
ALOGE("%s: unimplemented", __func__);
@@ -57,6 +61,49 @@ VirtGpuDevice* createPlatformVirtGpuDevice(enum VirtGpuCapset capset, int fd) {
if (fd >= 0) {
ALOGE("Fuchsia: fd not handled");
abort();
return nullptr;
}
return new FuchsiaVirtGpuDevice(capset);
const char kDevGpu[] = "/loader-gpu-devices/class/gpu";
struct os_dirent* de;
os_dir_t* dir = os_opendir(kDevGpu);
if (!dir) {
ALOGE("Error opening %s", kDevGpu);
return nullptr;
}
ALOGD("Opened dir %s", kDevGpu);
VirtGpuDevice* gpu_device = nullptr;
while ((de = os_readdir(dir)) != NULL) {
ALOGD("Got name %s", de->d_name);
if (strcmp(de->d_name, ".") == 0) {
continue;
}
// extra +1 ensures space for null termination
char name[sizeof(kDevGpu) + sizeof('/') + sizeof(de->d_name) + 1];
snprintf(name, sizeof(name), "%s/%s", kDevGpu, de->d_name);
zx_handle_t device_channel = GetConnectToServiceFunction()(name);
if (device_channel == ZX_HANDLE_INVALID) {
ALOGE("Failed to open device: %s", name);
continue;
}
magma_device_t magma_device;
magma_status_t status = magma_device_import(device_channel, &magma_device);
if (status != MAGMA_STATUS_OK) {
ALOGE("magma_device_import failed: %d", status);
continue;
}
gpu_device = new FuchsiaVirtGpuDevice(capset, magma_device);
break;
}
os_closedir(dir);
return gpu_device;
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2024 The Android Open Source Project
*
* 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 <cutils/log.h>
#include <lib/zxio/zxio.h>
#include <services/service_connector.h>
#include <string.h>
#include "os_dirent.h"
struct os_dir {
~os_dir() {
if (dir_iterator_init_) {
zxio_dirent_iterator_destroy(&iterator_);
}
if (zxio_init_) {
zxio_close(&io_storage_.io, /*should_wait=*/true);
}
}
// Always consumes |dir_channel|
bool Init(zx_handle_t dir_channel) {
zx_status_t status = zxio_create(dir_channel, &io_storage_);
if (status != ZX_OK) {
ALOGE("zxio_create failed: %d", status);
return false;
}
zxio_init_ = true;
status = zxio_dirent_iterator_init(&iterator_, &io_storage_.io);
if (status != ZX_OK) {
ALOGE("zxio_dirent_iterator_init failed: %d", status);
return false;
}
dir_iterator_init_ = true;
return true;
}
bool Next(struct os_dirent* entry) {
// dirent is an in-out parameter.
// name must be initialized to point to a buffer of at least ZXIO_MAX_FILENAME bytes.
static_assert(sizeof(entry->d_name) >= ZXIO_MAX_FILENAME);
zxio_dirent_t dirent = {.name = entry->d_name};
zx_status_t status = zxio_dirent_iterator_next(&iterator_, &dirent);
if (status != ZX_OK) {
if (status != ZX_ERR_NOT_FOUND) ALOGE("zxio_dirent_iterator_next failed: %d", status);
return false;
}
entry->d_ino = dirent.has.id ? dirent.id : OS_INO_UNKNOWN;
entry->d_name[dirent.name_length] = '\0';
return true;
}
private:
bool zxio_init_ = false;
bool dir_iterator_init_ = false;
zxio_storage_t io_storage_;
zxio_dirent_iterator_t iterator_;
};
os_dir_t* os_opendir(const char* path) {
zx_handle_t dir_channel = GetConnectToServiceFunction()(path);
if (dir_channel == ZX_HANDLE_INVALID) {
ALOGE("fuchsia_open(%s) failed", path);
return nullptr;
}
auto dir = new os_dir();
if (!dir->Init(dir_channel)) {
delete dir;
return nullptr;
}
return dir;
}
int os_closedir(os_dir_t* dir) {
delete dir;
return 0;
}
struct os_dirent* os_readdir(os_dir_t* dir) {
static struct os_dirent dirent = {};
return reinterpret_cast<os_dirent*>(dir->Next(&dirent)) ? &dirent : nullptr;
}