//
// 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.
//

// DmaBufImageSiblingVkLinux.cpp: Implements DmaBufImageSiblingVkLinux.

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.h"

#include "common/linux/dma_buf_utils.h"
#include "common/system_utils.h"
#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"

#include <fcntl.h>

namespace rx
{
namespace
{
constexpr uint32_t kMaxPlaneCount = 4;
template <typename T>
using PerPlane = std::array<T, kMaxPlaneCount>;

constexpr PerPlane<EGLenum> kFds = {EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE1_FD_EXT,
                                    EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE3_FD_EXT};

constexpr PerPlane<EGLenum> kOffsets = {
    EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT, EGL_DMA_BUF_PLANE2_OFFSET_EXT,
    EGL_DMA_BUF_PLANE3_OFFSET_EXT};

constexpr PerPlane<EGLenum> kPitches = {EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT,
                                        EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT};

constexpr PerPlane<EGLenum> kModifiersLo = {
    EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
    EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT};

constexpr PerPlane<EGLenum> kModifiersHi = {
    EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT,
    EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT};

constexpr VkImageUsageFlags kTransferUsage =
    VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
constexpr VkImageUsageFlags kTextureUsage = VK_IMAGE_USAGE_SAMPLED_BIT;
constexpr VkImageUsageFlags kRenderUsage =
    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
constexpr VkImageUsageFlags kRenderAndInputUsage =
    kRenderUsage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;

struct AllocateInfo
{
    PerPlane<VkMemoryDedicatedAllocateInfo> allocateInfo = {};
    PerPlane<VkImportMemoryFdInfoKHR> importFdInfo       = {};

