blob: 96fde7cae0cbc331f104a6275577ce981ca3acde [file] [log] [blame]
/*
* Copyright 2024 Google LLC
* SPDX-License-Identifier: MIT
*/
#include "GfxStreamConnectionManager.h"
#include <cerrno>
#include "GoldfishAddressSpaceStream.h"
#include "QemuPipeStream.h"
#include "VirtGpu.h"
#include "VirtioGpuAddressSpaceStream.h"
#include "VirtioGpuPipeStream.h"
#include "util/log.h"
#define STREAM_BUFFER_SIZE (4 * 1024 * 1024)
struct ThreadInfo {
std::unique_ptr<GfxStreamConnectionManager> mgr;
};
static thread_local ThreadInfo sThreadInfo;
GfxStreamConnectionManager::GfxStreamConnectionManager(GfxStreamTransportType type,
VirtGpuCapset capset)
: mTransportType(type), mCapset(capset) {}
GfxStreamConnectionManager::~GfxStreamConnectionManager() {}
bool GfxStreamConnectionManager::initialize() {
switch (mTransportType) {
case GFXSTREAM_TRANSPORT_ADDRESS_SPACE: {
mStream = createGoldfishAddressSpaceStream(STREAM_BUFFER_SIZE);
if (!mStream) {
mesa_loge("Failed to create AddressSpaceStream for host connection\n");
return false;
}
break;
}
case GFXSTREAM_TRANSPORT_QEMU_PIPE: {
mStream = new QemuPipeStream(STREAM_BUFFER_SIZE);
if (mStream->connect() < 0) {
mesa_loge("Failed to connect to host (QemuPipeStream)\n");
return false;
}
break;
}
case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE: {
VirtioGpuPipeStream* pipeStream =
new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, INVALID_DESCRIPTOR);
if (!pipeStream) {
mesa_loge("Failed to create VirtioGpu for host connection\n");
return false;
}
if (pipeStream->connect() < 0) {
mesa_loge("Failed to connect to host (VirtioGpu)\n");
return false;
}
mDescriptor = pipeStream->getRendernodeFd();
VirtGpuDevice::getInstance(mCapset);
mStream = pipeStream;
break;
}
case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE: {
// Use kCapsetGfxStreamVulkan for now, Ranchu HWC needs to be modified to pass in
// right capset.
auto device = VirtGpuDevice::getInstance(kCapsetGfxStreamVulkan);
mDescriptor = device->getDeviceHandle();
mStream = createVirtioGpuAddressSpaceStream(kCapsetGfxStreamVulkan);
if (!mStream) {
mesa_loge("Failed to create virtgpu AddressSpaceStream\n");
return false;
}
break;
}
default:
return false;
}
// send zero 'clientFlags' to the host. This is actually part of the gfxstream protocol.
unsigned int* pClientFlags = (unsigned int*)mStream->allocBuffer(sizeof(unsigned int));
*pClientFlags = 0;
mStream->commitBuffer(sizeof(unsigned int));
return true;
}
GfxStreamConnectionManager* GfxStreamConnectionManager::getThreadLocalInstance(
GfxStreamTransportType type, VirtGpuCapset capset) {
if (sThreadInfo.mgr == nullptr) {
sThreadInfo.mgr = std::make_unique<GfxStreamConnectionManager>(type, capset);
if (!sThreadInfo.mgr->initialize()) {
sThreadInfo.mgr = nullptr;
return nullptr;
}
}
return sThreadInfo.mgr.get();
}
void GfxStreamConnectionManager::threadLocalExit() {
if (sThreadInfo.mgr == nullptr) {
return;
}
sThreadInfo.mgr.reset();
}
int32_t GfxStreamConnectionManager::addConnection(GfxStreamConnectionType type,
std::unique_ptr<GfxStreamConnection> connection) {
if (mConnections.find(type) != mConnections.end()) {
return -EINVAL;
}
mConnections[type] = std::move(connection);
return 0;
}
void* GfxStreamConnectionManager::getEncoder(GfxStreamConnectionType type) {
auto iterator = mConnections.find(type);
if (iterator == mConnections.end()) {
return nullptr;
}
return iterator->second->getEncoder();
}
gfxstream::guest::IOStream* GfxStreamConnectionManager::getStream() { return mStream; }
gfxstream::guest::IOStream* GfxStreamConnectionManager::processPipeStream(
GfxStreamTransportType transportType) {
switch (transportType) {
case GFXSTREAM_TRANSPORT_ADDRESS_SPACE:
case GFXSTREAM_TRANSPORT_QEMU_PIPE:
return new QemuPipeStream(STREAM_BUFFER_SIZE);
case GFXSTREAM_TRANSPORT_VIRTIO_GPU_ADDRESS_SPACE:
case GFXSTREAM_TRANSPORT_VIRTIO_GPU_PIPE:
return new VirtioGpuPipeStream(STREAM_BUFFER_SIZE, mDescriptor);
default:
return nullptr;
}
}