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 #ifdef GFXSTREAM_ENABLE_GUEST_GOLDFISH
34 case GFXSTREAM_TRANSPORT_ADDRESS_SPACE: {
35 mStream = createGoldfishAddressSpaceStream(STREAM_BUFFER_SIZE);
36 if (!mStream) {
37 mesa_loge("Failed to create AddressSpaceStream for host connection\n");
38 return false;
39 }
40 break;
41 }
42 #endif
43 case GFXSTREAM_TRANSPORT_QEMU_PIPE: {
44 mStream = new QemuPipeStream(STREAM_BUFFER_SIZE);
45 if (mStream->connect() < 0) {
46 mesa_loge("Failed to connect to host (QemuPipeStream)\n");
47 return false;
48 }
49
50 break;
51 }
52 case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE: {
53 VirtioGpuPipeStream* pipeStream =
54 new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, INVALID_DESCRIPTOR);
55 if (!pipeStream) {
56 mesa_loge("Failed to create VirtioGpu for host connection\n");
57 return false;
58 }
59 if (pipeStream->connect() < 0) {
60 mesa_loge("Failed to connect to host (VirtioGpu)\n");
61 return false;
62 }
63
64 mDescriptor = pipeStream->getRendernodeFd();
65 VirtGpuDevice::getInstance(mCapset);
66 mStream = pipeStream;
67 break;
68 }
69 case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE: {
70 // Use kCapsetGfxStreamVulkan for now, Ranchu HWC needs to be modified to pass in
71 // right capset.
72 auto device = VirtGpuDevice::getInstance(kCapsetGfxStreamVulkan);
73 mDescriptor = device->getDeviceHandle();
74 mStream = createVirtioGpuAddressSpaceStream(kCapsetGfxStreamVulkan);
75 if (!mStream) {
76 mesa_loge("Failed to create virtgpu AddressSpaceStream\n");
77 return false;
78 }
79
80 break;
81 }
82 default:
83 return false;
84 }
85
86 // send zero 'clientFlags' to the host. This is actually part of the gfxstream protocol.
87 unsigned int* pClientFlags = (unsigned int*)mStream->allocBuffer(sizeof(unsigned int));
88 *pClientFlags = 0;
89 mStream->commitBuffer(sizeof(unsigned int));
90
91 return true;
92 }
93
getThreadLocalInstance(GfxStreamTransportType type,VirtGpuCapset capset)94 GfxStreamConnectionManager* GfxStreamConnectionManager::getThreadLocalInstance(
95 GfxStreamTransportType type, VirtGpuCapset capset) {
96 if (sThreadInfo.mgr == nullptr) {
97 sThreadInfo.mgr = std::make_unique<GfxStreamConnectionManager>(type, capset);
98 if (!sThreadInfo.mgr->initialize()) {
99 sThreadInfo.mgr = nullptr;
100 return nullptr;
101 }
102 }
103
104 return sThreadInfo.mgr.get();
105 }
106
threadLocalExit()107 void GfxStreamConnectionManager::threadLocalExit() {
108 if (sThreadInfo.mgr == nullptr) {
109 return;
110 }
111
112 sThreadInfo.mgr.reset();
113 }
114
addConnection(GfxStreamConnectionType type,std::unique_ptr<GfxStreamConnection> connection)115 int32_t GfxStreamConnectionManager::addConnection(GfxStreamConnectionType type,
116 std::unique_ptr<GfxStreamConnection> connection) {
117 if (mConnections.find(type) != mConnections.end()) {
118 return -EINVAL;
119 }
120
121 mConnections[type] = std::move(connection);
122 return 0;
123 }
124
getEncoder(GfxStreamConnectionType type)125 void* GfxStreamConnectionManager::getEncoder(GfxStreamConnectionType type) {
126 auto iterator = mConnections.find(type);
127 if (iterator == mConnections.end()) {
128 return nullptr;
129 }
130
131 return iterator->second->getEncoder();
132 }
133
getStream()134 gfxstream::guest::IOStream* GfxStreamConnectionManager::getStream() { return mStream; }
135
processPipeStream(GfxStreamTransportType transportType)136 gfxstream::guest::IOStream* GfxStreamConnectionManager::processPipeStream(
137 GfxStreamTransportType transportType) {
138 switch (transportType) {
139 case GFXSTREAM_TRANSPORT_ADDRESS_SPACE:
140 case GFXSTREAM_TRANSPORT_QEMU_PIPE:
141 return new QemuPipeStream(STREAM_BUFFER_SIZE);
142 case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE:
143 case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE:
144 return new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, mDescriptor);
145 default:
146 return nullptr;
147 }
148 }
149