Commit 806ba566 by Jonah Ryan-Davis Committed by Commit Bot

Extend ANGLE_iosurface_client_buffer to Vulkan backend for Swangle

Implement an IOSurface-backed pBuffer surface for the Vulkan backend on Mac, through SwANGLE. ANGLE will pass a raw pointer to Swiftshader and handle locking/unlocking the IOSurface. Bug: chromium:1015454 Change-Id: Ia3ead55334736003d405b54ba8dcc7701706fbb2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1965434 Commit-Queue: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5641d193
...@@ -55,6 +55,11 @@ New Tokens ...@@ -55,6 +55,11 @@ New Tokens
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
EGL_IOSURFACE_USAGE_HINT_ANGLE 0x348A EGL_IOSURFACE_USAGE_HINT_ANGLE 0x348A
Accepted in the <attribute> parameter of
eglGetConfigAttrib:
EGL_BIND_TO_TEXTURE_TARGET_ANGLE 0x348D
Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Replace the last sentence of paragraph 1 of Section 3.5.3 with the Replace the last sentence of paragraph 1 of Section 3.5.3 with the
...@@ -81,8 +86,8 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -81,8 +86,8 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
- EGL_TEXTURE_FORMAT with a value of EGL_TEXTURE_RGBA - EGL_TEXTURE_FORMAT with a value of EGL_TEXTURE_RGBA
- EGL_WIDTH with a value between 1 and the width of <buffer>. - EGL_WIDTH with a value between 1 and the width of <buffer>.
- EGL_HEIGHT with a value between 1 and the height of <buffer>. - EGL_HEIGHT with a value between 1 and the height of <buffer>.
- EGL_TEXTURE_TARGET with a value of EGL_TEXTURE_RECTANGLE_ANGLE (macOS) - EGL_TEXTURE_TARGET with a value that matches the attribute
or EGL_TEXTURE_2D (iOS) EGL_BIND_TO_TEXTURE_TARGET_ANGLE as queried from eglGetConfigAttrib.
- EGL_IOSURFACE_PLANE_ANGLE with a value between 0 and the number of - EGL_IOSURFACE_PLANE_ANGLE with a value between 0 and the number of
planes of <buffer> (exclusive). planes of <buffer> (exclusive).
...@@ -119,6 +124,15 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -119,6 +124,15 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
of the associcated IOSurface object are undefined while the pbuffer is of the associcated IOSurface object are undefined while the pbuffer is
bound to a client texture." bound to a client texture."
Append to the end of Table 3.1.
---------------------------------------------------------------------------
Attribute Type Notes
---------------------------------------------------------------------------
EGL_BIND_TO_TEXTURE_TARGET_ANGLE enum Texture target supported by
IOSurface-backed pbuffers.
---------------------------------------------------------------------------
Issues Issues
1. Can RGB formats be supported? 1. Can RGB formats be supported?
......
...@@ -197,6 +197,7 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limi ...@@ -197,6 +197,7 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limi
#define EGL_IOSURFACE_USAGE_HINT_ANGLE 0x348A #define EGL_IOSURFACE_USAGE_HINT_ANGLE 0x348A
#define EGL_IOSURFACE_READ_HINT_ANGLE 0x0001 #define EGL_IOSURFACE_READ_HINT_ANGLE 0x0001
#define EGL_IOSURFACE_WRITE_HINT_ANGLE 0x0002 #define EGL_IOSURFACE_WRITE_HINT_ANGLE 0x0002
#define EGL_BIND_TO_TEXTURE_TARGET_ANGLE 0x348D
#endif /* EGL_ANGLE_iosurface_client_buffer */ #endif /* EGL_ANGLE_iosurface_client_buffer */
#ifndef EGL_ANGLE_create_context_extensions_enabled #ifndef EGL_ANGLE_create_context_extensions_enabled
......
...@@ -229,6 +229,12 @@ struct FeaturesVk : FeatureSetBase ...@@ -229,6 +229,12 @@ struct FeaturesVk : FeatureSetBase
"Use ANGLE's Vulkan deferred command graph.", "Use ANGLE's Vulkan deferred command graph.",
&members, &members,
}; };
// Whether the VkDevice supports the VK_EXT_external_memory_host extension, on which the
// ANGLE_iosurface_client_buffer extension can be layered.
Feature supportsExternalMemoryHost = {
"supports_external_memory_host", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_EXT_external_memory_host extension", &members};
}; };
inline FeaturesVk::FeaturesVk() = default; inline FeaturesVk::FeaturesVk() = default;
......
...@@ -18,6 +18,7 @@ namespace angle ...@@ -18,6 +18,7 @@ namespace angle
{ {
std::string GetExecutablePath(); std::string GetExecutablePath();
std::string GetExecutableDirectory(); std::string GetExecutableDirectory();
std::string GetHelperExecutableDir();
const char *GetSharedLibraryExtension(); const char *GetSharedLibraryExtension();
const char *GetExecutableExtension(); const char *GetExecutableExtension();
char GetPathSeparator(); char GetPathSeparator();
......
...@@ -55,14 +55,9 @@ const char *GetPathSeparatorForEnvironmentVar() ...@@ -55,14 +55,9 @@ const char *GetPathSeparatorForEnvironmentVar()
return ":"; return ":";
} }
class PosixLibrary : public Library std::string GetHelperExecutableDir()
{ {
public:
PosixLibrary(const char *libraryName, SearchType searchType)
{
std::string directory; std::string directory;
if (searchType == SearchType::ApplicationDir)
{
static int dummySymbol = 0; static int dummySymbol = 0;
Dl_info dlInfo; Dl_info dlInfo;
if (dladdr(&dummySymbol, &dlInfo) != 0) if (dladdr(&dummySymbol, &dlInfo) != 0)
...@@ -70,6 +65,18 @@ class PosixLibrary : public Library ...@@ -70,6 +65,18 @@ class PosixLibrary : public Library
std::string moduleName = dlInfo.dli_fname; std::string moduleName = dlInfo.dli_fname;
directory = moduleName.substr(0, moduleName.find_last_of('/') + 1); directory = moduleName.substr(0, moduleName.find_last_of('/') + 1);
} }
return directory;
}
class PosixLibrary : public Library
{
public:
PosixLibrary(const char *libraryName, SearchType searchType)
{
std::string directory;
if (searchType == SearchType::ApplicationDir)
{
directory = GetHelperExecutableDir();
} }
std::string fullPath = directory + libraryName + "." + GetSharedLibraryExtension(); std::string fullPath = directory + libraryName + "." + GetSharedLibraryExtension();
......
...@@ -100,4 +100,9 @@ char GetPathSeparator() ...@@ -100,4 +100,9 @@ char GetPathSeparator()
{ {
return '\\'; return '\\';
} }
std::string GetHelperExecutableDir()
{
return "";
}
} // namespace angle } // namespace angle
...@@ -34,6 +34,7 @@ Config::Config() ...@@ -34,6 +34,7 @@ Config::Config()
alphaMaskSize(0), alphaMaskSize(0),
bindToTextureRGB(EGL_FALSE), bindToTextureRGB(EGL_FALSE),
bindToTextureRGBA(EGL_FALSE), bindToTextureRGBA(EGL_FALSE),
bindToTextureTarget(EGL_TEXTURE_2D),
colorBufferType(EGL_RGB_BUFFER), colorBufferType(EGL_RGB_BUFFER),
configCaveat(EGL_NONE), configCaveat(EGL_NONE),
configID(0), configID(0),
...@@ -318,6 +319,9 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) ...@@ -318,6 +319,9 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap)
case EGL_BIND_TO_TEXTURE_RGBA: case EGL_BIND_TO_TEXTURE_RGBA:
match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue); match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue);
break; break;
case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
match = config.bindToTextureTarget == static_cast<EGLenum>(attributeValue);
break;
case EGL_MIN_SWAP_INTERVAL: case EGL_MIN_SWAP_INTERVAL:
match = config.minSwapInterval == attributeValue; match = config.minSwapInterval == attributeValue;
break; break;
......
...@@ -43,6 +43,7 @@ struct Config ...@@ -43,6 +43,7 @@ struct Config
EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer
EGLBoolean bindToTextureRGB; // True if bindable to RGB textures. EGLBoolean bindToTextureRGB; // True if bindable to RGB textures.
EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures. EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures.
EGLenum bindToTextureTarget; // Which texture target should be used for pbuffers
EGLenum colorBufferType; // Color buffer type EGLenum colorBufferType; // Color buffer type
EGLenum configCaveat; // Any caveats for the configuration EGLenum configCaveat; // Any caveats for the configuration
EGLint configID; // Unique EGLConfig identifier EGLint configID; // Unique EGLConfig identifier
......
...@@ -3654,6 +3654,9 @@ void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value) ...@@ -3654,6 +3654,9 @@ void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
case EGL_SURFACE_TYPE: case EGL_SURFACE_TYPE:
*value = config->surfaceType; *value = config->surfaceType;
break; break;
case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
*value = config->bindToTextureTarget;
break;
case EGL_TRANSPARENT_TYPE: case EGL_TRANSPARENT_TYPE:
*value = config->transparentType; *value = config->transparentType;
break; break;
......
...@@ -259,6 +259,8 @@ egl::ConfigSet DisplayCGL::generateConfigs() ...@@ -259,6 +259,8 @@ egl::ConfigSet DisplayCGL::generateConfigs()
config.bindToTextureRGB = EGL_FALSE; config.bindToTextureRGB = EGL_FALSE;
config.bindToTextureRGBA = EGL_FALSE; config.bindToTextureRGBA = EGL_FALSE;
config.bindToTextureTarget = EGL_TEXTURE_RECTANGLE_ANGLE;
config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
config.minSwapInterval = 1; config.minSwapInterval = 1;
......
...@@ -204,6 +204,12 @@ egl::ConfigSet DisplayEAGL::generateConfigs() ...@@ -204,6 +204,12 @@ egl::ConfigSet DisplayEAGL::generateConfigs()
config.bindToTextureRGB = EGL_FALSE; config.bindToTextureRGB = EGL_FALSE;
config.bindToTextureRGBA = EGL_FALSE; config.bindToTextureRGBA = EGL_FALSE;
# if !ANGLE_PLATFORM_MACCATALYST
config.bindToTextureTarget = EGL_TEXTURE_2D;
# else
config.bindToTextureTarget = EGL_TEXTURE_RECTANGLE_ANGLE;
# endif
config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; config.surfaceType = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
config.minSwapInterval = 1; config.minSwapInterval = 1;
......
...@@ -45,18 +45,18 @@ _vulkan_backend_sources = [ ...@@ -45,18 +45,18 @@ _vulkan_backend_sources = [
"OverlayVk.h", "OverlayVk.h",
"PersistentCommandPool.cpp", "PersistentCommandPool.cpp",
"PersistentCommandPool.h", "PersistentCommandPool.h",
"ProgramVk.cpp",
"ProgramVk.h",
"ProgramPipelineVk.cpp", "ProgramPipelineVk.cpp",
"ProgramPipelineVk.h", "ProgramPipelineVk.h",
"ProgramVk.cpp",
"ProgramVk.h",
"QueryVk.cpp", "QueryVk.cpp",
"QueryVk.h", "QueryVk.h",
"RenderTargetVk.cpp",
"RenderTargetVk.h",
"RenderbufferVk.cpp", "RenderbufferVk.cpp",
"RenderbufferVk.h", "RenderbufferVk.h",
"RendererVk.cpp", "RendererVk.cpp",
"RendererVk.h", "RendererVk.h",
"RenderTargetVk.cpp",
"RenderTargetVk.h",
"SamplerVk.cpp", "SamplerVk.cpp",
"SamplerVk.h", "SamplerVk.h",
"SecondaryCommandBuffer.cpp", "SecondaryCommandBuffer.cpp",
...@@ -83,12 +83,12 @@ _vulkan_backend_sources = [ ...@@ -83,12 +83,12 @@ _vulkan_backend_sources = [
"vk_caps_utils.h", "vk_caps_utils.h",
"vk_ext_provoking_vertex.h", "vk_ext_provoking_vertex.h",
"vk_format_table_autogen.cpp", "vk_format_table_autogen.cpp",
"vk_format_utils.h",
"vk_format_utils.cpp", "vk_format_utils.cpp",
"vk_format_utils.h",
"vk_helpers.cpp", "vk_helpers.cpp",
"vk_helpers.h", "vk_helpers.h",
"vk_internal_shaders_autogen.h",
"vk_internal_shaders_autogen.cpp", "vk_internal_shaders_autogen.cpp",
"vk_internal_shaders_autogen.h",
"vk_mandatory_format_support_table_autogen.cpp", "vk_mandatory_format_support_table_autogen.cpp",
"vk_utils.cpp", "vk_utils.cpp",
"vk_utils.h", "vk_utils.h",
...@@ -144,10 +144,12 @@ if (is_ggp) { ...@@ -144,10 +144,12 @@ if (is_ggp) {
if (is_mac) { if (is_mac) {
_vulkan_backend_sources += [ _vulkan_backend_sources += [
"mac/DisplayVkMac.mm",
"mac/DisplayVkMac.h", "mac/DisplayVkMac.h",
"mac/WindowSurfaceVkMac.mm", "mac/DisplayVkMac.mm",
"mac/IOSurfaceSurfaceVkMac.h",
"mac/IOSurfaceSurfaceVkMac.mm",
"mac/WindowSurfaceVkMac.h", "mac/WindowSurfaceVkMac.h",
"mac/WindowSurfaceVkMac.mm",
] ]
} }
...@@ -170,9 +172,7 @@ group("angle_vulkan_entry_points") { ...@@ -170,9 +172,7 @@ group("angle_vulkan_entry_points") {
"//third_party/fuchsia-sdk/sdk:vulkan", "//third_party/fuchsia-sdk/sdk:vulkan",
] ]
} else if (!is_android && !is_ggp) { } else if (!is_android && !is_ggp) {
data_deps = [ data_deps = [ "$angle_root/third_party/vulkan-loader/src:libvulkan" ]
"$angle_root/third_party/vulkan-loader/src:libvulkan",
]
} }
} }
......
...@@ -95,10 +95,12 @@ class DisplayVk : public DisplayImpl, public vk::Context ...@@ -95,10 +95,12 @@ class DisplayVk : public DisplayImpl, public vk::Context
void populateFeatureList(angle::FeatureList *features) override; void populateFeatureList(angle::FeatureList *features) override;
protected:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
private: private:
virtual SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state, virtual SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window) = 0; EGLNativeWindowType window) = 0;
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
mutable angle::ScratchBuffer mScratchBuffer; mutable angle::ScratchBuffer mScratchBuffer;
......
...@@ -231,6 +231,21 @@ const char *GetVkObjectTypeName(VkObjectType type) ...@@ -231,6 +231,21 @@ const char *GetVkObjectTypeName(VkObjectType type)
} }
} }
// This function is unused on Android/Fuschia/GGP
#if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA) && \
!defined(ANGLE_PLATFORM_GGP)
const std::string WrapICDEnvironment(const char *icdEnvironment)
{
# if defined(ANGLE_PLATFORM_APPLE)
// On MacOS the libraries are bundled into the application directory
std::string ret = angle::GetHelperExecutableDir() + icdEnvironment;
return ret;
# endif // defined(ANGLE_PLATFORM_APPLE)
return icdEnvironment;
}
#endif // !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA) &&
// !defined(ANGLE_PLATFORM_GGP)
VKAPI_ATTR VkBool32 VKAPI_CALL VKAPI_ATTR VkBool32 VKAPI_CALL
DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
...@@ -370,7 +385,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable ...@@ -370,7 +385,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable
!defined(ANGLE_PLATFORM_GGP) !defined(ANGLE_PLATFORM_GGP)
if (icd == vk::ICD::Mock) if (icd == vk::ICD::Mock)
{ {
if (!setICDEnvironment(ANGLE_VK_MOCK_ICD_JSON)) if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_MOCK_ICD_JSON).c_str()))
{ {
ERR() << "Error setting environment for Mock/Null Driver."; ERR() << "Error setting environment for Mock/Null Driver.";
} }
...@@ -378,7 +393,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable ...@@ -378,7 +393,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable
# if defined(ANGLE_VK_SWIFTSHADER_ICD_JSON) # if defined(ANGLE_VK_SWIFTSHADER_ICD_JSON)
else if (icd == vk::ICD::SwiftShader) else if (icd == vk::ICD::SwiftShader)
{ {
if (!setICDEnvironment(ANGLE_VK_SWIFTSHADER_ICD_JSON)) if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_SWIFTSHADER_ICD_JSON).c_str()))
{ {
ERR() << "Error setting environment for SwiftShader."; ERR() << "Error setting environment for SwiftShader.";
} }
...@@ -552,6 +567,7 @@ RendererVk::RendererVk() ...@@ -552,6 +567,7 @@ RendererVk::RendererVk()
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()), mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mMaxVertexAttribDivisor(1), mMaxVertexAttribDivisor(1),
mMaxVertexAttribStride(0), mMaxVertexAttribStride(0),
mMinImportedHostPointerAlignment(1),
mDevice(VK_NULL_HANDLE), mDevice(VK_NULL_HANDLE),
mLastCompletedQueueSerial(mQueueSerialFactory.generate()), mLastCompletedQueueSerial(mQueueSerialFactory.generate()),
mCurrentQueueSerial(mQueueSerialFactory.generate()), mCurrentQueueSerial(mQueueSerialFactory.generate()),
...@@ -922,6 +938,10 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -922,6 +938,10 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mPhysicalDeviceSubgroupProperties = {}; mPhysicalDeviceSubgroupProperties = {};
mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; mPhysicalDeviceSubgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
mPhysicalDeviceExternalMemoryHostProperties = {};
mPhysicalDeviceExternalMemoryHostProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
if (!vkGetPhysicalDeviceProperties2KHR || !vkGetPhysicalDeviceFeatures2KHR) if (!vkGetPhysicalDeviceProperties2KHR || !vkGetPhysicalDeviceFeatures2KHR)
{ {
return; return;
...@@ -959,6 +979,12 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -959,6 +979,12 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
vk::AddToPNextChain(&deviceFeatures, &mTransformFeedbackFeatures); vk::AddToPNextChain(&deviceFeatures, &mTransformFeedbackFeatures);
} }
// Query external memory host properties
if (ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceProperties, &mPhysicalDeviceExternalMemoryHostProperties);
}
// Query subgroup properties // Query subgroup properties
vk::AddToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties); vk::AddToPNextChain(&deviceProperties, &mPhysicalDeviceSubgroupProperties);
...@@ -972,6 +998,7 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -972,6 +998,7 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mVertexAttributeDivisorProperties.pNext = nullptr; mVertexAttributeDivisorProperties.pNext = nullptr;
mTransformFeedbackFeatures.pNext = nullptr; mTransformFeedbackFeatures.pNext = nullptr;
mPhysicalDeviceSubgroupProperties.pNext = nullptr; mPhysicalDeviceSubgroupProperties.pNext = nullptr;
mPhysicalDeviceExternalMemoryHostProperties.pNext = nullptr;
} }
angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex) angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
...@@ -1193,6 +1220,13 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1193,6 +1220,13 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
vk::AddToPNextChain(&createInfo, &mTransformFeedbackFeatures); vk::AddToPNextChain(&createInfo, &mTransformFeedbackFeatures);
} }
if (getFeatures().supportsExternalMemoryHost.enabled)
{
enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
mMinImportedHostPointerAlignment =
mPhysicalDeviceExternalMemoryHostProperties.minImportedHostPointerAlignment;
}
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.flags = 0; createInfo.flags = 0;
createInfo.queueCreateInfoCount = 1; createInfo.queueCreateInfoCount = 1;
...@@ -1563,6 +1597,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1563,6 +1597,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION((&mFeatures), commandGraph, true); ANGLE_FEATURE_CONDITION((&mFeatures), commandGraph, true);
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsExternalMemoryHost,
ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames));
angle::PlatformMethods *platform = ANGLEPlatformCurrent(); angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures); platform->overrideFeaturesVk(platform, &mFeatures);
......
...@@ -145,6 +145,11 @@ class RendererVk : angle::NonCopyable ...@@ -145,6 +145,11 @@ class RendererVk : angle::NonCopyable
uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; } uint32_t getMaxVertexAttribDivisor() const { return mMaxVertexAttribDivisor; }
VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; } VkDeviceSize getMaxVertexAttribStride() const { return mMaxVertexAttribStride; }
VkDeviceSize getMinImportedHostPointerAlignment() const
{
return mMinImportedHostPointerAlignment;
}
bool isMockICDEnabled() const { return mEnabledICD == vk::ICD::Mock; } bool isMockICDEnabled() const { return mEnabledICD == vk::ICD::Mock; }
// Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and // Query the format properties for select bits (linearTilingFeatures, optimalTilingFeatures and
...@@ -264,6 +269,7 @@ class RendererVk : angle::NonCopyable ...@@ -264,6 +269,7 @@ class RendererVk : angle::NonCopyable
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties; VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT mVertexAttributeDivisorProperties;
VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures; VkPhysicalDeviceTransformFeedbackFeaturesEXT mTransformFeedbackFeatures;
VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties; VkPhysicalDeviceSubgroupProperties mPhysicalDeviceSubgroupProperties;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT mPhysicalDeviceExternalMemoryHostProperties;
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties; std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
std::mutex mQueueMutex; std::mutex mQueueMutex;
angle::PackedEnumMap<egl::ContextPriority, VkQueue> mQueues; angle::PackedEnumMap<egl::ContextPriority, VkQueue> mQueues;
...@@ -271,6 +277,7 @@ class RendererVk : angle::NonCopyable ...@@ -271,6 +277,7 @@ class RendererVk : angle::NonCopyable
uint32_t mCurrentQueueFamilyIndex; uint32_t mCurrentQueueFamilyIndex;
uint32_t mMaxVertexAttribDivisor; uint32_t mMaxVertexAttribDivisor;
VkDeviceSize mMaxVertexAttribStride; VkDeviceSize mMaxVertexAttribStride;
VkDeviceSize mMinImportedHostPointerAlignment;
VkDevice mDevice; VkDevice mDevice;
AtomicSerialFactory mQueueSerialFactory; AtomicSerialFactory mQueueSerialFactory;
AtomicSerialFactory mShaderSerialFactory; AtomicSerialFactory mShaderSerialFactory;
......
...@@ -155,6 +155,49 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display ...@@ -155,6 +155,49 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
return angle::Result::Continue; return angle::Result::Continue;
} }
angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
DisplayVk *displayVk,
EGLint width,
EGLint height,
const vk::Format &vkFormat,
GLint samples,
void *buffer)
{
RendererVk *renderer = displayVk->getRenderer();
ASSERT(renderer->getFeatures().supportsExternalMemoryHost.enabled);
const angle::Format &textureFormat = vkFormat.actualImageFormat();
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
const VkImageUsageFlags usage = isDepthOrStencilFormat ? kSurfaceVKDepthStencilImageUsageFlags
: kSurfaceVKColorImageUsageFlags;
VkExtent3D extents = {std::max(static_cast<uint32_t>(width), 1u),
std::max(static_cast<uint32_t>(height), 1u), 1u};
ANGLE_TRY(
image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, samples, usage, 0, 0, 1, 1));
VkImportMemoryHostPointerInfoEXT importMemoryHostPointerInfo = {};
importMemoryHostPointerInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT;
importMemoryHostPointerInfo.pNext = nullptr;
importMemoryHostPointerInfo.handleType =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT;
importMemoryHostPointerInfo.pHostPointer = buffer;
VkMemoryRequirements externalMemoryRequirements;
image.getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
VkMemoryPropertyFlags flags = 0;
ANGLE_TRY(image.initExternalMemory(displayVk, renderer->getMemoryProperties(),
externalMemoryRequirements, &importMemoryHostPointerInfo,
VK_QUEUE_FAMILY_EXTERNAL, flags));
// Clear the image if it has emulated channels.
image.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), vkFormat);
return angle::Result::Continue;
}
void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display) void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display)
{ {
DisplayVk *displayVk = vk::GetImpl(display); DisplayVk *displayVk = vk::GetImpl(display);
......
...@@ -75,7 +75,7 @@ class OffscreenSurfaceVk : public SurfaceVk ...@@ -75,7 +75,7 @@ class OffscreenSurfaceVk : public SurfaceVk
vk::ImageHelper *getColorAttachmentImage(); vk::ImageHelper *getColorAttachmentImage();
private: protected:
struct AttachmentImage final : angle::NonCopyable struct AttachmentImage final : angle::NonCopyable
{ {
AttachmentImage(); AttachmentImage();
...@@ -86,13 +86,21 @@ class OffscreenSurfaceVk : public SurfaceVk ...@@ -86,13 +86,21 @@ class OffscreenSurfaceVk : public SurfaceVk
EGLint height, EGLint height,
const vk::Format &vkFormat, const vk::Format &vkFormat,
GLint samples); GLint samples);
angle::Result initializeWithExternalMemory(DisplayVk *displayVk,
EGLint width,
EGLint height,
const vk::Format &vkFormat,
GLint samples,
void *buffer);
void destroy(const egl::Display *display); void destroy(const egl::Display *display);
vk::ImageHelper image; vk::ImageHelper image;
vk::ImageViewHelper imageViews; vk::ImageViewHelper imageViews;
}; };
angle::Result initializeImpl(DisplayVk *displayVk); virtual angle::Result initializeImpl(DisplayVk *displayVk);
EGLint mWidth; EGLint mWidth;
EGLint mHeight; EGLint mHeight;
......
...@@ -25,9 +25,21 @@ class DisplayVkMac : public DisplayVk ...@@ -25,9 +25,21 @@ class DisplayVkMac : public DisplayVk
SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state, SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window) override; EGLNativeWindowType window) override;
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) override;
egl::ConfigSet generateConfigs() override; egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override; bool checkConfigSupport(egl::Config *config) override;
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
egl::Error validateClientBuffer(const egl::Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
const char *getWSIExtension() const override; const char *getWSIExtension() const override;
}; };
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.h"
#include "libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h" #include "libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h" #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
...@@ -34,6 +36,16 @@ SurfaceImpl *DisplayVkMac::createWindowSurfaceVk(const egl::SurfaceState &state, ...@@ -34,6 +36,16 @@ SurfaceImpl *DisplayVkMac::createWindowSurfaceVk(const egl::SurfaceState &state,
return new WindowSurfaceVkMac(state, window); return new WindowSurfaceVkMac(state, window);
} }
SurfaceImpl *DisplayVkMac::createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs)
{
ASSERT(buftype == EGL_IOSURFACE_ANGLE);
return new IOSurfaceSurfaceVkMac(state, clientBuffer, attribs);
}
egl::ConfigSet DisplayVkMac::generateConfigs() egl::ConfigSet DisplayVkMac::generateConfigs()
{ {
constexpr GLenum kColorFormats[] = {GL_BGRA8_EXT, GL_BGRX8_ANGLEX}; constexpr GLenum kColorFormats[] = {GL_BGRA8_EXT, GL_BGRX8_ANGLEX};
...@@ -62,4 +74,26 @@ DisplayImpl *CreateVulkanMacDisplay(const egl::DisplayState &state) ...@@ -62,4 +74,26 @@ DisplayImpl *CreateVulkanMacDisplay(const egl::DisplayState &state)
return new DisplayVkMac(state); return new DisplayVkMac(state);
} }
void DisplayVkMac::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
outExtensions->iosurfaceClientBuffer =
getRenderer()->getFeatures().supportsExternalMemoryHost.enabled;
DisplayVk::generateExtensions(outExtensions);
}
egl::Error DisplayVkMac::validateClientBuffer(const egl::Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const
{
ASSERT(buftype == EGL_IOSURFACE_ANGLE);
if (!IOSurfaceSurfaceVkMac::ValidateAttributes(this, clientBuffer, attribs))
{
return egl::EglBadAttribute();
}
return egl::NoError();
}
} // namespace rx } // namespace rx
//
// Copyright 2020 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.
//
// IOSurfaceSurfaceVkMac.h:
// Subclasses SurfaceVk for the Mac platform to implement PBuffers using an IOSurface
//
#ifndef LIBANGLE_RENDERER_VULKAN_MAC_IOSURFACESURFACEVKMAC_H_
#define LIBANGLE_RENDERER_VULKAN_MAC_IOSURFACESURFACEVKMAC_H_
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
struct __IOSurface;
typedef __IOSurface *IOSurfaceRef;
namespace egl
{
class AttributeMap;
} // namespace egl
namespace rx
{
class IOSurfaceSurfaceVkMac : public OffscreenSurfaceVk
{
public:
IOSurfaceSurfaceVkMac(const egl::SurfaceState &state,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs);
~IOSurfaceSurfaceVkMac() override;
egl::Error initialize(const egl::Display *display) override;
egl::Error unMakeCurrent(const gl::Context *context) override;
egl::Error bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer) override;
egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
static bool ValidateAttributes(const DisplayVk *displayVk,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs);
protected:
angle::Result initializeImpl(DisplayVk *displayVk) override;
private:
IOSurfaceRef mIOSurface;
int mPlane;
int mFormatIndex;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_MAC_IOSURFACESURFACEVKMAC_H_
//
// Copyright 2020 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.
//
// IOSurfaceSurfaceVkMac.mm:
// Implements methods from IOSurfaceSurfaceVkMac.
//
#include "libANGLE/renderer/vulkan/mac/IOSurfaceSurfaceVkMac.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h"
#include <IOSurface/IOSurface.h>
namespace rx
{
namespace
{
struct IOSurfaceFormatInfo
{
GLenum internalFormat;
GLenum type;
size_t componentBytes;
GLenum nativeSizedInternalFormat;
};
// clang-format off
constexpr std::array<IOSurfaceFormatInfo, 6> kIOSurfaceFormats = {{
{GL_RED, GL_UNSIGNED_BYTE, 1, GL_R8 },
{GL_R16UI, GL_UNSIGNED_SHORT, 2, GL_R16UI },
{GL_RG, GL_UNSIGNED_BYTE, 2, GL_RG8 },
{GL_RGB, GL_UNSIGNED_BYTE, 4, GL_BGRA8_EXT},
{GL_BGRA_EXT, GL_UNSIGNED_BYTE, 4, GL_BGRA8_EXT },
{GL_RGBA, GL_HALF_FLOAT, 8, GL_RGBA16F },
}};
// clang-format on
int FindIOSurfaceFormatIndex(GLenum internalFormat, GLenum type)
{
for (int i = 0; i < static_cast<int>(kIOSurfaceFormats.size()); ++i)
{
const auto &formatInfo = kIOSurfaceFormats[i];
if (formatInfo.internalFormat == internalFormat && formatInfo.type == type)
{
return i;
}
}
return -1;
}
} // anonymous namespace
IOSurfaceSurfaceVkMac::IOSurfaceSurfaceVkMac(const egl::SurfaceState &state,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
: OffscreenSurfaceVk(state), mIOSurface(nullptr), mPlane(0), mFormatIndex(-1)
{
// Keep reference to the IOSurface so it doesn't get deleted while the pbuffer exists.
mIOSurface = reinterpret_cast<IOSurfaceRef>(buffer);
CFRetain(mIOSurface);
// Extract attribs useful for the call to CGLTexImageIOSurface2D
mWidth = static_cast<int>(attribs.get(EGL_WIDTH));
mHeight = static_cast<int>(attribs.get(EGL_HEIGHT));
mPlane = static_cast<int>(attribs.get(EGL_IOSURFACE_PLANE_ANGLE));
EGLAttrib internalFormat = attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE);
EGLAttrib type = attribs.get(EGL_TEXTURE_TYPE_ANGLE);
mFormatIndex =
FindIOSurfaceFormatIndex(static_cast<GLenum>(internalFormat), static_cast<GLenum>(type));
ASSERT(mFormatIndex >= 0);
}
IOSurfaceSurfaceVkMac::~IOSurfaceSurfaceVkMac()
{
if (mIOSurface != nullptr)
{
CFRelease(mIOSurface);
mIOSurface = nullptr;
}
}
egl::Error IOSurfaceSurfaceVkMac::initialize(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);
angle::Result result = initializeImpl(displayVk);
return angle::ToEGL(result, displayVk, EGL_BAD_SURFACE);
}
angle::Result IOSurfaceSurfaceVkMac::initializeImpl(DisplayVk *displayVk)
{
RendererVk *renderer = displayVk->getRenderer();
const egl::Config *config = mState.config;
GLint samples = 1;
if (config->sampleBuffers && config->samples > 1)
{
samples = config->samples;
}
ANGLE_VK_CHECK(displayVk, samples > 0, VK_ERROR_INITIALIZATION_FAILED);
// Swiftshader will use the raw pointer to the buffer referenced by the IOSurfaceRef
ANGLE_TRY(mColorAttachment.initializeWithExternalMemory(
displayVk, mWidth, mHeight,
renderer->getFormat(kIOSurfaceFormats[mFormatIndex].nativeSizedInternalFormat), samples,
IOSurfaceGetBaseAddressOfPlane(mIOSurface, mPlane)));
mColorRenderTarget.init(&mColorAttachment.image, &mColorAttachment.imageViews, 0, 0);
return angle::Result::Continue;
}
egl::Error IOSurfaceSurfaceVkMac::unMakeCurrent(const gl::Context *context)
{
ASSERT(context != nullptr);
ContextVk *contextVk = vk::GetImpl(context);
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
angle::Result result = contextVk->flushImpl(nullptr);
return angle::ToEGL(result, displayVk, EGL_BAD_SURFACE);
}
egl::Error IOSurfaceSurfaceVkMac::bindTexImage(const gl::Context *context,
gl::Texture *texture,
EGLint buffer)
{
IOSurfaceLock(mIOSurface, 0, nullptr);
return egl::NoError();
}
egl::Error IOSurfaceSurfaceVkMac::releaseTexImage(const gl::Context *context, EGLint buffer)
{
ASSERT(context != nullptr);
ContextVk *contextVk = vk::GetImpl(context);
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
angle::Result result = contextVk->finishImpl();
IOSurfaceUnlock(mIOSurface, 0, nullptr);
return angle::ToEGL(result, displayVk, EGL_BAD_SURFACE);
}
// static
bool IOSurfaceSurfaceVkMac::ValidateAttributes(const DisplayVk *displayVk,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
ASSERT(displayVk != nullptr);
RendererVk *renderer = displayVk->getRenderer();
IOSurfaceRef ioSurface = reinterpret_cast<IOSurfaceRef>(buffer);
// The plane must exist for this IOSurface. IOSurfaceGetPlaneCount can return 0 for non-planar
// ioSurfaces but we will treat non-planar like it is a single plane.
size_t surfacePlaneCount = std::max(size_t(1), IOSurfaceGetPlaneCount(ioSurface));
EGLAttrib plane = attribs.get(EGL_IOSURFACE_PLANE_ANGLE);
if (plane < 0 || static_cast<size_t>(plane) >= surfacePlaneCount)
{
return false;
}
// The width height specified must be at least (1, 1) and at most the plane size
EGLAttrib width = attribs.get(EGL_WIDTH);
EGLAttrib height = attribs.get(EGL_HEIGHT);
if (width <= 0 || static_cast<size_t>(width) > IOSurfaceGetWidthOfPlane(ioSurface, plane) ||
height <= 0 || static_cast<size_t>(height) > IOSurfaceGetHeightOfPlane(ioSurface, plane))
{
return false;
}
// Find this IOSurface format
EGLAttrib internalFormat = attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE);
EGLAttrib type = attribs.get(EGL_TEXTURE_TYPE_ANGLE);
int formatIndex =
FindIOSurfaceFormatIndex(static_cast<GLenum>(internalFormat), static_cast<GLenum>(type));
if (formatIndex < 0)
{
return false;
}
// Check that the format matches this IOSurface plane
if (IOSurfaceGetBytesPerElementOfPlane(ioSurface, plane) !=
kIOSurfaceFormats[formatIndex].componentBytes)
{
return false;
}
void *pointer = IOSurfaceGetBaseAddressOfPlane(ioSurface, plane);
VkMemoryHostPointerPropertiesEXT memoryHostPointerProperties = {};
memoryHostPointerProperties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT;
vkGetMemoryHostPointerPropertiesEXT(
renderer->getDevice(), VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT,
pointer, &memoryHostPointerProperties);
bool hostVisible =
memoryHostPointerProperties.memoryTypeBits & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
if (!hostVisible)
{
return false;
}
VkDeviceSize alignment = renderer->getMinImportedHostPointerAlignment();
if (reinterpret_cast<size_t>(pointer) % alignment != 0)
{
return false;
}
return true;
}
} // namespace rx
...@@ -178,6 +178,7 @@ Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute) ...@@ -178,6 +178,7 @@ Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute)
case EGL_SAMPLES: case EGL_SAMPLES:
case EGL_SAMPLE_BUFFERS: case EGL_SAMPLE_BUFFERS:
case EGL_SURFACE_TYPE: case EGL_SURFACE_TYPE:
case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
case EGL_TRANSPARENT_TYPE: case EGL_TRANSPARENT_TYPE:
case EGL_TRANSPARENT_BLUE_VALUE: case EGL_TRANSPARENT_BLUE_VALUE:
case EGL_TRANSPARENT_GREEN_VALUE: case EGL_TRANSPARENT_GREEN_VALUE:
...@@ -1874,19 +1875,11 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -1874,19 +1875,11 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
if (buftype == EGL_IOSURFACE_ANGLE) if (buftype == EGL_IOSURFACE_ANGLE)
{ {
#if ANGLE_PLATFORM_MACOS || ANGLE_PLATFORM_MACCATALYST if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
if (textureTarget != EGL_TEXTURE_RECTANGLE_ANGLE)
{ {
return EglBadAttribute() return EglBadAttribute()
<< "EGL_IOSURFACE requires the EGL_TEXTURE_RECTANGLE target on desktop macOS"; << "EGL_IOSURFACE requires the texture target to match the config";
} }
#else // ANGLE_PLATFORM_MACOS || ANGLE_PLATFORM_MACCATALYST
if (textureTarget != EGL_TEXTURE_2D)
{
return EglBadAttribute() << "EGL_IOSURFACE requires the EGL_TEXTURE_2D target on iOS";
}
#endif // ANGLE_PLATFORM_MACOS || ANGLE_PLATFORM_MACCATALYST
if (textureFormat != EGL_TEXTURE_RGBA) if (textureFormat != EGL_TEXTURE_RGBA)
{ {
return EglBadAttribute() << "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format"; return EglBadAttribute() << "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format";
......
...@@ -20,6 +20,8 @@ using namespace angle; ...@@ -20,6 +20,8 @@ using namespace angle;
namespace namespace
{ {
constexpr char kIOSurfaceExt[] = "EGL_ANGLE_iosurface_client_buffer";
void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value) void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
{ {
CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value); CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
...@@ -93,6 +95,31 @@ ScopedIOSurfaceRef CreateSinglePlaneIOSurface(int width, ...@@ -93,6 +95,31 @@ ScopedIOSurfaceRef CreateSinglePlaneIOSurface(int width,
class IOSurfaceClientBufferTest : public ANGLETest class IOSurfaceClientBufferTest : public ANGLETest
{ {
protected: protected:
EGLint getTextureTarget() const
{
EGLint target = 0;
eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &target);
return target;
}
GLint getGLTextureTarget() const
{
EGLint targetEGL = getTextureTarget();
GLenum targetGL = 0;
switch (targetEGL)
{
case EGL_TEXTURE_2D:
targetGL = GL_TEXTURE_2D;
break;
case EGL_TEXTURE_RECTANGLE_ANGLE:
targetGL = GL_TEXTURE_RECTANGLE_ANGLE;
break;
default:
break;
}
return targetGL;
}
IOSurfaceClientBufferTest() : mConfig(0), mDisplay(nullptr) {} IOSurfaceClientBufferTest() : mConfig(0), mDisplay(nullptr) {}
void testSetUp() override void testSetUp() override
...@@ -114,7 +141,7 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -114,7 +141,7 @@ class IOSurfaceClientBufferTest : public ANGLETest
EGL_WIDTH, width, EGL_WIDTH, width,
EGL_HEIGHT, height, EGL_HEIGHT, height,
EGL_IOSURFACE_PLANE_ANGLE, plane, EGL_IOSURFACE_PLANE_ANGLE, plane,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, internalFormat, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, internalFormat,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, type, EGL_TEXTURE_TYPE_ANGLE, type,
...@@ -139,7 +166,7 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -139,7 +166,7 @@ class IOSurfaceClientBufferTest : public ANGLETest
createIOSurfacePbuffer(ioSurface, width, height, plane, internalFormat, type, pbuffer); createIOSurfacePbuffer(ioSurface, width, height, plane, internalFormat, type, pbuffer);
// Bind the pbuffer // Bind the pbuffer
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, *texture); glBindTexture(getGLTextureTarget(), *texture);
EGLBoolean result = eglBindTexImage(mDisplay, *pbuffer, EGL_BACK_BUFFER); EGLBoolean result = eglBindTexImage(mDisplay, *pbuffer, EGL_BACK_BUFFER);
EXPECT_EGL_TRUE(result); EXPECT_EGL_TRUE(result);
EXPECT_EGL_SUCCESS(); EXPECT_EGL_SUCCESS();
...@@ -159,8 +186,8 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -159,8 +186,8 @@ class IOSurfaceClientBufferTest : public ANGLETest
GLFramebuffer fbo; GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getGLTextureTarget(), texture,
texture, 0); 0);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
...@@ -214,8 +241,7 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -214,8 +241,7 @@ class IOSurfaceClientBufferTest : public ANGLETest
"{\n" "{\n"
" gl_Position = vec4(position.xy, 0.0, 1.0);\n" " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
"}\n"; "}\n";
constexpr char kFS_rect[] =
constexpr char kFS[] =
"#extension GL_ARB_texture_rectangle : require\n" "#extension GL_ARB_texture_rectangle : require\n"
"precision mediump float;\n" "precision mediump float;\n"
"uniform sampler2DRect tex;\n" "uniform sampler2DRect tex;\n"
...@@ -223,8 +249,16 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -223,8 +249,16 @@ class IOSurfaceClientBufferTest : public ANGLETest
"{\n" "{\n"
" gl_FragColor = texture2DRect(tex, vec2(0, 0));\n" " gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
"}\n"; "}\n";
constexpr char kFS_2D[] =
"precision mediump float;\n"
"uniform sampler2D tex;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, vec2(0, 0));\n"
"}\n";
ANGLE_GL_PROGRAM(program, kVS, kFS); ANGLE_GL_PROGRAM(program, kVS,
(getTextureTarget() == EGL_TEXTURE_RECTANGLE_ANGLE ? kFS_rect : kFS_2D));
glUseProgram(program); glUseProgram(program);
GLint location = glGetUniformLocation(program, "tex"); GLint location = glGetUniformLocation(program, "tex");
...@@ -253,8 +287,8 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -253,8 +287,8 @@ class IOSurfaceClientBufferTest : public ANGLETest
GLFramebuffer iosurfaceFbo; GLFramebuffer iosurfaceFbo;
glBindFramebuffer(GL_FRAMEBUFFER, iosurfaceFbo); glBindFramebuffer(GL_FRAMEBUFFER, iosurfaceFbo);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getGLTextureTarget(), texture,
texture, 0); 0);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
...@@ -309,6 +343,8 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -309,6 +343,8 @@ class IOSurfaceClientBufferTest : public ANGLETest
EXPECT_EGL_SUCCESS(); EXPECT_EGL_SUCCESS();
} }
bool hasIOSurfaceExt() const { return IsEGLDisplayExtensionEnabled(mDisplay, kIOSurfaceExt); }
EGLConfig mConfig; EGLConfig mConfig;
EGLDisplay mDisplay; EGLDisplay mDisplay;
}; };
...@@ -316,6 +352,8 @@ class IOSurfaceClientBufferTest : public ANGLETest ...@@ -316,6 +352,8 @@ class IOSurfaceClientBufferTest : public ANGLETest
// Test using BGRA8888 IOSurfaces for rendering // Test using BGRA8888 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 4); GLColor color(3, 2, 1, 4);
...@@ -325,6 +363,11 @@ TEST_P(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface) ...@@ -325,6 +363,11 @@ TEST_P(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
// Test reading from BGRA8888 IOSurfaces // Test reading from BGRA8888 IOSurfaces
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface) TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
// TODO(http://anglebug.com/4369)
ANGLE_SKIP_TEST_IF(isSwiftshader());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 4); GLColor color(3, 2, 1, 4);
...@@ -334,6 +377,11 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface) ...@@ -334,6 +377,11 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
// Test using BGRX8888 IOSurfaces for rendering // Test using BGRX8888 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
// TODO(http://anglebug.com/4369)
ANGLE_SKIP_TEST_IF(isSwiftshader());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 255); GLColor color(3, 2, 1, 255);
...@@ -343,6 +391,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface) ...@@ -343,6 +391,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface)
// Test reading from BGRX8888 IOSurfaces // Test reading from BGRX8888 IOSurfaces
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface) TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
GLColor color(3, 2, 1, 4); GLColor color(3, 2, 1, 4);
...@@ -352,6 +402,8 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface) ...@@ -352,6 +402,8 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface)
// Test using RG88 IOSurfaces for rendering // Test using RG88 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2);
uint8_t color[2] = {1, 2}; uint8_t color[2] = {1, 2};
...@@ -361,6 +413,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface) ...@@ -361,6 +413,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
// Test reading from RG88 IOSurfaces // Test reading from RG88 IOSurfaces
TEST_P(IOSurfaceClientBufferTest, ReadFromRG88IOSurface) TEST_P(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2);
uint8_t color[2] = {1, 2}; uint8_t color[2] = {1, 2};
...@@ -370,6 +424,8 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromRG88IOSurface) ...@@ -370,6 +424,8 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
// Test using R8 IOSurfaces for rendering // Test using R8 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToR8IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToR8IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1);
uint8_t color = 1; uint8_t color = 1;
...@@ -379,6 +435,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToR8IOSurface) ...@@ -379,6 +435,8 @@ TEST_P(IOSurfaceClientBufferTest, RenderToR8IOSurface)
// Test reading from R8 IOSurfaces // Test reading from R8 IOSurfaces
TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface) TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1);
uint8_t color = 1; uint8_t color = 1;
...@@ -388,8 +446,12 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface) ...@@ -388,8 +446,12 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
// Test using R16 IOSurfaces for rendering // Test using R16 IOSurfaces for rendering
TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface) TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
// This test only works on ES3. // This test only works on ES3.
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
// TODO(http://anglebug.com/4369)
ANGLE_SKIP_TEST_IF(isSwiftshader());
// HACK(cwallez@chromium.org) 'L016' doesn't seem to be an official pixel format but it works // HACK(cwallez@chromium.org) 'L016' doesn't seem to be an official pixel format but it works
// sooooooo let's test using it // sooooooo let's test using it
...@@ -406,12 +468,16 @@ TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface) ...@@ -406,12 +468,16 @@ TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface)
// Test blitting from IOSurface // Test blitting from IOSurface
TEST_P(IOSurfaceClientBufferTest, BlitFromIOSurface) TEST_P(IOSurfaceClientBufferTest, BlitFromIOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
doBlitTest(true, 2, 2); doBlitTest(true, 2, 2);
} }
// Test blitting to IOSurface // Test blitting to IOSurface
TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface) TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
doBlitTest(false, 2, 2); doBlitTest(false, 2, 2);
} }
...@@ -419,6 +485,8 @@ TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface) ...@@ -419,6 +485,8 @@ TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface)
// IOSurface // IOSurface
TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
// Success case // Success case
...@@ -428,7 +496,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -428,7 +496,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -450,7 +518,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -450,7 +518,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
const EGLint attribs[] = { const EGLint attribs[] = {
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -470,7 +538,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -470,7 +538,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
const EGLint attribs[] = { const EGLint attribs[] = {
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -490,7 +558,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -490,7 +558,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
const EGLint attribs[] = { const EGLint attribs[] = {
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -532,7 +600,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -532,7 +600,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE,
...@@ -553,7 +621,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -553,7 +621,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE,
...@@ -573,7 +641,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -573,7 +641,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE,
...@@ -590,6 +658,8 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) ...@@ -590,6 +658,8 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
// Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface // Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
// Success case // Success case
...@@ -599,7 +669,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -599,7 +669,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -622,7 +692,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -622,7 +692,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -643,7 +713,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -643,7 +713,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 0, EGL_WIDTH, 0,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -664,7 +734,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -664,7 +734,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 11, EGL_WIDTH, 11,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -685,7 +755,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -685,7 +755,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 0, EGL_HEIGHT, 0,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -706,7 +776,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -706,7 +776,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 11, EGL_HEIGHT, 11,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -720,14 +790,27 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -720,14 +790,27 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE); EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
} }
// EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE // EGL_TEXTURE_FORMAT must be equal to the config's texture target
{
EGLint target = getTextureTarget();
EGLint wrongTarget = 0;
switch (target)
{ {
case EGL_TEXTURE_RECTANGLE_ANGLE:
wrongTarget = EGL_TEXTURE_2D;
break;
case EGL_TEXTURE_2D:
wrongTarget = EGL_TEXTURE_RECTANGLE_ANGLE;
break;
default:
break;
}
// clang-format off // clang-format off
const EGLint attribs[] = { const EGLint attribs[] = {
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_TEXTURE_TARGET, wrongTarget,
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -748,7 +831,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -748,7 +831,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, -1, EGL_IOSURFACE_PLANE_ANGLE, -1,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -769,7 +852,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -769,7 +852,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 1, EGL_IOSURFACE_PLANE_ANGLE, 1,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -790,7 +873,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -790,7 +873,7 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
EGL_WIDTH, 10, EGL_WIDTH, 10,
EGL_HEIGHT, 10, EGL_HEIGHT, 10,
EGL_IOSURFACE_PLANE_ANGLE, 0, EGL_IOSURFACE_PLANE_ANGLE, 0,
EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE, EGL_TEXTURE_TARGET, getTextureTarget(),
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
...@@ -808,6 +891,8 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) ...@@ -808,6 +891,8 @@ TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
// Test IOSurface pbuffers can be made current // Test IOSurface pbuffers can be made current
TEST_P(IOSurfaceClientBufferTest, MakeCurrent) TEST_P(IOSurfaceClientBufferTest, MakeCurrent)
{ {
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4); ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
EGLSurface pbuffer; EGLSurface pbuffer;
...@@ -827,4 +912,8 @@ TEST_P(IOSurfaceClientBufferTest, MakeCurrent) ...@@ -827,4 +912,8 @@ TEST_P(IOSurfaceClientBufferTest, MakeCurrent)
// TODO(cwallez@chromium.org): Test setting width and height to less than the IOSurface's work as // TODO(cwallez@chromium.org): Test setting width and height to less than the IOSurface's work as
// expected. // expected.
ANGLE_INSTANTIATE_TEST(IOSurfaceClientBufferTest, ES2_OPENGL(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(IOSurfaceClientBufferTest,
ES2_OPENGL(),
ES3_OPENGL(),
ES2_VULKAN_SWIFTSHADER(),
ES3_VULKAN_SWIFTSHADER());
...@@ -372,6 +372,12 @@ ANGLETestBase::ANGLETestBase(const PlatformParameters &params) ...@@ -372,6 +372,12 @@ ANGLETestBase::ANGLETestBase(const PlatformParameters &params)
PlatformParameters withMethods = params; PlatformParameters withMethods = params;
withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods; withMethods.eglParameters.platformMethods = &gDefaultPlatformMethods;
// We don't build vulkan debug layers on Mac (http://anglebug.com/4376)
if (IsOSX() && withMethods.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
{
withMethods.eglParameters.debugLayersEnabled = false;
}
auto iter = gFixtures.find(withMethods); auto iter = gFixtures.find(withMethods);
if (iter != gFixtures.end()) if (iter != gFixtures.end())
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment