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