xref: /aosp_15_r20/external/mesa3d/src/gfxstream/guest/platform/fuchsia/FuchsiaVirtGpuDevice.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <lib/zx/vmo.h>
7 #include <msd-virtio-gpu/magma-virtio-gpu-defs.h>
8 #include <os_dirent.h>
9 #include <services/service_connector.h>
10 
11 #include <climits>
12 #include <cstdio>
13 #include <cstdlib>
14 
15 #include "FuchsiaVirtGpu.h"
16 #include "Sync.h"
17 #include "util/log.h"
18 
FuchsiaVirtGpuDevice(enum VirtGpuCapset capset,magma_device_t device)19 FuchsiaVirtGpuDevice::FuchsiaVirtGpuDevice(enum VirtGpuCapset capset, magma_device_t device)
20     : VirtGpuDevice(capset), device_(device) {
21     memset(&mCaps, 0, sizeof(struct VirtGpuCaps));
22 
23     // Hard-coded values that may be assumed on Fuchsia.
24     mCaps.params[kParam3D] = 1;
25     mCaps.params[kParamCapsetFix] = 1;
26     mCaps.params[kParamResourceBlob] = 1;
27     mCaps.params[kParamHostVisible] = 1;
28     mCaps.params[kParamCrossDevice] = 0;
29     mCaps.params[kParamContextInit] = 1;
30     mCaps.params[kParamSupportedCapsetIds] = 0;
31     mCaps.params[kParamExplicitDebugName] = 0;
32     mCaps.params[kParamCreateGuestHandle] = 0;
33 
34     if (capset == kCapsetGfxStreamVulkan) {
35         uint64_t query_id = kMagmaVirtioGpuQueryCapset;
36         query_id |= static_cast<uint64_t>(kCapsetGfxStreamVulkan) << 32;
37         constexpr uint16_t kVersion = 0;
38         query_id |= static_cast<uint64_t>(kVersion) << 16;
39 
40         magma_handle_t buffer;
41         magma_status_t status = magma_device_query(device_, query_id, &buffer, nullptr);
42         if (status == MAGMA_STATUS_OK) {
43             zx::vmo capset_info(buffer);
44             zx_status_t status =
45                 capset_info.read(&mCaps.vulkanCapset, /*offset=*/0, sizeof(struct vulkanCapset));
46             mesa_logi("Got capset result, read status %d", status);
47         } else {
48             mesa_loge("Query(%lu) failed: status %d, expected buffer result", query_id, status);
49         }
50 
51         // We always need an ASG blob in some cases, so always define blobAlignment
52         if (!mCaps.vulkanCapset.blobAlignment) {
53             mCaps.vulkanCapset.blobAlignment = 4096;
54         }
55     }
56 }
57 
~FuchsiaVirtGpuDevice()58 FuchsiaVirtGpuDevice::~FuchsiaVirtGpuDevice() { magma_device_release(device_); }
59 
getDeviceHandle(void)60 int64_t FuchsiaVirtGpuDevice::getDeviceHandle(void) { return device_; }
61 
createBlob(const struct VirtGpuCreateBlob & blobCreate)62 VirtGpuResourcePtr FuchsiaVirtGpuDevice::createBlob(const struct VirtGpuCreateBlob& blobCreate) {
63     mesa_loge("%s: unimplemented", __func__);
64     return nullptr;
65 }
66 
createResource(uint32_t width,uint32_t height,uint32_t stride,uint32_t size,uint32_t virglFormat,uint32_t target,uint32_t bind)67 VirtGpuResourcePtr FuchsiaVirtGpuDevice::createResource(uint32_t width, uint32_t height,
68                                                         uint32_t stride, uint32_t size,
69                                                         uint32_t virglFormat, uint32_t target,
70                                                         uint32_t bind) {
71     mesa_loge("%s: unimplemented", __func__);
72     return nullptr;
73 }
74 
importBlob(const struct VirtGpuExternalHandle & handle)75 VirtGpuResourcePtr FuchsiaVirtGpuDevice::importBlob(const struct VirtGpuExternalHandle& handle) {
76     mesa_loge("%s: unimplemented", __func__);
77     return nullptr;
78 }
79 
execBuffer(struct VirtGpuExecBuffer & execbuffer,const VirtGpuResource * blob)80 int FuchsiaVirtGpuDevice::execBuffer(struct VirtGpuExecBuffer& execbuffer,
81                                      const VirtGpuResource* blob) {
82     mesa_loge("%s: unimplemented", __func__);
83     return 0;
84 }
85 
getCaps(void)86 struct VirtGpuCaps FuchsiaVirtGpuDevice::getCaps(void) { return {}; }
87 
osCreateVirtGpuDevice(enum VirtGpuCapset capset,int32_t descriptor)88 VirtGpuDevice* osCreateVirtGpuDevice(enum VirtGpuCapset capset, int32_t descriptor) {
89     // We don't handle the VirtioGpuPipeStream case.
90     if (descriptor >= 0) {
91         mesa_loge("Fuchsia: fd not handled");
92         return nullptr;
93     }
94 
95     const char kDevGpu[] = "/loader-gpu-devices/class/gpu";
96 
97     struct os_dirent* de;
98     os_dir_t* dir = os_opendir(kDevGpu);
99     if (!dir) {
100         mesa_loge("Error opening %s", kDevGpu);
101         return nullptr;
102     }
103 
104     mesa_logi("Opened dir %s", kDevGpu);
105 
106     VirtGpuDevice* gpu_device = nullptr;
107 
108     while ((de = os_readdir(dir)) != NULL) {
109         mesa_logi("Got name %s", de->d_name);
110 
111         if (strcmp(de->d_name, ".") == 0) {
112             continue;
113         }
114         // extra +1 ensures space for null termination
115         char name[sizeof(kDevGpu) + sizeof('/') + sizeof(de->d_name) + 1];
116         snprintf(name, sizeof(name), "%s/%s", kDevGpu, de->d_name);
117 
118         zx_handle_t device_channel = GetConnectToServiceFunction()(name);
119         if (device_channel == ZX_HANDLE_INVALID) {
120             mesa_loge("Failed to open device: %s", name);
121             continue;
122         }
123 
124         magma_device_t magma_device;
125         magma_status_t status = magma_device_import(device_channel, &magma_device);
126         if (status != MAGMA_STATUS_OK) {
127             mesa_loge("magma_device_import failed: %d", status);
128             continue;
129         }
130 
131         gpu_device = new FuchsiaVirtGpuDevice(capset, magma_device);
132         break;
133     }
134     os_closedir(dir);
135 
136     return gpu_device;
137 }
138 
139 namespace gfxstream {
140 
osCreateSyncHelper()141 SyncHelper* osCreateSyncHelper() { return nullptr; }
142 
143 }  // namespace gfxstream
144