xref: /aosp_15_r20/external/mesa3d/src/gfxstream/guest/connection-manager/GfxStreamConnectionManager.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "GfxStreamConnectionManager.h"
7 
8 #include <cerrno>
9 
10 #include "GoldfishAddressSpaceStream.h"
11 #include "QemuPipeStream.h"
12 #include "VirtGpu.h"
13 #include "VirtioGpuAddressSpaceStream.h"
14 #include "VirtioGpuPipeStream.h"
15 #include "util/log.h"
16 
17 #define STREAM_BUFFER_SIZE (4 * 1024 * 1024)
18 
19 struct ThreadInfo {
20     std::unique_ptr<GfxStreamConnectionManager> mgr;
21 };
22 
23 static thread_local ThreadInfo sThreadInfo;
24 
GfxStreamConnectionManager(GfxStreamTransportType type,VirtGpuCapset capset)25 GfxStreamConnectionManager::GfxStreamConnectionManager(GfxStreamTransportType type,
26                                                        VirtGpuCapset capset)
27     : mTransportType(type), mCapset(capset) {}
28 
~GfxStreamConnectionManager()29 GfxStreamConnectionManager::~GfxStreamConnectionManager() {}
30 
initialize()31 bool GfxStreamConnectionManager::initialize() {
32     switch (mTransportType) {
33         case GFXSTREAM_TRANSPORT_ADDRESS_SPACE: {
34             mStream = createGoldfishAddressSpaceStream(STREAM_BUFFER_SIZE);
35             if (!mStream) {
36                 mesa_loge("Failed to create AddressSpaceStream for host connection\n");
37                 return false;
38             }
39             break;
40         }
41         case GFXSTREAM_TRANSPORT_QEMU_PIPE: {
42             mStream = new QemuPipeStream(STREAM_BUFFER_SIZE);
43             if (mStream->connect() < 0) {
44                 mesa_loge("Failed to connect to host (QemuPipeStream)\n");
45                 return false;
46             }
47 
48             break;
49         }
50         case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE: {
51             VirtioGpuPipeStream* pipeStream =
52                 new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, INVALID_DESCRIPTOR);
53             if (!pipeStream) {
54                 mesa_loge("Failed to create VirtioGpu for host connection\n");
55                 return false;
56             }
57             if (pipeStream->connect() < 0) {
58                 mesa_loge("Failed to connect to host (VirtioGpu)\n");
59                 return false;
60             }
61 
62             mDescriptor = pipeStream->getRendernodeFd();
63             VirtGpuDevice::getInstance(mCapset);
64             mStream = pipeStream;
65             break;
66         }
67         case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE: {
68             // Use kCapsetGfxStreamVulkan for now, Ranchu HWC needs to be modified to pass in
69             // right capset.
70             auto device = VirtGpuDevice::getInstance(kCapsetGfxStreamVulkan);
71             mDescriptor = device->getDeviceHandle();
72             mStream = createVirtioGpuAddressSpaceStream(kCapsetGfxStreamVulkan);
73             if (!mStream) {
74                 mesa_loge("Failed to create virtgpu AddressSpaceStream\n");
75                 return false;
76             }
77 
78             break;
79         }
80         default:
81             return false;
82     }
83 
84     // send zero 'clientFlags' to the host.  This is actually part of the gfxstream protocol.
85     unsigned int* pClientFlags = (unsigned int*)mStream->allocBuffer(sizeof(unsigned int));
86     *pClientFlags = 0;
87     mStream->commitBuffer(sizeof(unsigned int));
88 
89     return true;
90 }
91 
getThreadLocalInstance(GfxStreamTransportType type,VirtGpuCapset capset)92 GfxStreamConnectionManager* GfxStreamConnectionManager::getThreadLocalInstance(
93     GfxStreamTransportType type, VirtGpuCapset capset) {
94     if (sThreadInfo.mgr == nullptr) {
95         sThreadInfo.mgr = std::make_unique<GfxStreamConnectionManager>(type, capset);
96         if (!sThreadInfo.mgr->initialize()) {
97             sThreadInfo.mgr = nullptr;
98             return nullptr;
99         }
100     }
101 
102     return sThreadInfo.mgr.get();
103 }
104 
threadLocalExit()105 void GfxStreamConnectionManager::threadLocalExit() {
106     if (sThreadInfo.mgr == nullptr) {
107         return;
108     }
109 
110     sThreadInfo.mgr.reset();
111 }
112 
addConnection(GfxStreamConnectionType type,std::unique_ptr<GfxStreamConnection> connection)113 int32_t GfxStreamConnectionManager::addConnection(GfxStreamConnectionType type,
114                                                   std::unique_ptr<GfxStreamConnection> connection) {
115     if (mConnections.find(type) != mConnections.end()) {
116         return -EINVAL;
117     }
118 
119     mConnections[type] = std::move(connection);
120     return 0;
121 }
122 
getEncoder(GfxStreamConnectionType type)123 void* GfxStreamConnectionManager::getEncoder(GfxStreamConnectionType type) {
124     auto iterator = mConnections.find(type);
125     if (iterator == mConnections.end()) {
126         return nullptr;
127     }
128 
129     return iterator->second->getEncoder();
130 }
131 
getStream()132 gfxstream::guest::IOStream* GfxStreamConnectionManager::getStream() { return mStream; }
133 
processPipeStream(GfxStreamTransportType transportType)134 gfxstream::guest::IOStream* GfxStreamConnectionManager::processPipeStream(
135     GfxStreamTransportType transportType) {
136     switch (transportType) {
137         case GFXSTREAM_TRANSPORT_ADDRESS_SPACE:
138         case GFXSTREAM_TRANSPORT_QEMU_PIPE:
139             return new QemuPipeStream(STREAM_BUFFER_SIZE);
140         case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE:
141         case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE:
142             return new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, mDescriptor);
143         default:
144             return nullptr;
145     }
146 }
147