Hash :
bd7915fd
Author :
Date :
2022-04-04T10:02:29
Use provided format as intended format for EGLImage from VkImage The problem is because VkImage is created with R8G8B8A8 format, and then imported into ANGLE as EGLImage with GL_RGB format, however ANGLE doesn't set intended format correctly (ANGLE uses R8G8B8A8 instead of R8G8B8X8). So when clients use glReadPixels() to get pixels, the alpha channel is filled with incorrect value. Bug: chromium:1312490 Change-Id: Ief5b87ec5eb03c9cb37f10b2c20b5caf3013262d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3569481 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Peng Huang <penghuang@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VkImageImageSiblingVk.cpp: Implements VkImageImageSiblingVk.
#include "libANGLE/renderer/vulkan/VkImageImageSiblingVk.h"
#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
VkImageImageSiblingVk::VkImageImageSiblingVk(EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
mVkImage.setHandle(*reinterpret_cast<VkImage *>(buffer));
ASSERT(attribs.contains(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
ASSERT(attribs.contains(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
uint64_t hi = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE));
uint64_t lo = static_cast<uint64_t>(attribs.get(EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE));
const VkImageCreateInfo *info =
reinterpret_cast<const VkImageCreateInfo *>((hi << 32) | (lo & 0xffffffff));
ASSERT(info->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
mVkImageInfo = *info;
// TODO(penghuang): support extensions.
mVkImageInfo.pNext = nullptr;
mInternalFormat = static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_NONE));
}
VkImageImageSiblingVk::~VkImageImageSiblingVk() = default;
egl::Error VkImageImageSiblingVk::initialize(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);
return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
}
angle::Result VkImageImageSiblingVk::initImpl(DisplayVk *displayVk)
{
RendererVk *renderer = displayVk->getRenderer();
const angle::FormatID formatID = vk::GetFormatIDFromVkFormat(mVkImageInfo.format);
ANGLE_VK_CHECK(displayVk, formatID != angle::FormatID::NONE, VK_ERROR_FORMAT_NOT_SUPPORTED);
const vk::Format &vkFormat = renderer->getFormat(formatID);
const vk::ImageAccess imageAccess =
isRenderable(nullptr) ? vk::ImageAccess::Renderable : vk::ImageAccess::SampleOnly;
const angle::FormatID actualImageFormatID = vkFormat.getActualImageFormatID(imageAccess);
const angle::Format &format = angle::Format::Get(actualImageFormatID);
angle::FormatID intendedFormatID;
if (mInternalFormat != GL_NONE)
{
// If EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is provided for eglCreateImageKHR(),
// the provided format will be used for mFormat and intendedFormat.
intendedFormatID = angle::Format::InternalFormatToID(mInternalFormat);
GLenum type = gl::GetSizedInternalFormatInfo(format.glInternalFormat).type;
mFormat = gl::Format(mInternalFormat, type);
}
else
{
intendedFormatID = vkFormat.getIntendedFormatID();
mFormat = gl::Format(format.glInternalFormat);
}
// Create the image
mImage = new vk::ImageHelper();
constexpr bool kIsRobustInitEnabled = false;
mImage->init2DWeakReference(displayVk, mVkImage.release(), getSize(), false, intendedFormatID,
actualImageFormatID, 1, kIsRobustInitEnabled);
return angle::Result::Continue;
}
void VkImageImageSiblingVk::onDestroy(const egl::Display *display)
{
ASSERT(mImage == nullptr);
}
gl::Format VkImageImageSiblingVk::getFormat() const
{
return mFormat;
}
bool VkImageImageSiblingVk::isRenderable(const gl::Context *context) const
{
return mVkImageInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
bool VkImageImageSiblingVk::isTexturable(const gl::Context *context) const
{
return mVkImageInfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT;
}
bool VkImageImageSiblingVk::isYUV() const
{
return false;
}
bool VkImageImageSiblingVk::hasProtectedContent() const
{
return false;
}
gl::Extents VkImageImageSiblingVk::getSize() const
{
return gl::Extents(mVkImageInfo.extent.width, mVkImageInfo.extent.height,
mVkImageInfo.extent.depth);
}
size_t VkImageImageSiblingVk::getSamples() const
{
return 0;
}
// ExternalImageSiblingVk interface
vk::ImageHelper *VkImageImageSiblingVk::getImage() const
{
return mImage;
}
void VkImageImageSiblingVk::release(RendererVk *renderer)
{
if (mImage != nullptr)
{
// TODO: Handle the case where the EGLImage is used in two contexts not in the same share
// group. https://issuetracker.google.com/169868803
mImage->releaseImageAndViewGarbage(renderer);
mImage->resetImageWeakReference();
mImage->destroy(renderer);
SafeDelete(mImage);
}
}
} // namespace rx