    PerPlane<const void *> allocateInfoPtr = {};
};

// Look at provided fds and count the number of planes based on that.
uint32_t GetPlaneCount(const egl::AttributeMap &attribs)
{
    // There should always be at least one plane.
    ASSERT(attribs.contains(kFds[0]));
    ASSERT(attribs.contains(kOffsets[0]));
    ASSERT(attribs.contains(kPitches[0]));

    for (uint32_t plane = 1; plane < kMaxPlaneCount; ++plane)
    {
        if (!attribs.contains(kFds[plane]))
        {
            return plane;
        }

        ASSERT(attribs.contains(kOffsets[plane]));
        ASSERT(attribs.contains(kPitches[plane]));
    }

    return kMaxPlaneCount;
}

uint64_t GetModifier(const egl::AttributeMap &attribs, EGLenum lo, EGLenum hi)
{
    if (!attribs.contains(lo))
    {
        return 0;
    }

    ASSERT(attribs.contains(hi));

    uint64_t modifier = attribs.getAsInt(hi);
    modifier          = modifier << 32 | attribs.getAsInt(lo);

    return modifier;
}

void GetModifiers(const egl::AttributeMap &attribs,
                  uint32_t planeCount,
                  PerPlane<uint64_t> *drmModifiersOut)
{
    for (uint32_t plane = 0; plane < planeCount; ++plane)
    {
        (*drmModifiersOut)[plane] = GetModifier(attribs, kModifiersLo[plane], kModifiersHi[plane]);
    }
}

bool GetFormatModifierProperties(DisplayVk *displayVk,
                                 VkFormat vkFormat,
                                 uint64_t drmModifier,
                                 VkDrmFormatModifierPropertiesEXT *modifierPropertiesOut)
{
    vk::Renderer *renderer = displayVk->getRenderer();

    // Query list of drm format modifiers compatible with VkFormat.
    VkDrmFormatModifierPropertiesListEXT formatModifierPropertiesList = {};
    formatModifierPropertiesList.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT;
    formatModifierPropertiesList.drmFormatModifierCount = 0;

    VkFormatProperties2 formatProperties = {};
    formatProperties.sType               = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
    formatProperties.pNext               = &formatModifierPropertiesList;

    vkGetPhysicalDeviceFormatProperties2(renderer->getPhysicalDevice(), vkFormat,
                                         &formatProperties);

    std::vector<VkDrmFormatModifierPropertiesEXT> formatModifierProperties(
        formatModifierPropertiesList.drmFormatModifierCount);
    formatModifierPropertiesList.pDrmFormatModifierProperties = formatModifierProperties.data();

    vkGetPhysicalDeviceFormatProperties2(renderer->getPhysicalDevice(), vkFormat,
                                         &formatProperties);

    // Find the requested DRM modifiers.
    uint32_t propertiesIndex = formatModifierPropertiesList.drmFormatModifierCount;
    for (uint32_t index = 0; index < formatModifierPropertiesList.drmFormatModifierCount; ++index)
    {
        if (formatModifierPropertiesList.pDrmFormatModifierProperties[index].drmFormatModifier ==
            drmModifier)
        {
            propertiesIndex = index;
            break;
        }
    }

    // Return the properties if found.
    if (propertiesIndex >= formatModifierPropertiesList.drmFormatModifierCount)
    {
        return false;
    }

    *modifierPropertiesOut =
        formatModifierPropertiesList.pDrmFormatModifierProperties[propertiesIndex];
    return true;
}

VkImageUsageFlags GetUsageFlags(vk::Renderer *renderer,
                                const angle::Format &format,
                                const VkDrmFormatModifierPropertiesEXT &properties,
                                bool *texturableOut,
                                bool *renderableOut)
{
    const bool isDepthStencilFormat = format.hasDepthOrStencilBits();

    // Check what format features are exposed for this modifier.
    constexpr uint32_t kTextureableRequiredBits =
        VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
    constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
    constexpr uint32_t kDepthStencilRenderableRequiredBits =
        VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;

    *texturableOut =
        IsMaskFlagSet(properties.drmFormatModifierTilingFeatures, kTextureableRequiredBits);
    *renderableOut = IsMaskFlagSet(
        properties.drmFormatModifierTilingFeatures,
        isDepthStencilFormat ? kDepthStencilRenderableRequiredBits : kColorRenderableRequiredBits);

    VkImageUsageFlags usage = kTransferUsage;
    if (*texturableOut)
    {
        usage |= kTextureUsage;
    }
    if (*renderableOut)
    {
        usage |= isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
                                      : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    }
    if (*texturableOut && *renderableOut)
    {
        usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
    }

    return usage;
}

bool IsFormatSupported(vk::Renderer *renderer,
                       VkFormat vkFormat,
                       uint64_t drmModifier,
                       VkImageUsageFlags usageFlags,
                       VkImageCreateFlags createFlags,
                       VkImageFormatListCreateInfoKHR imageFormatListInfo,
                       VkImageFormatProperties2 *imageFormatPropertiesOut)
{
    VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {};
    externalImageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
    externalImageFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
    imageFormatListInfo.pNext          = &externalImageFormatInfo;

    VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
    imageFormatInfo.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
    imageFormatInfo.format = vkFormat;
    imageFormatInfo.type   = VK_IMAGE_TYPE_2D;
    imageFormatInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
    imageFormatInfo.usage  = usageFlags;
    imageFormatInfo.flags  = createFlags;
    imageFormatInfo.pNext  = &imageFormatListInfo;

    VkPhysicalDeviceImageDrmFormatModifierInfoEXT drmFormatModifierInfo = {};
    drmFormatModifierInfo.sType =
        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT;
    drmFormatModifierInfo.drmFormatModifier = drmModifier;
    drmFormatModifierInfo.sharingMode       = VK_SHARING_MODE_EXCLUSIVE;
    externalImageFormatInfo.pNext           = &drmFormatModifierInfo;

    return vkGetPhysicalDeviceImageFormatProperties2(renderer->getPhysicalDevice(),
                                                     &imageFormatInfo, imageFormatPropertiesOut) !=
           VK_ERROR_FORMAT_NOT_SUPPORTED;
}

VkChromaLocation GetChromaLocation(const egl::AttributeMap &attribs, EGLenum hint)
{
    return attribs.getAsInt(hint, EGL_YUV_CHROMA_SITING_0_EXT) == EGL_YUV_CHROMA_SITING_0_EXT
               ? VK_CHROMA_LOCATION_COSITED_EVEN
               : VK_CHROMA_LOCATION_MIDPOINT;
}

VkSamplerYcbcrModelConversion GetYcbcrModel(const egl::AttributeMap &attribs)
{
    switch (attribs.getAsInt(EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_ITU_REC601_EXT))
    {
        case EGL_ITU_REC601_EXT:
            return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
        case EGL_ITU_REC709_EXT:
            return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
        case EGL_ITU_REC2020_EXT:
            return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020;
        default:
            UNREACHABLE();
            return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
    }
}

VkSamplerYcbcrRange GetYcbcrRange(const egl::AttributeMap &attribs)
{
    return attribs.getAsInt(EGL_SAMPLE_RANGE_HINT_EXT, EGL_YUV_FULL_RANGE_EXT) ==
                   EGL_YUV_FULL_RANGE_EXT
               ? VK_SAMPLER_YCBCR_RANGE_ITU_FULL
               : VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
}

angle::Result GetAllocateInfo(const egl::AttributeMap &attribs,
                              VkImage image,
                              uint32_t planeCount,
                              const VkDrmFormatModifierPropertiesEXT &properties,
                              AllocateInfo *infoOut,
                              uint32_t *infoCountOut)
{
    // There are a number of situations:
    //
    // - If the format tilingFeatures does not have the DISJOINT bit, then allocation and bind is
    //   done as usual; the fd is used to create the allocation and vkBindImageMemory is called
    //   without any extra bind info (which would need vkBindImageMemory2).
    // - If the format tilingFeatures does have the DISJOINT bit, but all fds are identical, it's
    //   handled similarly to the non-disjoint case.
    // - Otherwise if there are N planes, there must be N allocations and N binds (one per fd).
    //   When binding, VkBindImagePlaneMemoryInfo is used to identify which plane is being bound.
    //
    constexpr uint32_t kDisjointBit = VK_FORMAT_FEATURE_DISJOINT_BIT;
    bool isDisjoint =
        planeCount > 1 && IsMaskFlagSet(properties.drmFormatModifierTilingFeatures, kDisjointBit);
    if (isDisjoint)
    {
        bool areFdsIdentical = true;
        for (uint32_t plane = 1; plane < planeCount; ++plane)
        {
            if (!angle::IsSameFileDescriptor(attribs.getAsInt(kFds[plane]),
                                             attribs.getAsInt(kFds[0])))
            {
                areFdsIdentical = false;
                break;
            }
        }

        // Treat DISJOINT-but-identical-fds as non-disjoint.
        if (areFdsIdentical)
        {
            isDisjoint = false;
        }
    }

    // Fill in allocateInfo, importFdInfo, bindInfo and bindPlaneInfo first.
    *infoCountOut = isDisjoint ? planeCount : 1;
    for (uint32_t plane = 0; plane < *infoCountOut; ++plane)
    {
        infoOut->allocateInfo[plane].sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
        infoOut->allocateInfo[plane].pNext = &infoOut->importFdInfo[plane];
        infoOut->allocateInfo[plane].image = image;

        infoOut->importFdInfo[plane].sType      = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
        infoOut->importFdInfo[plane].handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;

        // Vulkan takes ownership of the FD, closed on vkFreeMemory.
        int dfd = fcntl(attribs.getAsInt(kFds[plane]), F_DUPFD_CLOEXEC, 0);
        if (dfd < 0)
        {
            ERR() << "failed to duplicate fd for dma_buf import" << std::endl;
            return angle::Result::Stop;
        }
        infoOut->importFdInfo[plane].fd = dfd;

        infoOut->allocateInfoPtr[plane] = &infoOut->allocateInfo[plane];
    }

    return angle::Result::Continue;
}
}  // anonymous namespace

DmaBufImageSiblingVkLinux::DmaBufImageSiblingVkLinux(const egl::AttributeMap &attribs)
    : mAttribs(attribs),
      mFormat(GL_NONE),
      mVkFormats(),
      mRenderable(false),
      mTextureable(false),
      mYUV(false),
      mSamples(0),
      mImage(nullptr)
{
    ASSERT(mAttribs.contains(EGL_WIDTH));
    ASSERT(mAttribs.contains(EGL_HEIGHT));
    mSize.width  = mAttribs.getAsInt(EGL_WIDTH);
    mSize.height = mAttribs.getAsInt(EGL_HEIGHT);
    mSize.depth  = 1;

    int fourCCFormat = mAttribs.getAsInt(EGL_LINUX_DRM_FOURCC_EXT);
    mFormat          = gl::Format(angle::DrmFourCCFormatToGLInternalFormat(fourCCFormat, &mYUV));
    mVkFormats       = angle::DrmFourCCFormatToVkFormats(fourCCFormat);

    mHasProtectedContent = mAttribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, false);
}

