Initial Android surface
Bug: dawn:286
Change-Id: I50b45706f031254ac5beba5c07c3c4c3d7f9ea12
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/84200
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3813bfe..6dd0b02 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,6 +88,9 @@
endif()
elseif(APPLE)
set(ENABLE_METAL ON)
+elseif(ANDROID)
+ set(ENABLE_VULKAN ON)
+ set(ENABLE_OPENGLES ON)
elseif(UNIX)
set(ENABLE_OPENGLES ON)
set(ENABLE_DESKTOP_GL ON)
@@ -96,7 +99,7 @@
endif()
# GLFW is not supported in UWP
-if((WIN32 AND NOT WINDOWS_STORE) OR UNIX)
+if((WIN32 AND NOT WINDOWS_STORE) OR UNIX AND NOT ANDROID)
set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING ON)
endif()
diff --git a/dawn_wire.json b/dawn_wire.json
index 58ef049..2e2318e 100644
--- a/dawn_wire.json
+++ b/dawn_wire.json
@@ -176,7 +176,8 @@
"SurfaceDescriptorFromWindowsHWND",
"SurfaceDescriptorFromXlibWindow",
"SurfaceDescriptorFromWindowsCoreWindow",
- "SurfaceDescriptorFromWindowsSwapChainPanel"
+ "SurfaceDescriptorFromWindowsSwapChainPanel",
+ "SurfaceDescriptorFromAndroidNativeWindow"
],
"client_side_commands": [
"AdapterCreateDevice",
diff --git a/src/dawn/native/Surface.cpp b/src/dawn/native/Surface.cpp
index bede05f..378a275 100644
--- a/src/dawn/native/Surface.cpp
+++ b/src/dawn/native/Surface.cpp
@@ -50,6 +50,9 @@
case Surface::Type::Xlib:
s->Append("Xlib");
break;
+ case Surface::Type::AndroidWindow:
+ s->Append("AndroidWindow");
+ break;
}
return {true};
}
@@ -65,6 +68,7 @@
descriptor);
DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
+ wgpu::SType::SurfaceDescriptorFromAndroidNativeWindow,
wgpu::SType::SurfaceDescriptorFromMetalLayer,
wgpu::SType::SurfaceDescriptorFromWindowsHWND,
wgpu::SType::SurfaceDescriptorFromWindowsCoreWindow,
@@ -82,6 +86,17 @@
}
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
+#if defined(DAWN_PLATFORM_ANDROID)
+ const SurfaceDescriptorFromAndroidNativeWindow* androidDesc = nullptr;
+ FindInChain(descriptor->nextInChain, &androidDesc);
+ // Currently the best validation we can do since it's not possible to check if the pointer
+ // to a ANativeWindow is valid.
+ if (androidDesc) {
+ DAWN_INVALID_IF(androidDesc->window == nullptr, "Android window is not set.");
+ return {};
+ }
+#endif // defined(DAWN_PLATFORM_ANDROID)
+
#if defined(DAWN_PLATFORM_WINDOWS)
# if defined(DAWN_PLATFORM_WIN32)
const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
@@ -142,20 +157,24 @@
Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
: mInstance(instance) {
ASSERT(descriptor->nextInChain != nullptr);
+ const SurfaceDescriptorFromAndroidNativeWindow* androidDesc = nullptr;
const SurfaceDescriptorFromMetalLayer* metalDesc = nullptr;
const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
const SurfaceDescriptorFromWindowsCoreWindow* coreWindowDesc = nullptr;
const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
const SurfaceDescriptorFromXlibWindow* xDesc = nullptr;
+ FindInChain(descriptor->nextInChain, &androidDesc);
FindInChain(descriptor->nextInChain, &metalDesc);
FindInChain(descriptor->nextInChain, &hwndDesc);
FindInChain(descriptor->nextInChain, &coreWindowDesc);
FindInChain(descriptor->nextInChain, &swapChainPanelDesc);
FindInChain(descriptor->nextInChain, &xDesc);
- ASSERT(metalDesc || hwndDesc || xDesc);
if (metalDesc) {
mType = Type::MetalLayer;
mMetalLayer = metalDesc->layer;
+ } else if (androidDesc) {
+ mType = Type::AndroidWindow;
+ mAndroidNativeWindow = androidDesc->window;
} else if (hwndDesc) {
mType = Type::WindowsHWND;
mHInstance = hwndDesc->hinstance;
@@ -202,6 +221,11 @@
return mType;
}
+ void* Surface::GetAndroidNativeWindow() const {
+ ASSERT(mType == Type::AndroidWindow);
+ return mAndroidNativeWindow;
+ }
+
void* Surface::GetMetalLayer() const {
ASSERT(mType == Type::MetalLayer);
return mMetalLayer;
diff --git a/src/dawn/native/Surface.h b/src/dawn/native/Surface.h
index c6320af..367a298 100644
--- a/src/dawn/native/Surface.h
+++ b/src/dawn/native/Surface.h
@@ -50,13 +50,23 @@
NewSwapChainBase* GetAttachedSwapChain();
// These are valid to call on all Surfaces.
- enum class Type { MetalLayer, WindowsHWND, WindowsCoreWindow, WindowsSwapChainPanel, Xlib };
+ enum class Type {
+ AndroidWindow,
+ MetalLayer,
+ WindowsHWND,
+ WindowsCoreWindow,
+ WindowsSwapChainPanel,
+ Xlib
+ };
Type GetType() const;
InstanceBase* GetInstance();
// Valid to call if the type is MetalLayer
void* GetMetalLayer() const;
+ // Valid to call if the type is Android
+ void* GetAndroidNativeWindow() const;
+
// Valid to call if the type is WindowsHWND
void* GetHInstance() const;
void* GetHWND() const;
@@ -83,6 +93,9 @@
// MetalLayer
void* mMetalLayer = nullptr;
+ // ANativeWindow
+ void* mAndroidNativeWindow = nullptr;
+
// WindowsHwnd
void* mHInstance = nullptr;
void* mHWND = nullptr;
diff --git a/src/dawn/native/SwapChain.cpp b/src/dawn/native/SwapChain.cpp
index 6b4c331..5fffc09 100644
--- a/src/dawn/native/SwapChain.cpp
+++ b/src/dawn/native/SwapChain.cpp
@@ -74,11 +74,17 @@
DAWN_TRY(ValidatePresentMode(descriptor->presentMode));
- // TODO(crbug.com/dawn/160): Lift this restriction once
- // wgpu::Instance::GetPreferredSurfaceFormat is implemented.
- DAWN_INVALID_IF(descriptor->format != wgpu::TextureFormat::BGRA8Unorm,
+// TODO(crbug.com/dawn/160): Lift this restriction once wgpu::Instance::GetPreferredSurfaceFormat is
+// implemented.
+// TODO(dawn:286):
+#if defined(DAWN_PLATFORM_ANDROID)
+ constexpr wgpu::TextureFormat kRequireSwapChainFormat = wgpu::TextureFormat::RGBA8Unorm;
+#else
+ constexpr wgpu::TextureFormat kRequireSwapChainFormat = wgpu::TextureFormat::BGRA8Unorm;
+#endif // !defined(DAWN_PLATFORM_ANDROID)
+ DAWN_INVALID_IF(descriptor->format != kRequireSwapChainFormat,
"Format (%s) is not %s, which is (currently) the only accepted format.",
- descriptor->format, wgpu::TextureFormat::BGRA8Unorm);
+ descriptor->format, kRequireSwapChainFormat);
DAWN_INVALID_IF(descriptor->usage != wgpu::TextureUsage::RenderAttachment,
"Usage (%s) is not %s, which is (currently) the only accepted usage.",
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp
index d0750e6..2c80d06 100644
--- a/src/dawn/native/vulkan/SwapChainVk.cpp
+++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -134,6 +134,30 @@
break;
#endif // defined(DAWN_PLATFORM_WINDOWS)
+#if defined(DAWN_PLATFORM_ANDROID)
+ case Surface::Type::AndroidWindow: {
+ if (info.HasExt(InstanceExt::AndroidSurface)) {
+ ASSERT(surface->GetAndroidNativeWindow() != nullptr);
+
+ VkAndroidSurfaceCreateInfoKHR createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ createInfo.pNext = nullptr;
+ createInfo.flags = 0;
+ createInfo.window =
+ static_cast<struct ANativeWindow*>(surface->GetAndroidNativeWindow());
+
+ VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+ DAWN_TRY(CheckVkSuccess(
+ fn.CreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+ "CreateAndroidSurfaceKHR"));
+ return vkSurface;
+ }
+
+ break;
+ }
+
+#endif // defined(DAWN_PLATFORM_ANDROID)
+
#if defined(DAWN_USE_X11)
case Surface::Type::Xlib: {
if (info.HasExt(InstanceExt::XlibSurface)) {
@@ -382,22 +406,22 @@
config.wgpuUsage = GetUsage();
}
- // Only support BGRA8Unorm with SRGB color space for now.
- bool hasBGRA8Unorm = false;
+ // Only support BGRA8Unorm (and RGBA8Unorm on android) with SRGB color space for now.
+ config.wgpuFormat = GetFormat();
+ config.format = VulkanImageFormat(ToBackend(GetDevice()), config.wgpuFormat);
+ config.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+
+ bool formatIsSupported = false;
for (const VkSurfaceFormatKHR& format : surfaceInfo.formats) {
- if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
- format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
- hasBGRA8Unorm = true;
+ if (format.format == config.format && format.colorSpace == config.colorSpace) {
+ formatIsSupported = true;
break;
}
}
- if (!hasBGRA8Unorm) {
- return DAWN_INTERNAL_ERROR(
- "Vulkan SwapChain must support BGRA8Unorm with sRGB colorspace.");
+ if (!formatIsSupported) {
+ return DAWN_INTERNAL_ERROR(absl::StrFormat(
+ "Vulkan SwapChain must support %s with sRGB colorspace.", config.wgpuFormat));
}
- config.format = VK_FORMAT_B8G8R8A8_UNORM;
- config.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
- config.wgpuFormat = wgpu::TextureFormat::BGRA8Unorm;
// Only the identity transform with opaque alpha is supported for now.
DAWN_INVALID_IF((surfaceInfo.capabilities.supportedTransforms &
@@ -406,11 +430,26 @@
config.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- DAWN_INVALID_IF((surfaceInfo.capabilities.supportedCompositeAlpha &
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0,
- "Vulkan SwapChain must support opaque alpha.");
-
config.alphaMode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+#if !defined(DAWN_PLATFORM_ANDROID)
+ DAWN_INVALID_IF((surfaceInfo.capabilities.supportedCompositeAlpha &
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0,
+ "Vulkan SwapChain must support opaque alpha.");
+#else
+ // TODO(dawn:286): investigate composite alpha for WebGPU native
+ VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = {
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ };
+ for (uint32_t i = 0; i < 4; i++) {
+ if (surfCapabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) {
+ config.alphaMode = compositeAlphaFlags[i];
+ break;
+ }
+ }
+#endif // #if !defined(DAWN_PLATFORM_ANDROID)
// Choose the number of images for the swapchain= and clamp it to the min and max from the
// surface capabilities. maxImageCount = 0 means there is no limit.
diff --git a/src/dawn/native/vulkan/VulkanExtensions.cpp b/src/dawn/native/vulkan/VulkanExtensions.cpp
index e34736e..3f54e54 100644
--- a/src/dawn/native/vulkan/VulkanExtensions.cpp
+++ b/src/dawn/native/vulkan/VulkanExtensions.cpp
@@ -47,6 +47,7 @@
{InstanceExt::Win32Surface, "VK_KHR_win32_surface", NeverPromoted},
{InstanceExt::XcbSurface, "VK_KHR_xcb_surface", NeverPromoted},
{InstanceExt::XlibSurface, "VK_KHR_xlib_surface", NeverPromoted},
+ {InstanceExt::AndroidSurface, "VK_KHR_android_surface", NeverPromoted},
{InstanceExt::DebugUtils, "VK_EXT_debug_utils", NeverPromoted},
{InstanceExt::ValidationFeatures, "VK_EXT_validation_features", NeverPromoted},
@@ -99,6 +100,7 @@
hasDependencies = HasDep(InstanceExt::GetPhysicalDeviceProperties2);
break;
+ case InstanceExt::AndroidSurface:
case InstanceExt::FuchsiaImagePipeSurface:
case InstanceExt::MetalSurface:
case InstanceExt::WaylandSurface:
diff --git a/src/dawn/native/vulkan/VulkanExtensions.h b/src/dawn/native/vulkan/VulkanExtensions.h
index 4e3cf19..d58c35e 100644
--- a/src/dawn/native/vulkan/VulkanExtensions.h
+++ b/src/dawn/native/vulkan/VulkanExtensions.h
@@ -37,6 +37,7 @@
Win32Surface,
XcbSurface,
XlibSurface,
+ AndroidSurface,
// Others
DebugUtils,
diff --git a/src/dawn/native/vulkan/VulkanFunctions.cpp b/src/dawn/native/vulkan/VulkanFunctions.cpp
index 782cd5a..48e9709 100644
--- a/src/dawn/native/vulkan/VulkanFunctions.cpp
+++ b/src/dawn/native/vulkan/VulkanFunctions.cpp
@@ -147,6 +147,12 @@
}
#endif // defined(DAWN_PLATFORM_WINDOWS)
+#if defined(DAWN_PLATFORM_ANDROID)
+ if (globalInfo.HasExt(InstanceExt::AndroidSurface)) {
+ GET_INSTANCE_PROC(CreateAndroidSurfaceKHR);
+ }
+#endif // defined(DAWN_PLATFORM_ANDROID)
+
#if defined(DAWN_USE_X11)
if (globalInfo.HasExt(InstanceExt::XlibSurface)) {
GET_INSTANCE_PROC(CreateXlibSurfaceKHR);
diff --git a/src/dawn/native/vulkan/VulkanFunctions.h b/src/dawn/native/vulkan/VulkanFunctions.h
index 07b8b39..0de5192 100644
--- a/src/dawn/native/vulkan/VulkanFunctions.h
+++ b/src/dawn/native/vulkan/VulkanFunctions.h
@@ -132,6 +132,10 @@
GetPhysicalDeviceWin32PresentationSupportKHR = nullptr;
#endif // defined(DAWN_PLATFORM_WINDOWS)
+#if defined(DAWN_PLATFORM_ANDROID)
+ PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR = nullptr;
+#endif // defined(DAWN_PLATFORM_ANDROID)
+
#if defined(DAWN_USE_X11)
// KHR_xlib_surface
PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR = nullptr;
diff --git a/src/dawn/utils/CMakeLists.txt b/src/dawn/utils/CMakeLists.txt
index 3ed0994..6e4d6f7 100644
--- a/src/dawn/utils/CMakeLists.txt
+++ b/src/dawn/utils/CMakeLists.txt
@@ -43,7 +43,6 @@
dawn_proc
dawn_wire
SPIRV-Tools-opt
- glfw
)
if(WIN32 AND NOT WINDOWS_STORE)
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 7c8619f..136c848 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -32,7 +32,7 @@
add_subdirectory(${DAWN_SPIRV_TOOLS_DIR} "${CMAKE_CURRENT_BINARY_DIR}/spirv-tools")
endif()
-if (NOT TARGET glfw)
+if (NOT TARGET glfw AND DAWN_SUPPORTS_GLFW_FOR_WINDOWING)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)