Introduce wgpu::Surface and implement it for HWND, X11 and Metal
This is another step to implement webgpu.h swapchains, Surface is essentially a union type of all the types of windows that can be used to create swapchains. Changes to allow implementing wgpu::Surface and test its creation are: - Add GLFWUtils.cpp/.h/_metal.mm that contains helpers used to use WebGPU with GLFW. This deprecates BackendBinding.h that will be removed when the NXT swapchain is removed. - Add a `dawn_use_x11` GN variable to factor all the places in BUILD.gn where we checked whether we should use X11. - Add a `supports_glfw_for_windowing` GN variable in the main BUILD.gn file to control which configuration tests and samples using GLFW can be built. - Add a ObjCUtils.h to contain some ObjC functionality that we'd need in files that otherwise would be C++ (so that they can be compiled on all platforms). Bug: dawn:269 Change-Id: I25548142a1d1d1f05b0f4d71aa3bdc4698d19622 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15081 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
2b24c3d92d
commit
3a1746e71c
72
BUILD.gn
72
BUILD.gn
|
@ -263,6 +263,8 @@ source_set("libdawn_native_sources") {
|
||||||
"src/dawn_native/ShaderModule.h",
|
"src/dawn_native/ShaderModule.h",
|
||||||
"src/dawn_native/StagingBuffer.cpp",
|
"src/dawn_native/StagingBuffer.cpp",
|
||||||
"src/dawn_native/StagingBuffer.h",
|
"src/dawn_native/StagingBuffer.h",
|
||||||
|
"src/dawn_native/Surface.cpp",
|
||||||
|
"src/dawn_native/Surface.h",
|
||||||
"src/dawn_native/SwapChain.cpp",
|
"src/dawn_native/SwapChain.cpp",
|
||||||
"src/dawn_native/SwapChain.h",
|
"src/dawn_native/SwapChain.h",
|
||||||
"src/dawn_native/Texture.cpp",
|
"src/dawn_native/Texture.cpp",
|
||||||
|
@ -346,8 +348,10 @@ source_set("libdawn_native_sources") {
|
||||||
"Cocoa.framework",
|
"Cocoa.framework",
|
||||||
"IOKit.framework",
|
"IOKit.framework",
|
||||||
"IOSurface.framework",
|
"IOSurface.framework",
|
||||||
|
"QuartzCore.framework",
|
||||||
]
|
]
|
||||||
sources += [
|
sources += [
|
||||||
|
"src/dawn_native/Surface_metal.mm",
|
||||||
"src/dawn_native/metal/BackendMTL.h",
|
"src/dawn_native/metal/BackendMTL.h",
|
||||||
"src/dawn_native/metal/BackendMTL.mm",
|
"src/dawn_native/metal/BackendMTL.mm",
|
||||||
"src/dawn_native/metal/BufferMTL.h",
|
"src/dawn_native/metal/BufferMTL.h",
|
||||||
|
@ -541,6 +545,10 @@ source_set("libdawn_native_sources") {
|
||||||
[ "DAWN_SWIFTSHADER_VK_ICD_JSON=\"${swiftshader_icd_file_name}\"" ]
|
[ "DAWN_SWIFTSHADER_VK_ICD_JSON=\"${swiftshader_icd_file_name}\"" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dawn_use_x11) {
|
||||||
|
libs += [ "X11" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# The static and shared libraries for libdawn_native. Most of the files are
|
# The static and shared libraries for libdawn_native. Most of the files are
|
||||||
|
@ -662,10 +670,12 @@ dawn_component("libdawn_wire") {
|
||||||
# GLFW wrapping target
|
# GLFW wrapping target
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
supports_glfw_for_windowing = is_win || (is_linux && !is_chromeos) || is_mac
|
||||||
|
|
||||||
# GLFW does not support ChromeOS, Android or Fuchsia, so provide a small mock
|
# GLFW does not support ChromeOS, Android or Fuchsia, so provide a small mock
|
||||||
# library that can be linked into the Dawn tests on these platforms. Otherwise,
|
# library that can be linked into the Dawn tests on these platforms. Otherwise,
|
||||||
# use the real library from third_party/.
|
# use the real library from third_party/.
|
||||||
if (is_win || (is_linux && !is_chromeos) || is_mac) {
|
if (supports_glfw_for_windowing) {
|
||||||
group("dawn_glfw") {
|
group("dawn_glfw") {
|
||||||
public_deps = [
|
public_deps = [
|
||||||
"third_party:glfw",
|
"third_party:glfw",
|
||||||
|
@ -724,25 +734,43 @@ static_library("dawn_utils") {
|
||||||
"src/utils/WGPUHelpers.cpp",
|
"src/utils/WGPUHelpers.cpp",
|
||||||
"src/utils/WGPUHelpers.h",
|
"src/utils/WGPUHelpers.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (is_win) {
|
|
||||||
sources += [ "src/utils/WindowsTimer.cpp" ]
|
|
||||||
} else if (is_mac) {
|
|
||||||
sources += [ "src/utils/OSXTimer.cpp" ]
|
|
||||||
} else {
|
|
||||||
sources += [ "src/utils/PosixTimer.cpp" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
public_deps = [
|
|
||||||
"${dawn_root}/src/dawn:dawncpp_headers",
|
|
||||||
]
|
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":libdawn_native",
|
":libdawn_native",
|
||||||
":libdawn_wire",
|
":libdawn_wire",
|
||||||
"${dawn_root}/src/common",
|
"${dawn_root}/src/common",
|
||||||
"${dawn_shaderc_dir}:libshaderc",
|
"${dawn_shaderc_dir}:libshaderc",
|
||||||
]
|
]
|
||||||
|
libs = []
|
||||||
|
|
||||||
|
if (is_win) {
|
||||||
|
sources += [ "src/utils/WindowsTimer.cpp" ]
|
||||||
|
} else if (is_mac) {
|
||||||
|
sources += [
|
||||||
|
"src/utils/OSXTimer.cpp",
|
||||||
|
"src/utils/ObjCUtils.h",
|
||||||
|
"src/utils/ObjCUtils.mm",
|
||||||
|
]
|
||||||
|
libs += [ "QuartzCore.framework" ]
|
||||||
|
} else {
|
||||||
|
sources += [ "src/utils/PosixTimer.cpp" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supports_glfw_for_windowing) {
|
||||||
|
sources += [
|
||||||
|
"src/utils/GLFWUtils.cpp",
|
||||||
|
"src/utils/GLFWUtils.h",
|
||||||
|
]
|
||||||
|
deps += [ ":dawn_glfw" ]
|
||||||
|
|
||||||
|
if (dawn_enable_metal) {
|
||||||
|
sources += [ "src/utils/GLFWUtils_metal.mm" ]
|
||||||
|
libs += [ "Metal.framework" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public_deps = [
|
||||||
|
"${dawn_root}/src/dawn:dawncpp_headers",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -915,12 +943,6 @@ source_set("dawn_end2end_tests_sources") {
|
||||||
|
|
||||||
libs = []
|
libs = []
|
||||||
|
|
||||||
if (dawn_enable_metal) {
|
|
||||||
sources += [ "src/tests/end2end/IOSurfaceWrappingTests.cpp" ]
|
|
||||||
|
|
||||||
libs += [ "IOSurface.framework" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dawn_enable_d3d12) {
|
if (dawn_enable_d3d12) {
|
||||||
sources += [ "src/tests/end2end/D3D12ResourceWrappingTests.cpp" ]
|
sources += [ "src/tests/end2end/D3D12ResourceWrappingTests.cpp" ]
|
||||||
libs += [
|
libs += [
|
||||||
|
@ -929,7 +951,17 @@ source_set("dawn_end2end_tests_sources") {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dawn_enable_metal) {
|
||||||
|
sources += [ "src/tests/end2end/IOSurfaceWrappingTests.cpp" ]
|
||||||
|
libs += [ "IOSurface.framework" ]
|
||||||
|
}
|
||||||
|
|
||||||
if (dawn_enable_opengl) {
|
if (dawn_enable_opengl) {
|
||||||
|
assert(supports_glfw_for_windowing)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supports_glfw_for_windowing) {
|
||||||
|
sources += [ "src/tests/end2end/WindowSurfaceTests.cpp" ]
|
||||||
deps += [ ":dawn_glfw" ]
|
deps += [ ":dawn_glfw" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
49
dawn.json
49
dawn.json
|
@ -771,7 +771,16 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"instance": {
|
"instance": {
|
||||||
"category": "object"
|
"category": "object",
|
||||||
|
"methods": [
|
||||||
|
{
|
||||||
|
"name": "create surface",
|
||||||
|
"returns": "surface",
|
||||||
|
"args": [
|
||||||
|
{"name": "descriptor", "type": "surface descriptor", "annotation": "const*"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"instance descriptor": {
|
"instance descriptor": {
|
||||||
"category": "structure",
|
"category": "structure",
|
||||||
|
@ -1274,6 +1283,39 @@
|
||||||
{"name": "pass op", "type": "stencil operation", "default": "keep"}
|
{"name": "pass op", "type": "stencil operation", "default": "keep"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"surface": {
|
||||||
|
"category": "object"
|
||||||
|
},
|
||||||
|
"surface descriptor": {
|
||||||
|
"category": "structure",
|
||||||
|
"extensible": true,
|
||||||
|
"members": [
|
||||||
|
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"surface descriptor from metal layer": {
|
||||||
|
"category": "structure",
|
||||||
|
"chained": true,
|
||||||
|
"members": [
|
||||||
|
{"name": "layer", "type": "void", "annotation": "*"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"surface descriptor from windows HWND": {
|
||||||
|
"category": "structure",
|
||||||
|
"chained": true,
|
||||||
|
"members": [
|
||||||
|
{"name": "hinstance", "type": "void", "annotation": "*"},
|
||||||
|
{"name": "hwnd", "type": "void", "annotation": "*"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"surface descriptor from xlib": {
|
||||||
|
"category": "structure",
|
||||||
|
"chained": true,
|
||||||
|
"members": [
|
||||||
|
{"name": "display", "type": "void", "annotation": "*"},
|
||||||
|
{"name": "window", "type": "uint32_t"}
|
||||||
|
]
|
||||||
|
},
|
||||||
"swap chain": {
|
"swap chain": {
|
||||||
"category": "object",
|
"category": "object",
|
||||||
"methods": [
|
"methods": [
|
||||||
|
@ -1301,7 +1343,10 @@
|
||||||
"s type": {
|
"s type": {
|
||||||
"category": "enum",
|
"category": "enum",
|
||||||
"values": [
|
"values": [
|
||||||
{"value": 0, "name": "invalid"}
|
{"value": 0, "name": "invalid"},
|
||||||
|
{"value": 1, "name": "surface descriptor from metal layer"},
|
||||||
|
{"value": 2, "name": "surface descriptor from windows HWND"},
|
||||||
|
{"value": 3, "name": "surface descriptor from xlib"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"texture": {
|
"texture": {
|
||||||
|
|
|
@ -89,7 +89,10 @@
|
||||||
},
|
},
|
||||||
"special items": {
|
"special items": {
|
||||||
"client_side_structures": [
|
"client_side_structures": [
|
||||||
"CreateBufferMappedResult"
|
"CreateBufferMappedResult",
|
||||||
|
"SurfaceDescriptorFromMetalLayer",
|
||||||
|
"SurfaceDescriptorFromWindowsHWND",
|
||||||
|
"SurfaceDescriptorFromXlib"
|
||||||
],
|
],
|
||||||
"client_side_commands": [
|
"client_side_commands": [
|
||||||
"BufferMapReadAsync",
|
"BufferMapReadAsync",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "common/Log.h"
|
#include "common/Log.h"
|
||||||
#include "common/Platform.h"
|
#include "common/Platform.h"
|
||||||
#include "utils/BackendBinding.h"
|
#include "utils/BackendBinding.h"
|
||||||
|
#include "utils/GLFWUtils.h"
|
||||||
#include "utils/TerribleCommandBuffer.h"
|
#include "utils/TerribleCommandBuffer.h"
|
||||||
|
|
||||||
#include <dawn/dawn_proc.h>
|
#include <dawn/dawn_proc.h>
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace dawn_native {
|
||||||
using FenceBase = Fence;
|
using FenceBase = Fence;
|
||||||
using RenderPassEncoderBase = RenderPassEncoder;
|
using RenderPassEncoderBase = RenderPassEncoder;
|
||||||
using RenderBundleEncoderBase = RenderBundleEncoder;
|
using RenderBundleEncoderBase = RenderBundleEncoder;
|
||||||
|
using SurfaceBase = Surface;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,9 @@ declare_args() {
|
||||||
# Enables error injection for faking failures to native API calls
|
# Enables error injection for faking failures to native API calls
|
||||||
dawn_enable_error_injection =
|
dawn_enable_error_injection =
|
||||||
is_debug || (build_with_chromium && use_fuzzing_engine)
|
is_debug || (build_with_chromium && use_fuzzing_engine)
|
||||||
|
|
||||||
|
# Whether Dawn should enable X11 support.
|
||||||
|
dawn_use_x11 = is_linux && !is_chromeos
|
||||||
}
|
}
|
||||||
|
|
||||||
# GN does not allow reading a variable defined in the same declare_args().
|
# GN does not allow reading a variable defined in the same declare_args().
|
||||||
|
|
|
@ -75,7 +75,7 @@ config("dawn_internal") {
|
||||||
defines += [ "DAWN_ENABLE_BACKEND_VULKAN" ]
|
defines += [ "DAWN_ENABLE_BACKEND_VULKAN" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_linux && !is_chromeos) {
|
if (dawn_use_x11) {
|
||||||
defines += [ "DAWN_USE_X11" ]
|
defines += [ "DAWN_USE_X11" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
// Macros defined for ANSI / Unicode support
|
// Macros defined for ANSI / Unicode support
|
||||||
|
#undef CreateWindow
|
||||||
#undef GetMessage
|
#undef GetMessage
|
||||||
|
|
||||||
// Macros defined to produce compiler intrinsics
|
// Macros defined to produce compiler intrinsics
|
||||||
|
|
|
@ -30,4 +30,6 @@
|
||||||
#undef None
|
#undef None
|
||||||
#undef Always
|
#undef Always
|
||||||
|
|
||||||
|
using XErrorHandler = int (*)(Display*, XErrorEvent*);
|
||||||
|
|
||||||
#endif // COMMON_XLIB_WITH_UNDEFS_H_
|
#endif // COMMON_XLIB_WITH_UNDEFS_H_
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "common/Assert.h"
|
#include "common/Assert.h"
|
||||||
#include "common/Log.h"
|
#include "common/Log.h"
|
||||||
#include "dawn_native/ErrorData.h"
|
#include "dawn_native/ErrorData.h"
|
||||||
|
#include "dawn_native/Surface.h"
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
|
@ -211,4 +212,12 @@ namespace dawn_native {
|
||||||
return mPlatform;
|
return mPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Surface* InstanceBase::CreateSurface(const SurfaceDescriptor* descriptor) {
|
||||||
|
if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Surface(this, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
|
class Surface;
|
||||||
|
|
||||||
// This is called InstanceBase for consistency across the frontend, even if the backends don't
|
// This is called InstanceBase for consistency across the frontend, even if the backends don't
|
||||||
// specialize this class.
|
// specialize this class.
|
||||||
class InstanceBase final : public RefCounted {
|
class InstanceBase final : public RefCounted {
|
||||||
|
@ -64,6 +66,9 @@ namespace dawn_native {
|
||||||
void SetPlatform(dawn_platform::Platform* platform);
|
void SetPlatform(dawn_platform::Platform* platform);
|
||||||
dawn_platform::Platform* GetPlatform() const;
|
dawn_platform::Platform* GetPlatform() const;
|
||||||
|
|
||||||
|
// Dawn API
|
||||||
|
Surface* CreateSurface(const SurfaceDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InstanceBase() = default;
|
InstanceBase() = default;
|
||||||
~InstanceBase() = default;
|
~InstanceBase() = default;
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
// Copyright 2020 the Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "dawn_native/Surface.h"
|
||||||
|
|
||||||
|
#include "common/Platform.h"
|
||||||
|
#include "dawn_native/Instance.h"
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
# include "common/windows_with_undefs.h"
|
||||||
|
#endif // DAWN_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
# include "common/xlib_with_undefs.h"
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
bool InheritsFromCAMetalLayer(void* obj);
|
||||||
|
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
|
||||||
|
const SurfaceDescriptor* descriptor) {
|
||||||
|
// TODO(cwallez@chromium.org): Have some type of helper to iterate over all the chained
|
||||||
|
// structures.
|
||||||
|
if (descriptor->nextInChain == nullptr) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Surface cannot be created with just the base descriptor");
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChainedStruct* chainedDescriptor = descriptor->nextInChain;
|
||||||
|
if (chainedDescriptor->nextInChain != nullptr) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Cannot specify two windows for a single surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (chainedDescriptor->sType) {
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromMetalLayer: {
|
||||||
|
const SurfaceDescriptorFromMetalLayer* metalDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromMetalLayer*>(chainedDescriptor);
|
||||||
|
|
||||||
|
// Check that the layer is a CAMetalLayer (or a derived class).
|
||||||
|
if (!InheritsFromCAMetalLayer(metalDesc->layer)) {
|
||||||
|
return DAWN_VALIDATION_ERROR("layer must be a CAMetalLayer");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromWindowsHWND: {
|
||||||
|
const SurfaceDescriptorFromWindowsHWND* hwndDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromWindowsHWND*>(chainedDescriptor);
|
||||||
|
|
||||||
|
// It is not possible to validate an HINSTANCE.
|
||||||
|
|
||||||
|
// Validate the hwnd using the windows.h IsWindow function.
|
||||||
|
if (IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Invalid HWND");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromXlib: {
|
||||||
|
const SurfaceDescriptorFromXlib* xDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromXlib*>(chainedDescriptor);
|
||||||
|
|
||||||
|
// It is not possible to validate an X Display.
|
||||||
|
|
||||||
|
// Check the validity of the window by calling a getter function on the window that
|
||||||
|
// returns a status code. If the window is bad the call return a status of zero. We
|
||||||
|
// need to set a temporary X11 error handler while doing this because the default
|
||||||
|
// X11 error handler exits the program on any error.
|
||||||
|
XErrorHandler oldErrorHandler =
|
||||||
|
XSetErrorHandler([](Display*, XErrorEvent*) { return 0; });
|
||||||
|
XWindowAttributes attributes;
|
||||||
|
int status = XGetWindowAttributes(reinterpret_cast<Display*>(xDesc->display),
|
||||||
|
xDesc->window, &attributes);
|
||||||
|
XSetErrorHandler(oldErrorHandler);
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Invalid X Window");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DAWN_VALIDATION_ERROR("Unsupported sType");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
|
||||||
|
: mInstance(instance) {
|
||||||
|
ASSERT(descriptor->nextInChain != nullptr);
|
||||||
|
const ChainedStruct* chainedDescriptor = descriptor->nextInChain;
|
||||||
|
|
||||||
|
switch (chainedDescriptor->sType) {
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromMetalLayer: {
|
||||||
|
const SurfaceDescriptorFromMetalLayer* metalDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromMetalLayer*>(chainedDescriptor);
|
||||||
|
mType = Type::MetalLayer;
|
||||||
|
mMetalLayer = metalDesc->layer;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromWindowsHWND: {
|
||||||
|
const SurfaceDescriptorFromWindowsHWND* hwndDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromWindowsHWND*>(chainedDescriptor);
|
||||||
|
mType = Type::WindowsHWND;
|
||||||
|
mHInstance = hwndDesc->hinstance;
|
||||||
|
mHWND = hwndDesc->hwnd;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case wgpu::SType::SurfaceDescriptorFromXlib: {
|
||||||
|
const SurfaceDescriptorFromXlib* xDesc =
|
||||||
|
static_cast<const SurfaceDescriptorFromXlib*>(chainedDescriptor);
|
||||||
|
mType = Type::Xlib;
|
||||||
|
mXDisplay = xDesc->display;
|
||||||
|
mXWindow = xDesc->window;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Surface::~Surface() = default;
|
||||||
|
|
||||||
|
InstanceBase* Surface::GetInstance() {
|
||||||
|
return mInstance.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Surface::Type Surface::GetType() const {
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Surface::GetMetalLayer() const {
|
||||||
|
ASSERT(mType == Type::MetalLayer);
|
||||||
|
return mMetalLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Surface::GetHInstance() const {
|
||||||
|
ASSERT(mType == Type::WindowsHWND);
|
||||||
|
return mHInstance;
|
||||||
|
}
|
||||||
|
void* Surface::GetHWND() const {
|
||||||
|
ASSERT(mType == Type::WindowsHWND);
|
||||||
|
return mHWND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Surface::GetXDisplay() const {
|
||||||
|
ASSERT(mType == Type::Xlib);
|
||||||
|
return mXDisplay;
|
||||||
|
}
|
||||||
|
uint32_t Surface::GetXWindow() const {
|
||||||
|
ASSERT(mType == Type::Xlib);
|
||||||
|
return mXWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef DAWNNATIVE_SURFACE_H_
|
||||||
|
#define DAWNNATIVE_SURFACE_H_
|
||||||
|
|
||||||
|
#include "dawn_native/Error.h"
|
||||||
|
#include "dawn_native/Forward.h"
|
||||||
|
#include "dawn_native/RefCounted.h"
|
||||||
|
|
||||||
|
#include "dawn_native/dawn_platform.h"
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
|
||||||
|
const SurfaceDescriptor* descriptor);
|
||||||
|
|
||||||
|
// A surface is a sum types of all the kind of windows Dawn supports. The OS-specific types
|
||||||
|
// aren't used because they would cause compilation errors on other OSes (or require
|
||||||
|
// ObjectiveC).
|
||||||
|
class Surface final : public RefCounted {
|
||||||
|
public:
|
||||||
|
Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor);
|
||||||
|
~Surface();
|
||||||
|
|
||||||
|
// These are valid to call on all Surfaces.
|
||||||
|
enum class Type { MetalLayer, WindowsHWND, Xlib };
|
||||||
|
Type GetType() const;
|
||||||
|
InstanceBase* GetInstance();
|
||||||
|
|
||||||
|
// Valid to call if the type is MetalLayer
|
||||||
|
void* GetMetalLayer() const;
|
||||||
|
|
||||||
|
// Valid to call if the type is WindowsHWND
|
||||||
|
void* GetHInstance() const;
|
||||||
|
void* GetHWND() const;
|
||||||
|
|
||||||
|
// Valid to call if the type is WindowsXlib
|
||||||
|
void* GetXDisplay() const;
|
||||||
|
uint32_t GetXWindow() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<InstanceBase> mInstance;
|
||||||
|
Type mType;
|
||||||
|
|
||||||
|
// MetalLayer
|
||||||
|
void* mMetalLayer = nullptr;
|
||||||
|
|
||||||
|
// WindowsHwnd
|
||||||
|
void* mHInstance = nullptr;
|
||||||
|
void* mHWND = nullptr;
|
||||||
|
|
||||||
|
// Xlib
|
||||||
|
void* mXDisplay = nullptr;
|
||||||
|
uint32_t mXWindow = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
||||||
|
|
||||||
|
#endif // DAWNNATIVE_SURFACE_H_
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2020 the Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Contains a helper function for Surface.cpp that needs to be written in ObjectiveC.
|
||||||
|
|
||||||
|
#if !defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
# error "Surface_metal.mm requires the Metal backend to be enabled."
|
||||||
|
#endif // !defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
namespace dawn_native {
|
||||||
|
|
||||||
|
bool InheritsFromCAMetalLayer(void* obj) {
|
||||||
|
id<NSObject> object = static_cast<id>(obj);
|
||||||
|
return [object isKindOfClass:[CAMetalLayer class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dawn_native
|
|
@ -0,0 +1,236 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "common/Log.h"
|
||||||
|
#include "common/Platform.h"
|
||||||
|
#include "dawn/dawn_proc.h"
|
||||||
|
#include "dawn_native/DawnNative.h"
|
||||||
|
#include "utils/GLFWUtils.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
# include "common/windows_with_undefs.h"
|
||||||
|
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
# include "common/xlib_with_undefs.h"
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
# include "utils/ObjCUtils.h"
|
||||||
|
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
#include "GLFW/glfw3native.h"
|
||||||
|
|
||||||
|
class WindowSurfaceInstanceTests : public testing::Test {
|
||||||
|
public:
|
||||||
|
void SetUp() override {
|
||||||
|
glfwSetErrorCallback([](int code, const char* message) {
|
||||||
|
dawn::ErrorLog() << "GLFW error " << code << " " << message;
|
||||||
|
});
|
||||||
|
glfwInit();
|
||||||
|
|
||||||
|
DawnProcTable procs = dawn_native::GetProcs();
|
||||||
|
dawnProcSetProcs(&procs);
|
||||||
|
|
||||||
|
mInstance = wgpu::CreateInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
if (mWindow != nullptr) {
|
||||||
|
glfwDestroyWindow(mWindow);
|
||||||
|
mWindow = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertSurfaceCreation(const wgpu::SurfaceDescriptor* descriptor, bool succeeds) {
|
||||||
|
ASSERT_EQ(mInstance.CreateSurface(descriptor).Get() != nullptr, succeeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* CreateWindow() {
|
||||||
|
// The WindowSurfaceInstance tests don't create devices so we don't need to call
|
||||||
|
// SetupGLFWWindowHintsForBackend. Set GLFW_NO_API anyway to avoid GLFW bringing up a GL
|
||||||
|
// context that we won't use.
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
mWindow = glfwCreateWindow(400, 400, "WindowSurfaceInstanceTests window", nullptr, nullptr);
|
||||||
|
return mWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wgpu::Instance mInstance;
|
||||||
|
GLFWwindow* mWindow = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test that a valid chained descriptor works (and that GLFWUtils creates a valid chained
|
||||||
|
// descriptor).
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, ControlCase) {
|
||||||
|
GLFWwindow* window = CreateWindow();
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = chainedDescriptor.get();
|
||||||
|
|
||||||
|
AssertSurfaceCreation(&descriptor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that just wgpu::SurfaceDescriptor isn't enough and needs a chained descriptor.
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, NoChainedDescriptors) {
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = nullptr; // That's the default value but we set it for clarity.
|
||||||
|
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a chained descriptor with a garbage sType produces an error.
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, BadChainedDescriptors) {
|
||||||
|
wgpu::ChainedStruct chainedDescriptor;
|
||||||
|
chainedDescriptor.sType = wgpu::SType::Invalid; // The default but we set it for clarity.
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that it is invalid to give two valid chained descriptors
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, TwoChainedDescriptors) {
|
||||||
|
GLFWwindow* window = CreateWindow();
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor1 =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor2 =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = chainedDescriptor1.get();
|
||||||
|
chainedDescriptor1->nextInChain = chainedDescriptor2.get();
|
||||||
|
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
// Tests that GLFWUtils returns a descriptor of HWND type
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, CorrectSTypeHWND) {
|
||||||
|
GLFWwindow* window = CreateWindow();
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromWindowsHWND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with setting an invalid hwnd
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, InvalidHWND) {
|
||||||
|
wgpu::SurfaceDescriptorFromWindowsHWND chainedDescriptor;
|
||||||
|
chainedDescriptor.hinstance = GetModuleHandle(nullptr);
|
||||||
|
chainedDescriptor.hwnd = 0; // This always is an invalid HWND value.
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
// Test using HWND when it is not supported
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, HWNDSurfacesAreInvalid) {
|
||||||
|
wgpu::SurfaceDescriptorFromWindowsHWND chainedDescriptor;
|
||||||
|
chainedDescriptor.hinstance = nullptr;
|
||||||
|
chainedDescriptor.hwnd = 0;
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
#if defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
// Tests that GLFWUtils returns a descriptor of Xlib type
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, CorrectSTypeXlib) {
|
||||||
|
GLFWwindow* window = CreateWindow();
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromXlib);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with setting an invalid window
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, InvalidXWindow) {
|
||||||
|
wgpu::SurfaceDescriptorFromXlib chainedDescriptor;
|
||||||
|
chainedDescriptor.display = XOpenDisplay(nullptr);
|
||||||
|
// From the "X Window System Protocol" "X Version 11, Release 6.8" page 2 at
|
||||||
|
// https://www.x.org/releases/X11R7.5/doc/x11proto/proto.pdf
|
||||||
|
// WINDOW 32-bit value (top three bits guaranteed to be zero.
|
||||||
|
// So UINT32_MAX should be an invalid window.
|
||||||
|
chainedDescriptor.window = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
// Test using Xlib when it is not supported
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, XlibSurfacesAreInvalid) {
|
||||||
|
wgpu::SurfaceDescriptorFromXlib chainedDescriptor;
|
||||||
|
chainedDescriptor.display = nullptr;
|
||||||
|
chainedDescriptor.window = 0;
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
// Tests that GLFWUtils returns a descriptor of Metal type
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, CorrectSTypeMetal) {
|
||||||
|
GLFWwindow* window = CreateWindow();
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
|
||||||
|
utils::SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
ASSERT_EQ(chainedDescriptor->sType, wgpu::SType::SurfaceDescriptorFromMetalLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with setting an invalid layer
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, InvalidMetalLayer) {
|
||||||
|
wgpu::SurfaceDescriptorFromMetalLayer chainedDescriptor;
|
||||||
|
// The CALayer is autoreleased. Releasing it causes a test failure when the Chromium GTest
|
||||||
|
// autoreleasepool is emptied.
|
||||||
|
chainedDescriptor.layer = utils::CreateDummyCALayer();
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
// Test using Metal when it is not supported
|
||||||
|
TEST_F(WindowSurfaceInstanceTests, MetalSurfacesAreInvalid) {
|
||||||
|
wgpu::SurfaceDescriptorFromMetalLayer chainedDescriptor;
|
||||||
|
chainedDescriptor.layer = nullptr;
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
AssertSurfaceCreation(&descriptor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
|
@ -44,17 +44,6 @@ namespace utils {
|
||||||
: mWindow(window), mDevice(device) {
|
: mWindow(window), mDevice(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupGLFWWindowHintsForBackend(wgpu::BackendType type) {
|
|
||||||
if (type == wgpu::BackendType::OpenGL) {
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
} else {
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscoverAdapter(dawn_native::Instance* instance,
|
void DiscoverAdapter(dawn_native::Instance* instance,
|
||||||
GLFWwindow* window,
|
GLFWwindow* window,
|
||||||
wgpu::BackendType type) {
|
wgpu::BackendType type) {
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace utils {
|
||||||
WGPUDevice mDevice = nullptr;
|
WGPUDevice mDevice = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetupGLFWWindowHintsForBackend(wgpu::BackendType type);
|
|
||||||
void DiscoverAdapter(dawn_native::Instance* instance,
|
void DiscoverAdapter(dawn_native::Instance* instance,
|
||||||
GLFWwindow* window,
|
GLFWwindow* window,
|
||||||
wgpu::BackendType type);
|
wgpu::BackendType type);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "utils/GLFWUtils.h"
|
||||||
|
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
#include "common/Platform.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
# define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#elif defined(DAWN_USE_X11)
|
||||||
|
# define GLFW_EXPOSE_NATIVE_X11
|
||||||
|
#endif
|
||||||
|
#include "GLFW/glfw3native.h"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
void SetupGLFWWindowHintsForBackend(wgpu::BackendType type) {
|
||||||
|
if (type == wgpu::BackendType::OpenGL) {
|
||||||
|
// Ask for OpenGL 4.4 which is what the GL backend requires for compute shaders and
|
||||||
|
// texture views.
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
} else {
|
||||||
|
// Without this GLFW will initialize a GL context on the window, which prevents using
|
||||||
|
// the window with other APIs (by crashing in weird ways).
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wgpu::Surface CreateSurfaceForWindow(wgpu::Instance instance, GLFWwindow* window) {
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> chainedDescriptor =
|
||||||
|
SetupWindowAndGetSurfaceDescriptorForTesting(window);
|
||||||
|
|
||||||
|
wgpu::SurfaceDescriptor descriptor;
|
||||||
|
descriptor.nextInChain = chainedDescriptor.get();
|
||||||
|
wgpu::Surface surface = instance.CreateSurface(&descriptor);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> SetupWindowAndGetSurfaceDescriptorForTesting(
|
||||||
|
GLFWwindow* window) {
|
||||||
|
std::unique_ptr<wgpu::SurfaceDescriptorFromWindowsHWND> desc =
|
||||||
|
std::make_unique<wgpu::SurfaceDescriptorFromWindowsHWND>();
|
||||||
|
desc->hwnd = glfwGetWin32Window(window);
|
||||||
|
desc->hinstance = GetModuleHandle(nullptr);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
#elif defined(DAWN_USE_X11)
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> SetupWindowAndGetSurfaceDescriptorForTesting(
|
||||||
|
GLFWwindow* window) {
|
||||||
|
std::unique_ptr<wgpu::SurfaceDescriptorFromXlib> desc =
|
||||||
|
std::make_unique<wgpu::SurfaceDescriptorFromXlib>();
|
||||||
|
desc->display = glfwGetX11Display();
|
||||||
|
desc->window = glfwGetX11Window(window);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
#elif defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
// SetupWindowAndGetSurfaceDescriptorForTesting defined in GLFWUtils_metal.mm
|
||||||
|
#else
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> SetupWindowAndGetSurfaceDescriptorForTesting(GLFWwindow*) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace utils
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef UTILS_GLFWUTILS_H_
|
||||||
|
#define UTILS_GLFWUTILS_H_
|
||||||
|
|
||||||
|
#include "dawn/webgpu_cpp.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct GLFWwindow;
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
// Adds all the necessary glfwWindowHint calls for the next GLFWwindow created to be used with
|
||||||
|
// the specified backend.
|
||||||
|
void SetupGLFWWindowHintsForBackend(wgpu::BackendType type);
|
||||||
|
|
||||||
|
// Does the necessary setup on the GLFWwindow to allow creating a wgpu::Surface with it and
|
||||||
|
// calls `instance.CreateSurface` with the correct descriptor for this window.
|
||||||
|
// Returns a null wgpu::Surface on failure.
|
||||||
|
wgpu::Surface CreateSurfaceForWindow(wgpu::Instance instance, GLFWwindow* window);
|
||||||
|
|
||||||
|
// Use for testing only. Does everything that CreateSurfaceForWindow does except the call to
|
||||||
|
// CreateSurface so the descriptor can be modified for testing.
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> SetupWindowAndGetSurfaceDescriptorForTesting(
|
||||||
|
GLFWwindow* window);
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
#endif // UTILS_GLFWUTILS_H_
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#if !defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
# error "GLFWUtils_metal.mm requires the Metal backend to be enabled."
|
||||||
|
#endif // !defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
|
||||||
|
#include "utils/GLFWUtils.h"
|
||||||
|
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
#include "GLFW/glfw3native.h"
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
std::unique_ptr<wgpu::ChainedStruct> SetupWindowAndGetSurfaceDescriptorForTesting(
|
||||||
|
GLFWwindow* window) {
|
||||||
|
if (@available(macOS 10.11, *)) {
|
||||||
|
NSWindow* nsWindow = glfwGetCocoaWindow(window);
|
||||||
|
NSView* view = [nsWindow contentView];
|
||||||
|
|
||||||
|
// Create a CAMetalLayer that covers the whole window that will be passed to
|
||||||
|
// CreateSurface.
|
||||||
|
[view setWantsLayer:YES];
|
||||||
|
[view setLayer:[CAMetalLayer layer]];
|
||||||
|
|
||||||
|
// Use retina if the window was created with retina support.
|
||||||
|
[[view layer] setContentsScale:[nsWindow backingScaleFactor]];
|
||||||
|
|
||||||
|
std::unique_ptr<wgpu::SurfaceDescriptorFromMetalLayer> desc =
|
||||||
|
std::make_unique<wgpu::SurfaceDescriptorFromMetalLayer>();
|
||||||
|
desc->layer = [view layer];
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef UTILS_OBJCUTILS_H_
|
||||||
|
#define UTILS_OBJCUTILS_H_
|
||||||
|
|
||||||
|
// Contains helper function to manipulate ObjC objects. This helps having C++ files do a little bit
|
||||||
|
// of ObjectiveC calls, when they cannot be converted to ObjectiveC++ because they are used on
|
||||||
|
// multiple platforms.
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
// The returned CALayer is autoreleased.
|
||||||
|
void* CreateDummyCALayer();
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
#endif // UTILS_OBJCUTILS_H_
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2020 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "utils/ObjCUtils.h"
|
||||||
|
|
||||||
|
#include <QuartzCore/CALayer.h>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
void* CreateDummyCALayer() {
|
||||||
|
return [CALayer layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
Loading…
Reference in New Issue