DmaBufImageSiblingVkLinux::~DmaBufImageSiblingVkLinux() {}

egl::Error DmaBufImageSiblingVkLinux::initialize(const egl::Display *display)
{
    DisplayVk *displayVk = vk::GetImpl(display);
    return angle::ToEGL(initImpl(displayVk), EGL_BAD_PARAMETER);
}

VkImageUsageFlags FindSupportedUsageFlagsForFormat(
    vk::Renderer *renderer,
    VkFormat format,
    uint64_t drmModifier,
    VkImageFormatListCreateInfo imageFormatListCreateInfo,
    VkImageUsageFlags usageFlags,
    VkImageCreateFlags createFlags,
    VkImageFormatProperties2 *outImageFormatProperties)
{
    if (!IsFormatSupported(renderer, format, drmModifier, usageFlags, createFlags,
                           imageFormatListCreateInfo, outImageFormatProperties))
    {
        usageFlags &= ~kRenderAndInputUsage;
        if (!IsFormatSupported(renderer, format, drmModifier, usageFlags, createFlags,
                               imageFormatListCreateInfo, outImageFormatProperties))
        {
            usageFlags &= ~kTextureUsage;
            if (!IsFormatSupported(renderer, format, drmModifier, usageFlags, createFlags,
                                   imageFormatListCreateInfo, outImageFormatProperties))
            {
                // Can not find supported usage flags for this image.
                return 0;
            }
        }
    }

    return usageFlags;
}

