Hash :
5e87ae0a
Author :
Date :
2022-03-01T12:41:00
Use VK_ANDROID_surfaceless_query for EGLConfig formats That extension allows DisplayVkAndroid::generateConfigs() to query the swapchain formats (but not yet colorspaces) before ANGLE is given any VkSurfaceKHR. This is used for creating EGLConfig's with GL_RGB10_A2 and GL_RGBA16F. Bug: b/203826952 Change-Id: I55302c98641fbce93f7af428087430763676bdb4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3492482 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Trevor David Black <vantablack@google.com> Commit-Queue: Ian Elliott <ianelliott@google.com>
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
//
// Copyright 2018 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.
//
// DisplayVkAndroid.cpp:
// Implements the class methods for DisplayVkAndroid.
//
#include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
#include <android/log.h>
#include <android/native_window.h>
#include <vulkan/vulkan.h>
#include "common/angle_version_info.h"
#include "libANGLE/renderer/driver_utils.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
#include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
namespace rx
{
DisplayVkAndroid::DisplayVkAndroid(const egl::DisplayState &state) : DisplayVk(state) {}
egl::Error DisplayVkAndroid::initialize(egl::Display *display)
{
ANGLE_TRY(DisplayVk::initialize(display));
std::stringstream strstr;
strstr << "Version (" << angle::GetANGLEVersionString() << "), ";
strstr << "Renderer (" << mRenderer->getRendererDescription() << ")";
__android_log_print(ANDROID_LOG_INFO, "ANGLE", "%s", strstr.str().c_str());
return egl::NoError();
}
bool DisplayVkAndroid::isValidNativeWindow(EGLNativeWindowType window) const
{
return (ANativeWindow_getFormat(window) >= 0);
}
SurfaceImpl *DisplayVkAndroid::createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window)
{
return new WindowSurfaceVkAndroid(state, window);
}
egl::ConfigSet DisplayVkAndroid::generateConfigs()
{
// ANGLE's Vulkan back-end on Android traditionally supports EGLConfig's with GL_RGBA8,
// GL_RGB8, and GL_RGB565. The Android Vulkan loader used to support all three of these
// (e.g. Android 7), but this has changed as Android now supports Vulkan devices that do not
// support all of those formats. The loader always supports GL_RGBA8. Other formats are
// optionally supported, depending on the underlying driver support. This includes GL_RGB10_A2
// and GL_RGBA16F, which ANGLE also desires to support EGLConfig's with.
//
// The problem for ANGLE is that Vulkan requires a VkSurfaceKHR in order to query available
// formats from the loader, but ANGLE must determine which EGLConfig's to expose before it has
// a VkSurfaceKHR. The VK_GOOGLE_surfaceless_query extension allows ANGLE to query formats
// without having a VkSurfaceKHR. The old path is still kept until this extension becomes
// universally available.
// Assume GL_RGB8 and GL_RGBA8 is always available.
std::vector<GLenum> kColorFormats = {GL_RGBA8, GL_RGB8};
std::vector<GLenum> kDesiredColorFormats = {GL_RGB565, GL_RGB10_A2, GL_RGBA16F};
if (!getRenderer()->getFeatures().supportsSurfacelessQueryExtension.enabled)
{
// Old path: Assume GL_RGB565 is available, as it is generally available on the devices
// that support Vulkan.
kColorFormats.push_back(GL_RGB565);
}
else
{
// Use the VK_GOOGLE_surfaceless_query extension to query the available formats and
// colorspaces by using a VK_NULL_HANDLE for the VkSurfaceKHR handle.
VkPhysicalDevice physicalDevice = mRenderer->getPhysicalDevice();
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2 = {};
surfaceInfo2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
surfaceInfo2.surface = VK_NULL_HANDLE;
uint32_t surfaceFormatCount = 0;
VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
&surfaceFormatCount, nullptr);
if (result != VK_SUCCESS)
{
return egl::ConfigSet();
}
std::vector<VkSurfaceFormat2KHR> surfaceFormats2(surfaceFormatCount);
for (VkSurfaceFormat2KHR &surfaceFormat2 : surfaceFormats2)
{
surfaceFormat2.sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
}
result = vkGetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, &surfaceInfo2,
&surfaceFormatCount, surfaceFormats2.data());
if (result != VK_SUCCESS)
{
return egl::ConfigSet();
}
for (const VkSurfaceFormat2KHR &surfaceFormat2 : surfaceFormats2)
{
// Need to convert each Vulkan VkFormat into its GLES equivalent and
// add formats in kDesiredColorFormats.
angle::FormatID angleFormatID =
vk::GetFormatIDFromVkFormat(surfaceFormat2.surfaceFormat.format);
const angle::Format &angleFormat = angle::Format::Get(angleFormatID);
GLenum glFormat = angleFormat.glInternalFormat;
if (std::find(kDesiredColorFormats.begin(), kDesiredColorFormats.end(), glFormat) !=
kDesiredColorFormats.end())
{
kColorFormats.push_back(glFormat);
}
}
}
std::vector<GLenum> depthStencilFormats(
egl_vk::kConfigDepthStencilFormats,
egl_vk::kConfigDepthStencilFormats + ArraySize(egl_vk::kConfigDepthStencilFormats));
if (getCaps().stencil8)
{
depthStencilFormats.push_back(GL_STENCIL_INDEX8);
}
return egl_vk::GenerateConfigs(kColorFormats.data(), kColorFormats.size(),
depthStencilFormats.data(), depthStencilFormats.size(), this);
}
void DisplayVkAndroid::enableRecordableIfSupported(egl::Config *config)
{
// TODO(b/181163023): Determine how to properly query for support. This is a hack to unblock
// launching SwANGLE on Cuttlefish.
// anglebug.com/6612: This is also required for app compatiblity.
config->recordable = true;
}
void DisplayVkAndroid::checkConfigSupport(egl::Config *config)
{
// TODO(geofflang): Test for native support and modify the config accordingly.
// anglebug.com/2692
enableRecordableIfSupported(config);
}
egl::Error DisplayVkAndroid::validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const
{
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
return HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(
mRenderer, clientBuffer, attribs);
default:
return DisplayVk::validateImageClientBuffer(context, target, clientBuffer, attribs);
}
}
ExternalImageSiblingImpl *DisplayVkAndroid::createExternalImageSibling(
const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
return new HardwareBufferImageSiblingVkAndroid(buffer);
default:
return DisplayVk::createExternalImageSibling(context, target, buffer, attribs);
}
}
const char *DisplayVkAndroid::getWSIExtension() const
{
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
bool IsVulkanAndroidDisplayAvailable()
{
return true;
}
DisplayImpl *CreateVulkanAndroidDisplay(const egl::DisplayState &state)
{
return new DisplayVkAndroid(state);
}
} // namespace rx