| // Copyright (C) 2024 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #include "ExtendedRenderControl.h" |
| |
| using gfxstream::guest::ChecksumCalculator; |
| |
| const std::string& ExtendedRCEncoderContext::queryHostExtensions() { |
| if (!m_hostExtensions.empty()) { |
| return m_hostExtensions; |
| } |
| |
| // Extensions strings are usually quite long, preallocate enough here. |
| std::string extensionsBuffer(1023, '\0'); |
| |
| // Returns the required size including the 0-terminator, so |
| // account it when passing/using the sizes. |
| int extensionSize = |
| this->rcGetHostExtensionsString(this, extensionsBuffer.size() + 1, &extensionsBuffer[0]); |
| if (extensionSize < 0) { |
| extensionsBuffer.resize(-extensionSize); |
| extensionSize = |
| this->rcGetHostExtensionsString(this, -extensionSize + 1, &extensionsBuffer[0]); |
| } |
| |
| if (extensionSize > 0) { |
| extensionsBuffer.resize(extensionSize - 1); |
| m_hostExtensions.swap(extensionsBuffer); |
| } |
| |
| return m_hostExtensions; |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetHostCompositionImpl() { |
| const std::string& hostExtensions = queryHostExtensions(); |
| // make sure V2 is checked first before V1, as host may declare supporting both |
| if (hostExtensions.find(kHostCompositionV2) != std::string::npos) { |
| this->setHostComposition(HOST_COMPOSITION_V2); |
| } else if (hostExtensions.find(kHostCompositionV1) != std::string::npos) { |
| this->setHostComposition(HOST_COMPOSITION_V1); |
| } else { |
| this->setHostComposition(HOST_COMPOSITION_NONE); |
| } |
| } |
| |
| void ExtendedRCEncoderContext::setChecksumHelper(ChecksumCalculator* calculator) { |
| const std::string& hostExtensions = queryHostExtensions(); |
| // check the host supported version |
| uint32_t checksumVersion = 0; |
| const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix(); |
| const char* glProtocolStr = strstr(hostExtensions.c_str(), checksumPrefix); |
| if (glProtocolStr) { |
| uint32_t maxVersion = ChecksumCalculator::getMaxVersion(); |
| sscanf(glProtocolStr + strlen(checksumPrefix), "%d", &checksumVersion); |
| if (maxVersion < checksumVersion) { |
| checksumVersion = maxVersion; |
| } |
| // The ordering of the following two commands matters! |
| // Must tell the host first before setting it in the guest |
| this->rcSelectChecksumHelper(this, checksumVersion, 0); |
| calculator->setVersion(checksumVersion); |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetSyncImpl() { |
| const std::string& hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kRCNativeSyncV4) != std::string::npos) { |
| this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V4); |
| } else if (hostExtensions.find(kRCNativeSyncV3) != std::string::npos) { |
| this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3); |
| } else if (hostExtensions.find(kRCNativeSyncV2) != std::string::npos) { |
| this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2); |
| } else { |
| this->setSyncImpl(SYNC_IMPL_NONE); |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetDmaImpl() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kDmaExtStr_v1) != std::string::npos) { |
| this->setDmaImpl(DMA_IMPL_v1); |
| } else { |
| this->setDmaImpl(DMA_IMPL_NONE); |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetGLESMaxVersion() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kGLESMaxVersion_2) != std::string::npos) { |
| this->setGLESMaxVersion(GLES_MAX_VERSION_2); |
| } else if (hostExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) { |
| this->setGLESMaxVersion(GLES_MAX_VERSION_3_0); |
| } else if (hostExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) { |
| this->setGLESMaxVersion(GLES_MAX_VERSION_3_1); |
| } else if (hostExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) { |
| this->setGLESMaxVersion(GLES_MAX_VERSION_3_2); |
| } else { |
| ALOGW("Unrecognized GLES max version string in extensions: %s", hostExtensions.c_str()); |
| this->setGLESMaxVersion(GLES_MAX_VERSION_2); |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetNoErrorState(bool& hostError) { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kGLESUseHostError) != std::string::npos) { |
| hostError = false; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetDirectMemSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kGLDirectMem) != std::string::npos) { |
| this->featureInfo()->hasDirectMem = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkan) != std::string::npos) { |
| this->featureInfo()->hasVulkan = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetDeferredVulkanCommandsSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kDeferredVulkanCommands) != std::string::npos) { |
| this->featureInfo()->hasDeferredVulkanCommands = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanNullOptionalStringsSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanNullOptionalStrings) != std::string::npos) { |
| this->featureInfo()->hasVulkanNullOptionalStrings = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanCreateResourcesWithRequirementsSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanCreateResourcesWithRequirements) != std::string::npos) { |
| this->featureInfo()->hasVulkanCreateResourcesWithRequirements = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanIgnoredHandles() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanIgnoredHandles) != std::string::npos) { |
| this->featureInfo()->hasVulkanIgnoredHandles = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetYUVCache() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kYUVCache) != std::string::npos) { |
| this->featureInfo()->hasYUVCache = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetAsyncUnmapBuffer() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kAsyncUnmapBuffer) != std::string::npos) { |
| this->featureInfo()->hasAsyncUnmapBuffer = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVirtioGpuNext() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVirtioGpuNext) != std::string::npos) { |
| this->featureInfo()->hasVirtioGpuNext = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryHasSharedSlotsHostMemoryAllocator() { |
| const std::string& hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kHasSharedSlotsHostMemoryAllocator) != std::string::npos) { |
| this->featureInfo()->hasSharedSlotsHostMemoryAllocator = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanFreeMemorySync() { |
| const std::string& hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanFreeMemorySync) != std::string::npos) { |
| this->featureInfo()->hasVulkanFreeMemorySync = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVirtioGpuNativeSync() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVirtioGpuNativeSync) != std::string::npos) { |
| this->featureInfo()->hasVirtioGpuNativeSync = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanShaderFloat16Int8Support() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanShaderFloat16Int8) != std::string::npos) { |
| this->featureInfo()->hasVulkanShaderFloat16Int8 = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanAsyncQueueSubmitSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanAsyncQueueSubmit) != std::string::npos) { |
| this->featureInfo()->hasVulkanAsyncQueueSubmit = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetHostSideTracingSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kHostSideTracing) != std::string::npos) { |
| this->featureInfo()->hasHostSideTracing = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetAsyncFrameCommands() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kAsyncFrameCommands) != std::string::npos) { |
| this->featureInfo()->hasAsyncFrameCommands = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanQueueSubmitWithCommandsSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanQueueSubmitWithCommands) != std::string::npos) { |
| this->featureInfo()->hasVulkanQueueSubmitWithCommands = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanBatchedDescriptorSetUpdateSupport() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanBatchedDescriptorSetUpdate) != std::string::npos) { |
| this->featureInfo()->hasVulkanBatchedDescriptorSetUpdate = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetSyncBufferData() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kSyncBufferData) != std::string::npos) { |
| this->featureInfo()->hasSyncBufferData = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanAsyncQsri() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kVulkanAsyncQsri) != std::string::npos) { |
| this->featureInfo()->hasVulkanAsyncQsri = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetReadColorBufferDma() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kReadColorBufferDma) != std::string::npos) { |
| this->featureInfo()->hasReadColorBufferDma = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetHWCMultiConfigs() { |
| std::string hostExtensions = queryHostExtensions(); |
| if (hostExtensions.find(kHWCMultiConfigs) != std::string::npos) { |
| this->featureInfo()->hasHWCMultiConfigs = true; |
| } |
| } |
| |
| void ExtendedRCEncoderContext::queryAndSetVulkanAuxCommandBufferMemory() { |
| std::string hostExtensions = queryHostExtensions(); |
| this->featureInfo()->hasVulkanAuxCommandMemory = |
| hostExtensions.find(kVulkanAuxCommandMemory) != std::string::npos; |
| } |
| |
| GLint ExtendedRCEncoderContext::queryVersion() { |
| GLint version = this->rcGetRendererVersion(this); |
| return version; |
| } |
| |
| void ExtendedRCEncoderContext::setVulkanFeatureInfo(void* info) { |
| struct EmulatorGfxStreamVkFeatureInfo* featureInfo = |
| (struct EmulatorGfxStreamVkFeatureInfo*)info; |
| |
| featureInfo->hasDirectMem = this->featureInfo()->hasDirectMem; |
| featureInfo->hasVulkan = this->featureInfo()->hasVulkan; |
| featureInfo->hasDeferredVulkanCommands = this->featureInfo()->hasDeferredVulkanCommands; |
| featureInfo->hasVulkanNullOptionalStrings = this->featureInfo()->hasVulkanNullOptionalStrings; |
| featureInfo->hasVulkanCreateResourcesWithRequirements = |
| this->featureInfo()->hasVulkanCreateResourcesWithRequirements; |
| featureInfo->hasVulkanIgnoredHandles = this->featureInfo()->hasVulkanIgnoredHandles; |
| featureInfo->hasVirtioGpuNext = this->featureInfo()->hasVirtioGpuNext; |
| featureInfo->hasVulkanFreeMemorySync = this->featureInfo()->hasVulkanFreeMemorySync; |
| featureInfo->hasVirtioGpuNativeSync = this->featureInfo()->hasVirtioGpuNativeSync; |
| featureInfo->hasVulkanShaderFloat16Int8 = this->featureInfo()->hasVulkanShaderFloat16Int8; |
| featureInfo->hasVulkanAsyncQueueSubmit = this->featureInfo()->hasVulkanAsyncQueueSubmit; |
| featureInfo->hasVulkanQueueSubmitWithCommands = |
| this->featureInfo()->hasVulkanQueueSubmitWithCommands; |
| featureInfo->hasVulkanBatchedDescriptorSetUpdate = |
| this->featureInfo()->hasVulkanBatchedDescriptorSetUpdate; |
| featureInfo->hasVulkanAsyncQsri = this->featureInfo()->hasVulkanAsyncQsri; |
| featureInfo->hasVulkanAuxCommandMemory = this->featureInfo()->hasVulkanAuxCommandMemory; |
| } |