bool FindSupportedFlagsForFormat(vk::Renderer *renderer,
                                 VkFormat format,
                                 uint64_t drmModifier,
                                 VkImageFormatListCreateInfo imageFormatListCreateInfo,
                                 VkImageUsageFlags *outUsageFlags,
                                 VkImageCreateFlags createFlags,
                                 VkImageFormatProperties2 *outImageFormatProperties)
{
    *outUsageFlags =
        FindSupportedUsageFlagsForFormat(renderer, format, drmModifier, imageFormatListCreateInfo,
                                         *outUsageFlags, createFlags, outImageFormatProperties);
    return *outUsageFlags != 0;
}

angle::Result DmaBufImageSiblingVkLinux::initWithFormat(DisplayVk *displayVk,
                                                        const angle::Format &format,
                                                        VkFormat vulkanFormat,
                                                        MutableFormat mutableFormat,
                                                        InitResult *initResultOut)
{
    *initResultOut         = InitResult::Success;
    vk::Renderer *renderer = displayVk->getRenderer();

    const angle::FormatID intendedFormatID    = vk::GetFormatIDFromVkFormat(vulkanFormat);
    const angle::FormatID actualImageFormatID = vk::GetFormatIDFromVkFormat(vulkanFormat);

    const uint32_t planeCount = GetPlaneCount(mAttribs);

    PerPlane<uint64_t> planeModifiers = {};
    GetModifiers(mAttribs, planeCount, &planeModifiers);

    // The EGL extension allows for each plane to have a different DRM modifier.  This is not
    // allowed in Vulkan, and all hardware past and current require the planes to have the same DRM
    // modifier.  If an application provides different modifiers for the planes, fail.
    const uint64_t plane0Modifier = planeModifiers[0];
    for (uint32_t plane = 0; plane < planeCount; ++plane)
    {
        ANGLE_VK_CHECK(displayVk, planeModifiers[plane] == plane0Modifier,
                       VK_ERROR_INCOMPATIBLE_DRIVER);
    }

    // First, check the possible features for the format and determine usage and create flags.
    VkDrmFormatModifierPropertiesEXT modifierProperties = {};
    if (!GetFormatModifierProperties(displayVk, vulkanFormat, plane0Modifier, &modifierProperties))
    {
        // Format is incompatible
        *initResultOut = InitResult::Failed;
        return angle::Result::Continue;
    }

    VkImageUsageFlags usageFlags =
        GetUsageFlags(renderer, format, modifierProperties, &mTextureable, &mRenderable);

    VkImageCreateFlags createFlags =
        vk::kVkImageCreateFlagsNone | (hasProtectedContent() ? VK_IMAGE_CREATE_PROTECTED_BIT : 0);

    // The Vulkan and EGL plane counts are expected to match.
    ANGLE_VK_CHECK(displayVk, modifierProperties.drmFormatModifierPlaneCount == planeCount,
                   VK_ERROR_INCOMPATIBLE_DRIVER);

    // Verify that such a usage is compatible with the provided modifiers, if any.  If not, try to
    // remove features until it is.
    VkExternalImageFormatProperties externalFormatProperties = {};
    externalFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;

    VkImageFormatProperties2 imageFormatProperties = {};
    imageFormatProperties.sType                    = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
    imageFormatProperties.pNext                    = &externalFormatProperties;

    std::vector<VkSubresourceLayout> planes(planeCount, VkSubresourceLayout{});
    for (uint32_t plane = 0; plane < planeCount; ++plane)
    {
        planes[plane].offset   = mAttribs.getAsInt(kOffsets[plane]);
        planes[plane].rowPitch = mAttribs.getAsInt(kPitches[plane]);
    }

    VkImageDrmFormatModifierExplicitCreateInfoEXT imageDrmModifierCreateInfo = {};
    imageDrmModifierCreateInfo.sType =
        VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
    imageDrmModifierCreateInfo.drmFormatModifier           = plane0Modifier;
    imageDrmModifierCreateInfo.drmFormatModifierPlaneCount = planeCount;
    imageDrmModifierCreateInfo.pPlaneLayouts               = planes.data();

    VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
    externalMemoryImageCreateInfo.sType       = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
    externalMemoryImageCreateInfo.pNext       = &imageDrmModifierCreateInfo;
    externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;

    vk::ImageFormatReinterpretability formatReinterpretability =
        ((usageFlags & VK_IMAGE_USAGE_STORAGE_BIT) == 0)
            ? vk::ImageFormatReinterpretability::ColorspaceOverrides
            : vk::ImageFormatReinterpretability::Full;
    if (mutableFormat == MutableFormat::NotAllowed)
    {
        createFlags &= ~VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
        formatReinterpretability = vk::ImageFormatReinterpretability::None;
    }

    VkImageFormatListCreateInfoKHR imageFormatListCreateInfo;
    vk::ImageHelper::ImageFormats imageFormats;
    const void *imageCreateInfoPNext = vk::ImageHelper::DeriveCreateInfoPNext(
        displayVk, actualImageFormatID, &externalMemoryImageCreateInfo, &imageFormatListCreateInfo,
        &imageFormats, formatReinterpretability, &createFlags);

    if (!FindSupportedFlagsForFormat(renderer, vulkanFormat, plane0Modifier,
                                     imageFormatListCreateInfo, &usageFlags, createFlags,
                                     &imageFormatProperties))
    {
        // The image is not unusable with current flags.
        *initResultOut = InitResult::Failed;
        return angle::Result::Continue;
    }
    mRenderable  = usageFlags & kRenderUsage;
    mTextureable = usageFlags & kTextureUsage;

    // Make sure image width/height/samples are within allowed range and the image is importable.
    const bool isWidthValid = static_cast<uint32_t>(mSize.width) <=
                              imageFormatProperties.imageFormatProperties.maxExtent.width;
    const bool isHeightValid = static_cast<uint32_t>(mSize.height) <=
                               imageFormatProperties.imageFormatProperties.maxExtent.height;
    const bool isSampleCountValid =
        (imageFormatProperties.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_1_BIT) != 0;
    const bool isMemoryImportable =
        (externalFormatProperties.externalMemoryProperties.externalMemoryFeatures &
         VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0;
    ANGLE_VK_CHECK(displayVk,
                   isWidthValid && isHeightValid && isSampleCountValid && isMemoryImportable,
                   VK_ERROR_INCOMPATIBLE_DRIVER);

    // Create the image
    mImage = new vk::ImageHelper();

    VkExtent3D vkExtents;
    gl_vk::GetExtent(mSize, &vkExtents);

    constexpr bool kIsRobustInitEnabled = false;

    vk::YcbcrConversionDesc conversionDesc{};
    if (mYUV)
    {
        const VkChromaLocation xChromaOffset =
            GetChromaLocation(mAttribs, EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT);
        const VkChromaLocation yChromaOffset =
            GetChromaLocation(mAttribs, EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT);
        const VkSamplerYcbcrModelConversion model = GetYcbcrModel(mAttribs);
        const VkSamplerYcbcrRange range           = GetYcbcrRange(mAttribs);
        const VkComponentMapping components       = {
            VK_COMPONENT_SWIZZLE_IDENTITY,
            VK_COMPONENT_SWIZZLE_IDENTITY,
            VK_COMPONENT_SWIZZLE_IDENTITY,
            VK_COMPONENT_SWIZZLE_IDENTITY,
        };

        ANGLE_VK_CHECK(displayVk, renderer->getFeatures().supportsYUVSamplerConversion.enabled,
                       VK_ERROR_FEATURE_NOT_PRESENT);

        const vk::YcbcrLinearFilterSupport linearFilterSupported =
            renderer->hasImageFormatFeatureBits(
                actualImageFormatID,
                VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT)
                ? vk::YcbcrLinearFilterSupport::Supported
                : vk::YcbcrLinearFilterSupport::Unsupported;

        // Build an appropriate conversion desc. This is not an android-style external format,
        // but requires Ycbcr sampler conversion.
        conversionDesc.update(renderer, 0, model, range, xChromaOffset, yChromaOffset,
                              vk::kDefaultYCbCrChromaFilter, components, intendedFormatID,
                              linearFilterSupported);
    }

    ANGLE_TRY(mImage->initExternal(
        displayVk, gl::TextureType::_2D, vkExtents, intendedFormatID, actualImageFormatID, 1,
        usageFlags, createFlags, vk::ImageAccess::ExternalPreInitialized, imageCreateInfoPNext,
        gl::LevelIndex(0), 1, 1, kIsRobustInitEnabled, hasProtectedContent(),
        vk::TileMemory::Prohibited, conversionDesc, nullptr, formatReinterpretability));

    VkMemoryRequirements externalMemoryRequirements;
    mImage->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);

    const VkMemoryPropertyFlags flags =
        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
        (hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);

    AllocateInfo allocateInfo;
    uint32_t allocateInfoCount;
    ANGLE_TRY(GetAllocateInfo(mAttribs, mImage->getImage().getHandle(), planeCount,
                              modifierProperties, &allocateInfo, &allocateInfoCount));

    return mImage->initExternalMemory(
        displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, allocateInfoCount,
        allocateInfo.allocateInfoPtr.data(), vk::kForeignDeviceQueueIndex, flags);
}

