зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Support Wayland
Implement DisplayVkWayland and WindowSurfaceVkWayland. Get window size from native window and check egl config is just empty. Then add an EGL wayland test for testing rendering and buffers swapping. Bug: angleproject:6902 Change-Id: I8204a5cc99f26330b74caba241bebf14c5650c2d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3395898 Reviewed-by: mohan maiya <m.maiya@samsung.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Auto-Submit: Antonio Caggiano <antonio.caggiano@collabora.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
ea86cfd2e3
Коммит
510351f200
38
BUILD.gn
38
BUILD.gn
|
@ -153,6 +153,15 @@ config("internal_config") {
|
|||
if (!angle_use_x11) {
|
||||
defines += [ "EGL_NO_X11" ]
|
||||
}
|
||||
|
||||
# These two are needed here to correctly select OSWindow::New
|
||||
if (angle_use_x11) {
|
||||
defines += [ "ANGLE_USE_X11" ]
|
||||
}
|
||||
if (angle_use_wayland) {
|
||||
defines += [ "ANGLE_USE_WAYLAND" ]
|
||||
}
|
||||
|
||||
if (angle_vulkan_display_mode == "simple") {
|
||||
defines += [ "ANGLE_VULKAN_DISPLAY_MODE_SIMPLE" ]
|
||||
} else if (angle_vulkan_display_mode == "headless") {
|
||||
|
@ -513,6 +522,10 @@ angle_static_library("angle_gpu_info_util") {
|
|||
"Xext",
|
||||
]
|
||||
}
|
||||
|
||||
if (angle_use_wayland && angle_has_build) {
|
||||
public_deps += [ ":angle_wayland" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (use_libpci) {
|
||||
|
@ -824,6 +837,10 @@ config("libANGLE_config") {
|
|||
defines += [ "ANGLE_USE_X11" ]
|
||||
}
|
||||
|
||||
if (angle_use_wayland) {
|
||||
defines += [ "ANGLE_USE_WAYLAND" ]
|
||||
}
|
||||
|
||||
if (angle_enable_overlay) {
|
||||
defines += [ "ANGLE_ENABLE_OVERLAY=1" ]
|
||||
}
|
||||
|
@ -1018,6 +1035,27 @@ angle_source_set("angle_gl_enum_utils") {
|
|||
]
|
||||
}
|
||||
|
||||
if (angle_use_wayland) {
|
||||
config("angle_wayland_config") {
|
||||
libs = [
|
||||
"wayland-client",
|
||||
"wayland-egl",
|
||||
]
|
||||
include_dirs = [
|
||||
"$angle_wayland_dir/egl",
|
||||
"$angle_wayland_dir/src",
|
||||
|
||||
# In case we are building with chromium, we need to take into account the case
|
||||
# where wayland-egl-backend.h is not installed in the system include directories
|
||||
"//third_party/wayland/src/egl",
|
||||
]
|
||||
}
|
||||
|
||||
group("angle_wayland") {
|
||||
public_configs = [ ":angle_wayland_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined(angle_abseil_cpp_dir)) {
|
||||
angle_abseil_cpp_dir = "//third_party/abseil-cpp"
|
||||
}
|
||||
|
|
|
@ -210,6 +210,7 @@ IGNORED_INCLUDES = {
|
|||
b'libANGLE/renderer/vulkan/mac/DisplayVkMac.h',
|
||||
b'libANGLE/renderer/vulkan/win32/DisplayVkWin32.h',
|
||||
b'libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h',
|
||||
b'libANGLE/renderer/vulkan/wayland/DisplayVkWayland.h',
|
||||
b'loader_cmake_config.h',
|
||||
b'loader_linux.h',
|
||||
b'loader_windows.h',
|
||||
|
|
|
@ -280,6 +280,8 @@ EGLAttrib GetPlatformTypeFromEnvironment()
|
|||
return 0;
|
||||
#elif defined(ANGLE_USE_X11)
|
||||
return EGL_PLATFORM_X11_EXT;
|
||||
#elif defined(ANGLE_USE_WAYLAND)
|
||||
return EGL_PLATFORM_WAYLAND_EXT;
|
||||
#elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_SIMPLE)
|
||||
return EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE;
|
||||
#elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_HEADLESS)
|
||||
|
@ -432,6 +434,13 @@ rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType,
|
|||
break;
|
||||
}
|
||||
# endif
|
||||
# if defined(ANGLE_USE_WAYLAND)
|
||||
if (platformType == EGL_PLATFORM_WAYLAND_EXT && rx::IsVulkanWaylandDisplayAvailable())
|
||||
{
|
||||
impl = rx::CreateVulkanWaylandDisplay(state);
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
# if defined(ANGLE_USE_VULKAN_DISPLAY)
|
||||
if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE &&
|
||||
rx::IsVulkanSimpleDisplayAvailable())
|
||||
|
|
|
@ -197,6 +197,15 @@ if (angle_use_x11) {
|
|||
]
|
||||
}
|
||||
|
||||
if (angle_use_wayland) {
|
||||
_vulkan_backend_sources += [
|
||||
"linux/wayland/DisplayVkWayland.cpp",
|
||||
"linux/wayland/DisplayVkWayland.h",
|
||||
"linux/wayland/WindowSurfaceVkWayland.cpp",
|
||||
"linux/wayland/WindowSurfaceVkWayland.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
_vulkan_backend_sources += [
|
||||
"fuchsia/DisplayVkFuchsia.cpp",
|
||||
|
@ -292,6 +301,10 @@ angle_source_set("angle_vulkan_backend") {
|
|||
]
|
||||
public_configs = [ ":angle_vulkan_backend_config" ]
|
||||
|
||||
if (angle_use_wayland) {
|
||||
public_configs += [ "$angle_root:angle_wayland_config" ]
|
||||
}
|
||||
|
||||
data_deps = []
|
||||
|
||||
defines = []
|
||||
|
|
|
@ -24,6 +24,9 @@ DisplayImpl *CreateVulkanWin32Display(const egl::DisplayState &state);
|
|||
#endif // defined(ANGLE_PLATFORM_WINDOWS)
|
||||
|
||||
#if defined(ANGLE_PLATFORM_LINUX)
|
||||
bool IsVulkanWaylandDisplayAvailable();
|
||||
DisplayImpl *CreateVulkanWaylandDisplay(const egl::DisplayState &state);
|
||||
|
||||
bool IsVulkanXcbDisplayAvailable();
|
||||
DisplayImpl *CreateVulkanXcbDisplay(const egl::DisplayState &state);
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
//
|
||||
// DisplayVkLinux.h:
|
||||
// Defines the class interface for DisplayVkLinux, which is the base of DisplayVkSimple,
|
||||
// DisplayVkHeadless and DisplayVkXcb. This base class implements the common functionality of
|
||||
// handling Linux dma-bufs.
|
||||
// DisplayVkHeadless, DisplayVkXcb and DisplayVkWayland. This base class implements the
|
||||
// common functionality of handling Linux dma-bufs.
|
||||
//
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKLINUX_H_
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// Copyright 2021-2022 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.
|
||||
//
|
||||
// DisplayVkWayland.cpp:
|
||||
// Implements the class methods for DisplayVkWayland.
|
||||
//
|
||||
|
||||
#include "libANGLE/renderer/vulkan/linux/wayland/DisplayVkWayland.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include "common/system_utils.h"
|
||||
#include "libANGLE/Display.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h"
|
||||
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
DisplayVkWayland::DisplayVkWayland(const egl::DisplayState &state)
|
||||
: DisplayVkLinux(state), mWaylandDisplay(nullptr)
|
||||
{}
|
||||
|
||||
egl::Error DisplayVkWayland::initialize(egl::Display *display)
|
||||
{
|
||||
mWaylandDisplay = reinterpret_cast<wl_display *>(display->getNativeDisplayId());
|
||||
if (!mWaylandDisplay)
|
||||
{
|
||||
ERR() << "Failed to retrieve wayland display";
|
||||
return egl::EglNotInitialized();
|
||||
}
|
||||
|
||||
return DisplayVk::initialize(display);
|
||||
}
|
||||
|
||||
void DisplayVkWayland::terminate()
|
||||
{
|
||||
mWaylandDisplay = nullptr;
|
||||
DisplayVk::terminate();
|
||||
}
|
||||
|
||||
bool DisplayVkWayland::isValidNativeWindow(EGLNativeWindowType window) const
|
||||
{
|
||||
// Wayland display Errors are fatal.
|
||||
// If this function returns non-zero, the display is not valid anymore.
|
||||
int error = wl_display_get_error(mWaylandDisplay);
|
||||
if (error)
|
||||
{
|
||||
WARN() << "Wayland window is not valid: " << error << " " << strerror(error);
|
||||
}
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
SurfaceImpl *DisplayVkWayland::createWindowSurfaceVk(const egl::SurfaceState &state,
|
||||
EGLNativeWindowType window)
|
||||
{
|
||||
return new WindowSurfaceVkWayland(state, window, mWaylandDisplay);
|
||||
}
|
||||
|
||||
egl::ConfigSet DisplayVkWayland::generateConfigs()
|
||||
{
|
||||
const std::array<GLenum, 1> kColorFormats = {GL_BGRA8_EXT};
|
||||
|
||||
std::vector<GLenum> depthStencilFormats(
|
||||
egl_vk::kConfigDepthStencilFormats,
|
||||
egl_vk::kConfigDepthStencilFormats + ArraySize(egl_vk::kConfigDepthStencilFormats));
|
||||
|
||||
if (getCaps().stencil8)
|
||||
{
|
||||
depthStencilFormats.push_back(GL_STENCIL_INDEX8);
|
||||
}
|
||||
return egl_vk::GenerateConfigs(kColorFormats.data(), kColorFormats.size(),
|
||||
depthStencilFormats.data(), depthStencilFormats.size(), this);
|
||||
}
|
||||
|
||||
void DisplayVkWayland::checkConfigSupport(egl::Config *config)
|
||||
{
|
||||
// In wayland there is no native visual ID or type
|
||||
}
|
||||
|
||||
const char *DisplayVkWayland::getWSIExtension() const
|
||||
{
|
||||
return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
|
||||
}
|
||||
|
||||
bool IsVulkanWaylandDisplayAvailable()
|
||||
{
|
||||
wl_display *display = wl_display_connect(nullptr);
|
||||
if (!display)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
wl_display_disconnect(display);
|
||||
return true;
|
||||
}
|
||||
|
||||
DisplayImpl *CreateVulkanWaylandDisplay(const egl::DisplayState &state)
|
||||
{
|
||||
return new DisplayVkWayland(state);
|
||||
}
|
||||
} // namespace rx
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Copyright 2021-2022 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.
|
||||
//
|
||||
// DisplayVkWayland.h:
|
||||
// Defines the class interface for DisplayVkWayland, implementing DisplayVk for Wayland.
|
||||
//
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_VULKAN_WAYLAND_DISPLAYVKWAYLAND_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_WAYLAND_DISPLAYVKWAYLAND_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h"
|
||||
|
||||
struct wl_display;
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class DisplayVkWayland : public DisplayVkLinux
|
||||
{
|
||||
public:
|
||||
DisplayVkWayland(const egl::DisplayState &state);
|
||||
|
||||
egl::Error initialize(egl::Display *display) override;
|
||||
void terminate() override;
|
||||
|
||||
bool isValidNativeWindow(EGLNativeWindowType window) const override;
|
||||
|
||||
SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
|
||||
EGLNativeWindowType window) override;
|
||||
|
||||
egl::ConfigSet generateConfigs() override;
|
||||
void checkConfigSupport(egl::Config *config) override;
|
||||
|
||||
const char *getWSIExtension() const override;
|
||||
|
||||
private:
|
||||
wl_display *mWaylandDisplay;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_VULKAN_WAYLAND_DISPLAYVKWAYLAND_H_
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// Copyright 2021-2022 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.
|
||||
//
|
||||
// WindowSurfaceVkWayland.cpp:
|
||||
// Implements the class methods for WindowSurfaceVkWayland.
|
||||
//
|
||||
|
||||
#include "libANGLE/renderer/vulkan/linux/wayland/WindowSurfaceVkWayland.h"
|
||||
|
||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||
|
||||
#include <wayland-egl-backend.h>
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
void WindowSurfaceVkWayland::ResizeCallback(wl_egl_window *eglWindow, void *payload)
|
||||
{
|
||||
WindowSurfaceVkWayland *windowSurface = reinterpret_cast<WindowSurfaceVkWayland *>(payload);
|
||||
|
||||
windowSurface->mExtents.width = eglWindow->width;
|
||||
windowSurface->mExtents.height = eglWindow->height;
|
||||
}
|
||||
|
||||
WindowSurfaceVkWayland::WindowSurfaceVkWayland(const egl::SurfaceState &surfaceState,
|
||||
EGLNativeWindowType window,
|
||||
wl_display *display)
|
||||
: WindowSurfaceVk(surfaceState, window), mWaylandDisplay(display)
|
||||
{
|
||||
wl_egl_window *eglWindow = reinterpret_cast<wl_egl_window *>(window);
|
||||
eglWindow->resize_callback = WindowSurfaceVkWayland::ResizeCallback;
|
||||
eglWindow->driver_private = this;
|
||||
|
||||
mExtents = gl::Extents(eglWindow->width, eglWindow->height, 1);
|
||||
}
|
||||
|
||||
angle::Result WindowSurfaceVkWayland::createSurfaceVk(vk::Context *context, gl::Extents *extentsOut)
|
||||
{
|
||||
ANGLE_VK_CHECK(context,
|
||||
vkGetPhysicalDeviceWaylandPresentationSupportKHR(
|
||||
context->getRenderer()->getPhysicalDevice(), 0, mWaylandDisplay),
|
||||
VK_ERROR_INITIALIZATION_FAILED);
|
||||
|
||||
wl_egl_window *eglWindow = reinterpret_cast<wl_egl_window *>(mNativeWindowType);
|
||||
|
||||
VkWaylandSurfaceCreateInfoKHR createInfo = {};
|
||||
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.flags = 0;
|
||||
createInfo.display = mWaylandDisplay;
|
||||
createInfo.surface = eglWindow->surface;
|
||||
ANGLE_VK_TRY(context, vkCreateWaylandSurfaceKHR(context->getRenderer()->getInstance(),
|
||||
&createInfo, nullptr, &mSurface));
|
||||
|
||||
return getCurrentWindowSize(context, extentsOut);
|
||||
}
|
||||
|
||||
angle::Result WindowSurfaceVkWayland::getCurrentWindowSize(vk::Context *context,
|
||||
gl::Extents *extentsOut)
|
||||
{
|
||||
*extentsOut = mExtents;
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
} // namespace rx
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Copyright 2021-2022 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.
|
||||
//
|
||||
// WindowSurfaceVkWayland.h:
|
||||
// Defines the class interface for WindowSurfaceVkWayland, implementing WindowSurfaceVk.
|
||||
//
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_VULKAN_WAYLAND_WINDOWSURFACEVKWAYLAND_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_WAYLAND_WINDOWSURFACEVKWAYLAND_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
|
||||
|
||||
struct wl_display;
|
||||
struct wl_egl_window;
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class WindowSurfaceVkWayland : public WindowSurfaceVk
|
||||
{
|
||||
public:
|
||||
static void ResizeCallback(wl_egl_window *window, void *payload);
|
||||
|
||||
WindowSurfaceVkWayland(const egl::SurfaceState &surfaceState,
|
||||
EGLNativeWindowType window,
|
||||
wl_display *display);
|
||||
|
||||
private:
|
||||
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
|
||||
angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
|
||||
|
||||
wl_display *mWaylandDisplay;
|
||||
gl::Extents mExtents;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_VULKAN_WAYLAND_WINDOWSURFACEVKWAYLAND_H_
|
|
@ -147,6 +147,12 @@ const char *DisplayVkXcb::getWSIExtension() const
|
|||
|
||||
bool IsVulkanXcbDisplayAvailable()
|
||||
{
|
||||
Display *display = XOpenDisplay(nullptr);
|
||||
if (!display)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
XCloseDisplay(display);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -243,6 +243,9 @@ if (is_win || is_linux || is_chromeos || is_android || is_fuchsia || is_apple) {
|
|||
if (angle_use_x11) {
|
||||
sources += [ "egl_tests/EGLX11VisualTest.cpp" ]
|
||||
}
|
||||
if (angle_use_wayland) {
|
||||
sources += [ "egl_tests/EGLWaylandTest.cpp" ]
|
||||
}
|
||||
|
||||
configs += [ "${angle_root}:libANGLE_config" ]
|
||||
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
//
|
||||
// Copyright 2022 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.
|
||||
//
|
||||
|
||||
// EGLWaylandTest.cpp: tests for EGL_EXT_platform_wayland
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-egl-backend.h>
|
||||
|
||||
#include "test_utils/ANGLETest.h"
|
||||
#include "util/linux/wayland/WaylandWindow.h"
|
||||
|
||||
using namespace angle;
|
||||
|
||||
namespace
|
||||
{
|
||||
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
}
|
||||
|
||||
class EGLWaylandTest : public ANGLETest
|
||||
{
|
||||
public:
|
||||
std::vector<EGLint> getDisplayAttributes() const
|
||||
{
|
||||
std::vector<EGLint> attribs;
|
||||
|
||||
attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
|
||||
attribs.push_back(GetParam().getRenderer());
|
||||
attribs.push_back(EGL_NONE);
|
||||
|
||||
return attribs;
|
||||
}
|
||||
|
||||
void testSetUp() override
|
||||
{
|
||||
mOsWindow = WaylandWindow::New();
|
||||
ASSERT_TRUE(mOsWindow->initialize("EGLWaylandTest", 500, 500));
|
||||
setWindowVisible(mOsWindow, true);
|
||||
|
||||
EGLNativeDisplayType waylandDisplay = mOsWindow->getNativeDisplay();
|
||||
std::vector<EGLint> attribs = getDisplayAttributes();
|
||||
mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, (void *)waylandDisplay,
|
||||
attribs.data());
|
||||
ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
|
||||
|
||||
ASSERT_TRUE(EGL_TRUE == eglInitialize(mDisplay, nullptr, nullptr));
|
||||
|
||||
int nConfigs = 0;
|
||||
ASSERT_TRUE(EGL_TRUE == eglGetConfigs(mDisplay, nullptr, 0, &nConfigs));
|
||||
ASSERT_GE(nConfigs, 1);
|
||||
|
||||
int nReturnedConfigs = 0;
|
||||
mConfigs.resize(nConfigs);
|
||||
ASSERT_TRUE(EGL_TRUE ==
|
||||
eglGetConfigs(mDisplay, mConfigs.data(), nConfigs, &nReturnedConfigs));
|
||||
ASSERT_EQ(nConfigs, nReturnedConfigs);
|
||||
}
|
||||
|
||||
void testTearDown() override
|
||||
{
|
||||
mConfigs.clear();
|
||||
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglTerminate(mDisplay);
|
||||
OSWindow::Delete(&mOsWindow);
|
||||
}
|
||||
|
||||
OSWindow *mOsWindow;
|
||||
EGLDisplay mDisplay;
|
||||
std::vector<EGLConfig> mConfigs;
|
||||
};
|
||||
|
||||
// Test that a Wayland window can be created and used for rendering
|
||||
TEST_P(EGLWaylandTest, WaylandWindowRendering)
|
||||
{
|
||||
for (EGLConfig config : mConfigs)
|
||||
{
|
||||
// Finally, try to do a clear on the window.
|
||||
EGLContext context = eglCreateContext(mDisplay, config, EGL_NO_CONTEXT, contextAttribs);
|
||||
ASSERT_NE(EGL_NO_CONTEXT, context);
|
||||
|
||||
EGLSurface window =
|
||||
eglCreateWindowSurface(mDisplay, config, mOsWindow->getNativeWindow(), nullptr);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglMakeCurrent(mDisplay, window, window, context);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
glViewport(0, 0, 500, 500);
|
||||
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);
|
||||
|
||||
// Teardown
|
||||
eglDestroySurface(mDisplay, window);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglDestroyContext(mDisplay, context);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a Wayland window can swap buffers multiple times with no issues
|
||||
TEST_P(EGLWaylandTest, SwapBuffers)
|
||||
{
|
||||
for (EGLConfig config : mConfigs)
|
||||
{
|
||||
EGLContext context = eglCreateContext(mDisplay, config, EGL_NO_CONTEXT, contextAttribs);
|
||||
ASSERT_NE(EGL_NO_CONTEXT, context);
|
||||
|
||||
EGLSurface surface =
|
||||
eglCreateWindowSurface(mDisplay, config, mOsWindow->getNativeWindow(), nullptr);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglMakeCurrent(mDisplay, surface, surface, context);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
const uint32_t loopcount = 16;
|
||||
for (uint32_t i = 0; i < loopcount; i++)
|
||||
{
|
||||
mOsWindow->messageLoop();
|
||||
|
||||
glViewport(0, 0, 500, 500);
|
||||
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ASSERT_GL_NO_ERROR() << "glClear failed";
|
||||
EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255);
|
||||
|
||||
eglSwapBuffers(mDisplay, surface);
|
||||
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
|
||||
}
|
||||
|
||||
// Teardown
|
||||
eglDestroySurface(mDisplay, surface);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglDestroyContext(mDisplay, context);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
}
|
||||
}
|
||||
|
||||
ANGLE_INSTANTIATE_TEST(EGLWaylandTest, WithNoFixture(ES2_VULKAN()));
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "test_utils/ANGLETest.h"
|
||||
#include "util/OSWindow.h"
|
||||
#include "util/x11/X11Window.h"
|
||||
#include "util/linux/x11/X11Window.h"
|
||||
|
||||
using namespace angle;
|
||||
|
||||
|
|
|
@ -51,13 +51,24 @@ if (is_linux) {
|
|||
|
||||
if (angle_use_x11) {
|
||||
_util_sources += [
|
||||
"x11/X11Pixmap.cpp",
|
||||
"x11/X11Pixmap.h",
|
||||
"x11/X11Window.cpp",
|
||||
"x11/X11Window.h",
|
||||
"linux/x11/X11Pixmap.cpp",
|
||||
"linux/x11/X11Pixmap.h",
|
||||
"linux/x11/X11Window.cpp",
|
||||
"linux/x11/X11Window.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (angle_use_wayland) {
|
||||
_util_sources += [
|
||||
"linux/wayland/WaylandWindow.cpp",
|
||||
"linux/wayland/WaylandWindow.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (angle_use_x11 || angle_use_wayland) {
|
||||
_util_sources += [ "linux/LinuxWindow.cpp" ]
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
_util_sources += [
|
||||
"fuchsia/FuchsiaPixmap.cpp",
|
||||
|
@ -309,7 +320,12 @@ config("angle_test_util_config") {
|
|||
|
||||
angle_source_set("angle_test_utils") {
|
||||
public_configs = [ ":angle_test_util_config" ]
|
||||
|
||||
public_deps = [ "$angle_root:angle_common" ]
|
||||
if (angle_use_wayland) {
|
||||
public_deps += [ "$angle_root:angle_wayland" ]
|
||||
}
|
||||
|
||||
deps = []
|
||||
sources = [
|
||||
"Timer.cpp",
|
||||
|
|
|
@ -79,7 +79,7 @@ void DisplayWindow::signalTestEvent()
|
|||
}
|
||||
|
||||
// static
|
||||
#if defined(ANGLE_USE_VULKAN_DISPLAY) && defined(EGL_NO_X11)
|
||||
#if defined(ANGLE_USE_VULKAN_DISPLAY) && defined(EGL_NO_X11) && !defined(ANGLE_USE_WAYLAND)
|
||||
OSWindow *OSWindow::New()
|
||||
{
|
||||
return new DisplayWindow();
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Copyright 2022 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.
|
||||
//
|
||||
|
||||
// LinuxWindow.cpp: Implementation of OSWindow::New for Linux
|
||||
|
||||
#include "util/OSWindow.h"
|
||||
|
||||
#if defined(ANGLE_USE_WAYLAND)
|
||||
# include "wayland/WaylandWindow.h"
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_USE_X11)
|
||||
# include "x11/X11Window.h"
|
||||
#endif
|
||||
|
||||
// static
|
||||
#if defined(ANGLE_USE_X11) || defined(ANGLE_USE_WAYLAND)
|
||||
OSWindow *OSWindow::New()
|
||||
{
|
||||
# if defined(ANGLE_USE_X11)
|
||||
// Prefer X11
|
||||
if (IsX11WindowAvailable())
|
||||
{
|
||||
return new X11Window();
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(ANGLE_USE_WAYLAND)
|
||||
if (IsWaylandWindowAvailable())
|
||||
{
|
||||
return new WaylandWindow();
|
||||
}
|
||||
# endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,173 @@
|
|||
//
|
||||
// Copyright 2022 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.
|
||||
//
|
||||
|
||||
// WaylandWindow.cpp: Implementation of OSWindow for Wayland
|
||||
|
||||
#include "util/linux/wayland/WaylandWindow.h"
|
||||
|
||||
WaylandWindow::WaylandWindow()
|
||||
: mDisplay{nullptr}, mCompositor{nullptr}, mSurface{nullptr}, mWindow{nullptr}
|
||||
{}
|
||||
|
||||
WaylandWindow::~WaylandWindow()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void WaylandWindow::RegistryHandleGlobal(void *data,
|
||||
struct wl_registry *registry,
|
||||
uint32_t name,
|
||||
const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
WaylandWindow *vc = reinterpret_cast<WaylandWindow *>(data);
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0)
|
||||
{
|
||||
void *compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
|
||||
vc->mCompositor = reinterpret_cast<wl_compositor *>(compositor);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandWindow::RegistryHandleGlobalRemove(void *data,
|
||||
struct wl_registry *registry,
|
||||
uint32_t name)
|
||||
{}
|
||||
|
||||
const struct wl_registry_listener WaylandWindow::registryListener = {
|
||||
WaylandWindow::RegistryHandleGlobal, WaylandWindow::RegistryHandleGlobalRemove};
|
||||
|
||||
bool WaylandWindow::initializeImpl(const std::string &name, int width, int height)
|
||||
{
|
||||
destroy();
|
||||
|
||||
if (!mDisplay)
|
||||
{
|
||||
mDisplay = wl_display_connect(nullptr);
|
||||
if (!mDisplay)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Not get a window
|
||||
struct wl_registry *registry = wl_display_get_registry(mDisplay);
|
||||
wl_registry_add_listener(registry, ®istryListener, this);
|
||||
|
||||
// Round-trip to get globals
|
||||
wl_display_roundtrip(mDisplay);
|
||||
if (!mCompositor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't need this anymore
|
||||
wl_registry_destroy(registry);
|
||||
|
||||
mSurface = wl_compositor_create_surface(mCompositor);
|
||||
if (!mSurface)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mWindow = wl_egl_window_create(mSurface, width, height);
|
||||
if (!mWindow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fds[0] = {wl_display_get_fd(mDisplay), POLLIN, 0};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaylandWindow::disableErrorMessageDialog() {}
|
||||
|
||||
void WaylandWindow::destroy()
|
||||
{
|
||||
if (mWindow)
|
||||
{
|
||||
wl_egl_window_destroy(mWindow);
|
||||
mWindow = nullptr;
|
||||
}
|
||||
|
||||
if (mSurface)
|
||||
{
|
||||
wl_surface_destroy(mSurface);
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
if (mCompositor)
|
||||
{
|
||||
wl_compositor_destroy(mCompositor);
|
||||
mCompositor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandWindow::resetNativeWindow() {}
|
||||
|
||||
EGLNativeWindowType WaylandWindow::getNativeWindow() const
|
||||
{
|
||||
return reinterpret_cast<EGLNativeWindowType>(mWindow);
|
||||
}
|
||||
|
||||
EGLNativeDisplayType WaylandWindow::getNativeDisplay() const
|
||||
{
|
||||
return reinterpret_cast<EGLNativeDisplayType>(mDisplay);
|
||||
}
|
||||
|
||||
void WaylandWindow::messageLoop()
|
||||
{
|
||||
while (wl_display_prepare_read(mDisplay) != 0)
|
||||
wl_display_dispatch_pending(mDisplay);
|
||||
if (wl_display_flush(mDisplay) < 0 && errno != EAGAIN)
|
||||
{
|
||||
wl_display_cancel_read(mDisplay);
|
||||
return;
|
||||
}
|
||||
if (poll(fds, 1, 0) > 0)
|
||||
{
|
||||
wl_display_read_events(mDisplay);
|
||||
wl_display_dispatch_pending(mDisplay);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_display_cancel_read(mDisplay);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandWindow::setMousePosition(int x, int y) {}
|
||||
|
||||
bool WaylandWindow::setOrientation(int width, int height)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaylandWindow::setPosition(int x, int y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaylandWindow::resize(int width, int height)
|
||||
{
|
||||
wl_egl_window_resize(mWindow, width, height, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaylandWindow::setVisible(bool isVisible) {}
|
||||
|
||||
void WaylandWindow::signalTestEvent() {}
|
||||
|
||||
bool IsWaylandWindowAvailable()
|
||||
{
|
||||
wl_display *display = wl_display_connect(nullptr);
|
||||
if (!display)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
wl_display_disconnect(display);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Copyright 2022 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.
|
||||
//
|
||||
|
||||
// WaylandWindow.h: Definition of the implementation of OSWindow for Wayland
|
||||
|
||||
#ifndef UTIL_WAYLAND_WINDOW_H
|
||||
#define UTIL_WAYLAND_WINDOW_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-egl-core.h>
|
||||
|
||||
#include "util/OSWindow.h"
|
||||
#include "util/util_export.h"
|
||||
|
||||
bool IsWaylandWindowAvailable();
|
||||
|
||||
class ANGLE_UTIL_EXPORT WaylandWindow : public OSWindow
|
||||
{
|
||||
public:
|
||||
WaylandWindow();
|
||||
~WaylandWindow() override;
|
||||
|
||||
void disableErrorMessageDialog() override;
|
||||
void destroy() override;
|
||||
|
||||
void resetNativeWindow() override;
|
||||
EGLNativeWindowType getNativeWindow() const override;
|
||||
EGLNativeDisplayType getNativeDisplay() const override;
|
||||
|
||||
void messageLoop() override;
|
||||
|
||||
void setMousePosition(int x, int y) override;
|
||||
bool setOrientation(int width, int height) override;
|
||||
bool setPosition(int x, int y) override;
|
||||
bool resize(int width, int height) override;
|
||||
void setVisible(bool isVisible) override;
|
||||
|
||||
void signalTestEvent() override;
|
||||
|
||||
private:
|
||||
static void RegistryHandleGlobal(void *data,
|
||||
struct wl_registry *registry,
|
||||
uint32_t name,
|
||||
const char *interface,
|
||||
uint32_t version);
|
||||
static void RegistryHandleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name);
|
||||
|
||||
bool initializeImpl(const std::string &name, int width, int height) override;
|
||||
|
||||
static const struct wl_registry_listener registryListener;
|
||||
|
||||
struct wl_display *mDisplay;
|
||||
struct wl_compositor *mCompositor;
|
||||
struct wl_surface *mSurface;
|
||||
struct wl_egl_window *mWindow;
|
||||
|
||||
struct pollfd fds[1];
|
||||
};
|
||||
|
||||
#endif // UTIL_WAYLAND_WINDOW_H
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// X11Pixmap.cpp: Implementation of OSPixmap for X11
|
||||
|
||||
#include "util/x11/X11Pixmap.h"
|
||||
#include "util/linux/x11/X11Pixmap.h"
|
||||
|
||||
X11Pixmap::X11Pixmap() : mPixmap(0), mDisplay(nullptr) {}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// X11Window.cpp: Implementation of OSWindow for X11
|
||||
|
||||
#include "util/x11/X11Window.h"
|
||||
#include "util/linux/x11/X11Window.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "util/Timer.h"
|
||||
|
@ -722,8 +722,13 @@ void X11Window::processEvent(const XEvent &xEvent)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
OSWindow *OSWindow::New()
|
||||
bool IsX11WindowAvailable()
|
||||
{
|
||||
return new X11Window();
|
||||
Display *display = XOpenDisplay(nullptr);
|
||||
if (!display)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
XCloseDisplay(display);
|
||||
return true;
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
#include "util/OSWindow.h"
|
||||
#include "util/util_export.h"
|
||||
|
||||
bool IsX11WindowAvailable();
|
||||
|
||||
class ANGLE_UTIL_EXPORT X11Window : public OSWindow
|
||||
{
|
||||
public:
|
Загрузка…
Ссылка в новой задаче