diff options
author | Jason Macnak <natsu@google.com> | 2024-05-21 13:46:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-21 13:46:54 +0000 |
commit | 2ce3894362b8afb5bb0a2a26faec72474dd819b6 (patch) | |
tree | debf339f8f83bf8658e91017ca583053b349052d | |
parent | 25b42040aeefebda329b03af7e19c3cb97346793 (diff) | |
parent | 0542653cd3e3fe7d4023c30e6ac2b6b2a04a847c (diff) | |
download | gfxstream-master.tar.gz |
-rw-r--r-- | common/end2end/GfxstreamEnd2EndCompositionTests.cpp | 76 | ||||
-rw-r--r-- | common/end2end/GfxstreamEnd2EndTests.cpp | 15 | ||||
-rw-r--r-- | common/end2end/GfxstreamEnd2EndTests.h | 2 | ||||
-rw-r--r-- | guest/android/GrallocEmulated.cpp | 7 | ||||
-rw-r--r-- | host/vulkan/CompositorVk.cpp | 70 | ||||
-rw-r--r-- | host/vulkan/CompositorVk.h | 11 |
6 files changed, 162 insertions, 19 deletions
diff --git a/common/end2end/GfxstreamEnd2EndCompositionTests.cpp b/common/end2end/GfxstreamEnd2EndCompositionTests.cpp index 56d5da23..2f54f70b 100644 --- a/common/end2end/GfxstreamEnd2EndCompositionTests.cpp +++ b/common/end2end/GfxstreamEnd2EndCompositionTests.cpp @@ -100,6 +100,82 @@ TEST_P(GfxstreamEnd2EndCompositionTest, BasicComposition) { GL_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png")); } +TEST_P(GfxstreamEnd2EndCompositionTest, BasicCompositionBGRA) { + ScopedRenderControlDevice rcDevice(*mRc); + + auto layer1Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android.png")); + auto layer2Ahb = GL_ASSERT(CreateAHBFromImage("256x256_android_with_transparency.png")); + auto resultAhb = GL_ASSERT( + ScopedAHardwareBuffer::Allocate(*mGralloc, 256, 256, GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM)); + + const RenderControlComposition composition = { + .displayId = 0, + .compositionResultColorBufferHandle = mGralloc->getHostHandle(resultAhb), + }; + const RenderControlCompositionLayer compositionLayers[2] = { + { + .colorBufferHandle = mGralloc->getHostHandle(layer1Ahb), + .composeMode = HWC2_COMPOSITION_DEVICE, + .displayFrame = + { + .left = 0, + .top = 0, + .right = 256, + .bottom = 256, + }, + .crop = + { + .left = 0, + .top = 0, + .right = static_cast<float>(256), + .bottom = static_cast<float>(256), + }, + .blendMode = HWC2_BLEND_MODE_PREMULTIPLIED, + .alpha = 1.0, + .color = + { + .r = 0, + .g = 0, + .b = 0, + .a = 0, + }, + .transform = static_cast<hwc_transform_t>(0), + }, + { + .colorBufferHandle = mGralloc->getHostHandle(layer2Ahb), + .composeMode = HWC2_COMPOSITION_DEVICE, + .displayFrame = + { + .left = 64, + .top = 32, + .right = 128, + .bottom = 160, + }, + .crop = + { + .left = 0, + .top = 0, + .right = static_cast<float>(256), + .bottom = static_cast<float>(256), + }, + .blendMode = HWC2_BLEND_MODE_PREMULTIPLIED, + .alpha = 1.0, + .color = + { + .r = 0, + .g = 0, + .b = 0, + .a = 0, + }, + .transform = static_cast<hwc_transform_t>(0), + }, + }; + + ASSERT_THAT(mRc->rcCompose(rcDevice, &composition, 2, compositionLayers), Eq(0)); + + GL_ASSERT(CompareAHBWithGolden(resultAhb, "256x256_golden_basic_composition.png")); +} + INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndCompositionTest, ::testing::ValuesIn({ TestParams{ diff --git a/common/end2end/GfxstreamEnd2EndTests.cpp b/common/end2end/GfxstreamEnd2EndTests.cpp index 00b9c429..660cbf82 100644 --- a/common/end2end/GfxstreamEnd2EndTests.cpp +++ b/common/end2end/GfxstreamEnd2EndTests.cpp @@ -652,11 +652,26 @@ GlExpected<Image> GfxstreamEnd2EndTest::AsImage(ScopedAHardwareBuffer& ahb) { return android::base::unexpected("Failed to query AHB height."); } actual.pixels.resize(actual.width * actual.height); + + const uint32_t ahbFormat = ahb.GetAHBFormat(); + if (ahbFormat != GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM && + ahbFormat != GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM) { + return android::base::unexpected("Unhandled AHB format " + std::to_string(ahbFormat)); + } + { uint8_t* ahbPixels = GL_EXPECT(ahb.Lock()); std::memcpy(actual.pixels.data(), ahbPixels, actual.pixels.size() * sizeof(uint32_t)); ahb.Unlock(); } + + if (ahbFormat == GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM) { + for (uint32_t& pixel : actual.pixels) { + uint8_t* pixelComponents = reinterpret_cast<uint8_t*>(&pixel); + std::swap(pixelComponents[0], pixelComponents[2]); + } + } + return actual; } diff --git a/common/end2end/GfxstreamEnd2EndTests.h b/common/end2end/GfxstreamEnd2EndTests.h index 35c7579e..0654ab7f 100644 --- a/common/end2end/GfxstreamEnd2EndTests.h +++ b/common/end2end/GfxstreamEnd2EndTests.h @@ -417,6 +417,8 @@ class ScopedAHardwareBuffer { uint32_t GetHeight() const { return mGralloc->getHeight(mHandle); } + uint32_t GetAHBFormat() const { return mGralloc->getFormat(mHandle); } + GlExpected<uint8_t*> Lock() { uint8_t* mapped = nullptr; int status = mGralloc->lock(mHandle, &mapped); diff --git a/guest/android/GrallocEmulated.cpp b/guest/android/GrallocEmulated.cpp index cf0e427b..4aa7e9ab 100644 --- a/guest/android/GrallocEmulated.cpp +++ b/guest/android/GrallocEmulated.cpp @@ -59,6 +59,8 @@ std::optional<uint32_t> AhbToDrmFormat(uint32_t ahbFormat) { */ case GFXSTREAM_AHB_FORMAT_R5G6B5_UNORM: return DRM_FORMAT_RGB565; + case GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM: + return DRM_FORMAT_ARGB8888; case GFXSTREAM_AHB_FORMAT_BLOB: return DRM_FORMAT_R8_BLOB; case GFXSTREAM_AHB_FORMAT_R8_UNORM: @@ -79,6 +81,8 @@ std::optional<uint32_t> DrmToAhbFormat(uint32_t drmFormat) { return GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM; case DRM_FORMAT_XBGR8888: return GFXSTREAM_AHB_FORMAT_R8G8B8X8_UNORM; + case DRM_FORMAT_ARGB8888: + return GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM; case DRM_FORMAT_BGR888: return GFXSTREAM_AHB_FORMAT_R8G8B8_UNORM; case DRM_FORMAT_RGB565: @@ -100,6 +104,7 @@ std::optional<uint32_t> DrmToAhbFormat(uint32_t drmFormat) { std::optional<uint32_t> DrmToBpp(uint32_t drmFormat) { switch (drmFormat) { case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_ARGB8888: case DRM_FORMAT_XBGR8888: return 4; case DRM_FORMAT_BGR888: @@ -117,6 +122,8 @@ std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) { switch (drmFormat) { case DRM_FORMAT_ABGR8888: return VIRGL_FORMAT_R8G8B8A8_UNORM; + case DRM_FORMAT_ARGB8888: + return VIRGL_FORMAT_B8G8R8A8_UNORM; case DRM_FORMAT_BGR888: return VIRGL_FORMAT_R8G8B8_UNORM; case DRM_FORMAT_BGR565: diff --git a/host/vulkan/CompositorVk.cpp b/host/vulkan/CompositorVk.cpp index 39f7e514..e96ab3b8 100644 --- a/host/vulkan/CompositorVk.cpp +++ b/host/vulkan/CompositorVk.cpp @@ -182,8 +182,10 @@ CompositorVk::~CompositorVk() { m_vk.vkDestroyBuffer(m_vkDevice, m_vertexVkBuffer, nullptr); m_vk.vkFreeMemory(m_vkDevice, m_indexVkDeviceMemory, nullptr); m_vk.vkDestroyBuffer(m_vkDevice, m_indexVkBuffer, nullptr); - m_vk.vkDestroyPipeline(m_vkDevice, m_graphicsVkPipeline, nullptr); - m_vk.vkDestroyRenderPass(m_vkDevice, m_vkRenderPass, nullptr); + for (auto& [_, formatResources] : m_formatResources) { + m_vk.vkDestroyPipeline(m_vkDevice, formatResources.m_graphicsVkPipeline, nullptr); + m_vk.vkDestroyRenderPass(m_vkDevice, formatResources.m_vkRenderPass, nullptr); + } m_vk.vkDestroyPipelineLayout(m_vkDevice, m_vkPipelineLayout, nullptr); m_vk.vkDestroySampler(m_vkDevice, m_vkSampler, nullptr); m_vk.vkDestroyDescriptorSetLayout(m_vkDevice, m_vkDescriptorSetLayout, nullptr); @@ -331,8 +333,8 @@ void CompositorVk::setUpGraphicsPipeline() { VK_CHECK( m_vk.vkCreatePipelineLayout(m_vkDevice, &pipelineLayoutCi, nullptr, &m_vkPipelineLayout)); - const VkAttachmentDescription colorAttachment = { - .format = VK_FORMAT_R8G8B8A8_UNORM, + VkAttachmentDescription colorAttachment = { + .format = VK_FORMAT_UNDEFINED, .samples = VK_SAMPLE_COUNT_1_BIT, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, @@ -375,9 +377,8 @@ void CompositorVk::setUpGraphicsPipeline() { .dependencyCount = 1, .pDependencies = &subpassDependency, }; - VK_CHECK(m_vk.vkCreateRenderPass(m_vkDevice, &renderPassCi, nullptr, &m_vkRenderPass)); - const VkGraphicsPipelineCreateInfo graphicsPipelineCi = { + VkGraphicsPipelineCreateInfo graphicsPipelineCi = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .stageCount = static_cast<uint32_t>(std::size(shaderStageCis)), .pStages = shaderStageCis, @@ -390,13 +391,33 @@ void CompositorVk::setUpGraphicsPipeline() { .pColorBlendState = &colorBlendStateCi, .pDynamicState = &dynamicStateCi, .layout = m_vkPipelineLayout, - .renderPass = m_vkRenderPass, + .renderPass = VK_NULL_HANDLE, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = -1, }; - VK_CHECK(m_vk.vkCreateGraphicsPipelines(m_vkDevice, VK_NULL_HANDLE, 1, &graphicsPipelineCi, - nullptr, &m_graphicsVkPipeline)); + + const std::vector<VkFormat> kRenderTargetFormats = { + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_B8G8R8A8_UNORM, + }; + for (VkFormat renderTargetFormat : kRenderTargetFormats) { + colorAttachment.format = renderTargetFormat; + + VkRenderPass renderPass = VK_NULL_HANDLE; + VK_CHECK(m_vk.vkCreateRenderPass(m_vkDevice, &renderPassCi, nullptr, &renderPass)); + + graphicsPipelineCi.renderPass = renderPass; + + VkPipeline pipeline = VK_NULL_HANDLE; + VK_CHECK(m_vk.vkCreateGraphicsPipelines(m_vkDevice, VK_NULL_HANDLE, 1, &graphicsPipelineCi, + nullptr, &pipeline)); + + m_formatResources[renderTargetFormat] = PerFormatResources{ + .m_vkRenderPass = renderPass, + .m_graphicsVkPipeline = pipeline, + }; + } m_vk.vkDestroyShaderModule(m_vkDevice, vertShaderMod, nullptr); m_vk.vkDestroyShaderModule(m_vkDevice, fragShaderMod, nullptr); @@ -862,9 +883,16 @@ CompositorVk::RenderTarget* CompositorVk::getOrCreateRenderTargetInfo( return renderTargetPtr->get(); } - auto* renderTarget = new RenderTarget(m_vk, m_vkDevice, imageInfo.image, imageInfo.imageView, - imageInfo.imageCreateInfo.extent.width, - imageInfo.imageCreateInfo.extent.height, m_vkRenderPass); + auto formatResourcesIt = m_formatResources.find(imageInfo.imageCreateInfo.format); + if (formatResourcesIt == m_formatResources.end()) { + return nullptr; + } + auto& formatResources = formatResourcesIt->second; + + auto* renderTarget = + new RenderTarget(m_vk, m_vkDevice, imageInfo.image, imageInfo.imageView, + imageInfo.imageCreateInfo.extent.width, + imageInfo.imageCreateInfo.extent.height, formatResources.m_vkRenderPass); m_renderTargetCache.set(imageInfo.id, std::unique_ptr<RenderTarget>(renderTarget)); @@ -898,7 +926,8 @@ bool CompositorVk::canCompositeTo(const VkImageCreateInfo& imageCi) { string_VkImageUsageFlags(imageCi.usage).c_str()); return false; } - if (imageCi.format != k_renderTargetFormat) { + + if (m_formatResources.find(imageCi.format) == m_formatResources.end()) { ERR("The format of the image, %s, is not supported by the CompositorVk as the render " "target.", string_VkFormat(imageCi.format)); @@ -910,13 +939,24 @@ bool CompositorVk::canCompositeTo(const VkImageCreateInfo& imageCi) { void CompositorVk::buildCompositionVk(const CompositionRequest& compositionRequest, CompositionVk* compositionVk) { const BorrowedImageInfoVk* targetImage = getInfoOrAbort(compositionRequest.target); + + auto formatResourcesIt = m_formatResources.find(targetImage->imageCreateInfo.format); + if (formatResourcesIt == m_formatResources.end()) { + GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) + << "CompositorVk did not find format resource for format " + << targetImage->imageCreateInfo.format; + } + const auto& formatResources = formatResourcesIt->second; + RenderTarget* targetImageRenderTarget = getOrCreateRenderTargetInfo(*targetImage); const uint32_t targetWidth = targetImage->width; const uint32_t targetHeight = targetImage->height; compositionVk->targetImage = targetImage; + compositionVk->targetRenderPass = formatResources.m_vkRenderPass; compositionVk->targetFramebuffer = targetImageRenderTarget->m_vkFramebuffer; + compositionVk->pipeline = formatResources.m_graphicsVkPipeline; for (const CompositionRequestLayer& layer : compositionRequest.layers) { uint32_t sourceImageWidth = 0; @@ -1123,7 +1163,7 @@ CompositorVk::CompositionFinishedWaitable CompositorVk::compose( }; const VkRenderPassBeginInfo renderPassBeginInfo = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = m_vkRenderPass, + .renderPass = compositionVk.targetRenderPass, .framebuffer = compositionVk.targetFramebuffer, .renderArea = { @@ -1143,7 +1183,7 @@ CompositorVk::CompositionFinishedWaitable CompositorVk::compose( }; m_vk.vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - m_vk.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsVkPipeline); + m_vk.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, compositionVk.pipeline); const VkRect2D scissor = { .offset = diff --git a/host/vulkan/CompositorVk.h b/host/vulkan/CompositorVk.h index a5fc688c..3fe5676b 100644 --- a/host/vulkan/CompositorVk.h +++ b/host/vulkan/CompositorVk.h @@ -46,8 +46,11 @@ struct CompositorVkBase : public vk_util::MultiCrtp<CompositorVkBase, // std::shared_ptr<android::base::Lock> m_vkQueueLock; VkDescriptorSetLayout m_vkDescriptorSetLayout; VkPipelineLayout m_vkPipelineLayout; - VkRenderPass m_vkRenderPass; - VkPipeline m_graphicsVkPipeline; + struct PerFormatResources { + VkRenderPass m_vkRenderPass = VK_NULL_HANDLE; + VkPipeline m_graphicsVkPipeline = VK_NULL_HANDLE; + }; + std::unordered_map<VkFormat, PerFormatResources> m_formatResources; VkBuffer m_vertexVkBuffer; VkDeviceMemory m_vertexVkDeviceMemory; VkBuffer m_indexVkBuffer; @@ -130,8 +133,6 @@ struct CompositorVkBase : public vk_util::MultiCrtp<CompositorVkBase, // m_vkQueueLock(queueLock), m_vkDescriptorSetLayout(VK_NULL_HANDLE), m_vkPipelineLayout(VK_NULL_HANDLE), - m_vkRenderPass(VK_NULL_HANDLE), - m_graphicsVkPipeline(VK_NULL_HANDLE), m_vertexVkBuffer(VK_NULL_HANDLE), m_vertexVkDeviceMemory(VK_NULL_HANDLE), m_indexVkBuffer(VK_NULL_HANDLE), @@ -205,7 +206,9 @@ class CompositorVk : protected CompositorVkBase, public Compositor { // the Vulkan components needed for command recording and submission. struct CompositionVk { const BorrowedImageInfoVk* targetImage = nullptr; + VkRenderPass targetRenderPass = VK_NULL_HANDLE; VkFramebuffer targetFramebuffer = VK_NULL_HANDLE; + VkPipeline pipeline = VK_NULL_HANDLE; std::vector<const BorrowedImageInfoVk*> layersSourceImages; FrameDescriptorSetsContents layersDescriptorSets; }; |