angle::Result DmaBufImageSiblingVkLinux::initImpl(DisplayVk *displayVk)
{
    vk::Renderer *renderer = displayVk->getRenderer();

    const vk::Format &vkFormat = renderer->getFormat(mFormat.info->sizedInternalFormat);
    const angle::Format &format =
        vkFormat.getActualImageFormat(rx::vk::ImageFormatSupport::SampleOnly);

    InitResult initResult;

    for (VkFormat vkFmt : mVkFormats)
    {
        // Try all formats with mutable format bit first
        ANGLE_TRY(initWithFormat(displayVk, format, vkFmt, MutableFormat::Allowed, &initResult));
        if (initResult == InitResult::Success)
        {
            return angle::Result::Continue;
        }
    }

    for (VkFormat vkFmt : mVkFormats)
    {
        // Then try without mutable format bit
        ANGLE_TRY(initWithFormat(displayVk, format, vkFmt, MutableFormat::NotAllowed, &initResult));
        if (initResult == InitResult::Success)
        {
            return angle::Result::Continue;
        }
    }

    // Failed to find any suitable format
    ANGLE_VK_UNREACHABLE(displayVk);
    return angle::Result::Stop;
}

void DmaBufImageSiblingVkLinux::onDestroy(const egl::Display *display)
{
    ASSERT(mImage == nullptr);
}

gl::Format DmaBufImageSiblingVkLinux::getFormat() const
{
    return mFormat;
}

bool DmaBufImageSiblingVkLinux::isRenderable(const gl::Context *context) const
{
    return mRenderable;
}

bool DmaBufImageSiblingVkLinux::isTexturable(const gl::Context *context) const
{
    return mTextureable;
}

bool DmaBufImageSiblingVkLinux::isYUV() const
{
    return mYUV;
}

bool DmaBufImageSiblingVkLinux::hasProtectedContent() const
{
    return mHasProtectedContent;
}

gl::Extents DmaBufImageSiblingVkLinux::getSize() const
{
    return mSize;
}

size_t DmaBufImageSiblingVkLinux::getSamples() const
{
    return mSamples;
}

// ExternalImageSiblingVk interface
vk::ImageHelper *DmaBufImageSiblingVkLinux::getImage() const
{
    return mImage;
}

void DmaBufImageSiblingVkLinux::release(vk::Renderer *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->releaseImage(renderer);
        mImage->releaseStagedUpdates(renderer);
        SafeDelete(mImage);
    }
}

}  // namespace rx
