• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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