[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:
@@ -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_;
|
||||
};
|
||||
|
@@ -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;
|
||||
}
|
||||
|
104
src/gfxstream/guest/platform/fuchsia/os_dirent_fuchsia.cpp
Normal file
104
src/gfxstream/guest/platform/fuchsia/os_dirent_fuchsia.cpp
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user