/* * Copyright 2024 Google LLC * SPDX-License-Identifier: MIT */ #include "GfxStreamConnectionManager.h" #include #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 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(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 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; } }