aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Macnak <natsu@google.com>2024-05-21 13:46:54 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-05-21 13:46:54 +0000
commit2ce3894362b8afb5bb0a2a26faec72474dd819b6 (patch)
treedebf339f8f83bf8658e91017ca583053b349052d
parent25b42040aeefebda329b03af7e19c3cb97346793 (diff)
parent0542653cd3e3fe7d4023c30e6ac2b6b2a04a847c (diff)
downloadgfxstream-master.tar.gz
Merge "Support BGRA render target in CompositorVk" into mainHEADmastermain
-rw-r--r--common/end2end/GfxstreamEnd2EndCompositionTests.cpp76
-rw-r--r--common/end2end/GfxstreamEnd2EndTests.cpp15
-rw-r--r--common/end2end/GfxstreamEnd2EndTests.h2
-rw-r--r--guest/android/GrallocEmulated.cpp7
-rw-r--r--host/vulkan/CompositorVk.cpp70
-rw-r--r--host/vulkan/CompositorVk.h11
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;
};