Skip to content

Commit 282c217

Browse files
committed
X11 and Wayland display helpers
1 parent 0f3a5e2 commit 282c217

File tree

13 files changed

+739
-3
lines changed

13 files changed

+739
-3
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ jobs:
206206
libcairo2 \
207207
libsecret-1-dev \
208208
libtool \
209+
libx11-dev \
210+
libxfixes-dev \
211+
libxrandr-dev \
209212
nasm \
210213
ninja-build \
211214
qtbase5-dev

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@ if(APPLE)
132132
find_package(LibArchive REQUIRED)
133133
elseif(UNIX)
134134
find_package(LIBSECRET)
135-
find_package(Uuid REQUIRED)
136135
find_package(Fontconfig REQUIRED)
136+
find_package(Uuid REQUIRED)
137+
find_package(Wayland COMPONENTS Client)
138+
find_package(X11 COMPONENTS Xrandr)
137139
elseif(WIN32)
138140
if(PLASMA_BUILD_MAX_PLUGIN STREQUAL "REQUIRED")
139141
set(_3dsm_FIND_ARG "REQUIRED")
@@ -183,6 +185,8 @@ cmake_dependent_option(USE_SPEEX "Use Speex audio for voice chat" ON "TARGET Spe
183185
cmake_dependent_option(USE_VPX "Use VPX for movie support" ON "TARGET VPX::VPX" OFF)
184186
cmake_dependent_option(USE_WEBM "Use WebM movie player" ON "TARGET Opus::opus AND TARGET libwebm::libwebm AND USE_VPX" OFF)
185187
cmake_dependent_option(USE_VLD "Build and link with Visual Leak Detector" OFF "TARGET VLD::VLD" OFF)
188+
cmake_dependent_option(USE_WAYLAND "Build with Wayland compositor support" ON "TARGET Wayland::Client" OFF)
189+
cmake_dependent_option(USE_X11 "Build with X11 support" ON "TARGET X11::X11" OFF)
186190

187191
# Configure compile-time compiler-specific flags and other config files
188192
include(cmake/CompilerChecks.cmake)

Sources/Plasma/PubUtilLib/plPipeline/pl3DPipeline.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ static const float kAvTexPoolShrinkThresh = 30.f; // seconds
110110
class plDisplayHelper
111111
{
112112
public:
113+
virtual ~plDisplayHelper() {}
114+
113115
virtual plDisplayMode DesktopDisplayMode() = 0;
114116
virtual std::vector<plDisplayMode> GetSupportedDisplayModes(hsDisplayHndl display, int ColorDepth = 32) const = 0;
115117
virtual hsDisplayHndl DefaultDisplay() const = 0;

Sources/Tools/hsG3DDeviceDumper/CMakeLists.txt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
set(hsG3DDeviceDumper_SOURCES
22
plAllCreatables.cpp
33
main.cpp
4+
5+
$<$<BOOL:${USE_WAYLAND}>:plWaylandDisplayHelper.cpp>
6+
$<$<BOOL:${USE_X11}>:plX11DisplayHelper.cpp>
7+
)
8+
9+
set(hsG3DDeviceDumper_HEADERS
10+
$<$<BOOL:${USE_WAYLAND}>:plWaylandDisplayHelper.h>
11+
$<$<BOOL:${USE_WAYLAND}>:plWaylandFunctions.h>
12+
13+
$<$<BOOL:${USE_X11}>:plX11DisplayHelper.h>
14+
$<$<BOOL:${USE_X11}>:plX11Functions.h>
415
)
516

617
plasma_executable(hsG3DDeviceDumper TOOL
718
FOLDER Tools
819
SOURCES
9-
${hsG3DDeviceDumper_SOURCES}
20+
${hsG3DDeviceDumper_HEADERS} ${hsG3DDeviceDumper_SOURCES}
1021

1122
# Hack hack hack
1223
$<$<PLATFORM_ID:Darwin>:../../Plasma/Apps/plClient/Mac-Cocoa/plMacDisplayHelper.mm>
24+
$<$<PLATFORM_ID:Windows>:../../Plasma/Apps/plClient/win32/plWinDisplayHelper.cpp>
25+
)
26+
27+
target_include_directories(
28+
hsG3DDeviceDumper
29+
PRIVATE
30+
$<$<AND:$<BOOL:${USE_WAYLAND}>,$<TARGET_EXISTS:Wayland::Client>>:$<TARGET_PROPERTY:Wayland::Client,INCLUDE_DIRECTORIES>>
31+
$<$<AND:$<BOOL:${USE_X11}>,$<TARGET_EXISTS:X11::X11>>:$<TARGET_PROPERTY:X11::X11,INCLUDE_DIRECTORIES>>
32+
$<$<AND:$<BOOL:${USE_X11}>,$<TARGET_EXISTS:X11::Xrandr>>:$<TARGET_PROPERTY:X11::Xrandr,INCLUDE_DIRECTORIES>>
1333
)
1434

1535
target_link_libraries(
@@ -29,3 +49,4 @@ target_link_libraries(
2949
)
3050

3151
source_group("Source Files" FILES ${hsG3DDeviceDumper_SOURCES})
52+
source_group("Header Files" FILES ${hsG3DDeviceDumper_HEADERS})

Sources/Tools/hsG3DDeviceDumper/main.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
4040
4141
*==LICENSE==*/
4242

43+
#include <cstdlib>
4344
#include <string_theory/stdio>
4445

4546
#include "HeadSpin.h"
@@ -50,6 +51,16 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
5051
#ifdef HS_BUILD_FOR_MACOS
5152
# include "../../Plasma/Apps/plClient/Mac-Cocoa/plMacDisplayHelper.h"
5253
#endif
54+
#ifdef HS_BUILD_FOR_WIN32
55+
# include "../../Plasma/Apps/plClient/win32/plWinDisplayHelper.h"
56+
#endif
57+
58+
#ifdef USE_X11
59+
# include "plX11DisplayHelper.h"
60+
#endif
61+
#ifdef USE_WAYLAND
62+
# include "plWaylandDisplayHelper.h"
63+
#endif
5364

5465
#ifdef PLASMA_PIPELINE_GL
5566
# include "pfGLPipeline/plGLPipeline.h"
@@ -65,8 +76,33 @@ int main(int argc, const char* argv[]) {
6576
hsG3DDeviceSelector devSel;
6677
plDisplayHelper* helper = nullptr;
6778

79+
#ifdef USE_WAYLAND
80+
# ifdef USE_X11
81+
// In a perfect world, this would always be set to tell us if we're running
82+
// X11 or Wayland, but the world is far from perfect so we'll try this and
83+
// then guess based on other variables.
84+
// We only need to do the runtime detection if both are available,
85+
// otherwise you get what you get
86+
const char* sessionType = getenv("XDG_SESSION_TYPE");
87+
if (strcmp(sessionType, "wayland") == 0 || !sessionType && getenv("WAYLAND_DISPLAY"))
88+
// Fallthrough
89+
# endif
90+
helper = new plWaylandDisplayHelper();
91+
#endif
92+
93+
#ifdef USE_X11
94+
if (!helper && getenv("DISPLAY"))
95+
helper = new plX11DisplayHelper();
96+
#endif
97+
6898
#ifdef HS_BUILD_FOR_MACOS
69-
helper = new plMacDisplayHelper();
99+
if (!helper)
100+
helper = new plMacDisplayHelper();
101+
#endif
102+
103+
#ifdef HS_BUILD_FOR_WIN32
104+
if (!helper)
105+
helper = new plWinDisplayHelper();
70106
#endif
71107

72108
plDisplayHelper::SetInstance(helper);
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*==LICENSE==*
2+
3+
CyanWorlds.com Engine - MMOG client, server and tools
4+
Copyright (C) 2011 Cyan Worlds, Inc.
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
Additional permissions under GNU GPL version 3 section 7
20+
21+
If you modify this Program, or any covered work, by linking or
22+
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
23+
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
24+
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
25+
(or a modified version of those libraries),
26+
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
27+
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
28+
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
29+
licensors of this Program grant you additional
30+
permission to convey the resulting work. Corresponding Source for a
31+
non-source form of such a combination shall include the source code for
32+
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
33+
work.
34+
35+
You can contact Cyan Worlds, Inc. by email legal@cyan.com
36+
or by snail mail at:
37+
Cyan Worlds, Inc.
38+
14617 N Newport Hwy
39+
Mead, WA 99021
40+
41+
*==LICENSE==*/
42+
43+
#include "plWaylandDisplayHelper.h"
44+
45+
#include <cstring>
46+
#include "plWaylandFunctions.h"
47+
48+
template <typename... Args> void ignore(Args...) {}
49+
50+
void plWaylandDisplayHelper::output_handle_mode(void* data, wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
51+
{
52+
plWaylandDisplayHelper* self = reinterpret_cast<plWaylandDisplayHelper*>(data);
53+
54+
if (flags & WL_OUTPUT_MODE_CURRENT) {
55+
self->fDisplayModes.emplace_back(plDisplayMode {
56+
width,
57+
height,
58+
32
59+
});
60+
}
61+
}
62+
63+
void plWaylandDisplayHelper::global_handler(void* data, wl_registry* registry, uint32_t id, const char* interface, uint32_t version)
64+
{
65+
plWaylandDisplayHelper* self = reinterpret_cast<plWaylandDisplayHelper*>(data);
66+
67+
if (strcmp(interface, (*__wl_output_interface).name) == 0) {
68+
static const wl_output_listener output_listener = {
69+
&ignore,
70+
&plWaylandDisplayHelper::output_handle_mode,
71+
&ignore,
72+
&ignore,
73+
&ignore,
74+
&ignore
75+
};
76+
77+
self->fCurrentOutput = reinterpret_cast<wl_output*>(wl_registry_bind(registry, id, &__wl_output_interface, std::min<uint32_t>((*__wl_output_interface).version, version)));
78+
wl_output_add_listener(self->fCurrentOutput, &output_listener, data);
79+
}
80+
}
81+
82+
plWaylandDisplayHelper::plWaylandDisplayHelper() : fCurrentDisplay(), fCurrentRegistry(), fCurrentOutput()
83+
{
84+
}
85+
86+
plWaylandDisplayHelper::~plWaylandDisplayHelper()
87+
{
88+
if (fCurrentRegistry)
89+
wl_registry_destroy(fCurrentRegistry);
90+
91+
if (fCurrentDisplay)
92+
__wl_display_disconnect(fCurrentDisplay);
93+
}
94+
95+
void plWaylandDisplayHelper::SetCurrentScreen(wl_display* display) const
96+
{
97+
if (fCurrentDisplay == display)
98+
return;
99+
else if (fCurrentDisplay) {
100+
if (fCurrentRegistry)
101+
wl_registry_destroy(fCurrentRegistry);
102+
103+
__wl_display_disconnect(fCurrentDisplay);
104+
}
105+
106+
fCurrentDisplay = display;
107+
if (!fCurrentDisplay)
108+
return;
109+
110+
fCurrentRegistry = wl_display_get_registry(fCurrentDisplay);
111+
if (!fCurrentRegistry)
112+
return;
113+
114+
fDisplayModes.clear();
115+
116+
static const wl_registry_listener registry_listener = {
117+
&plWaylandDisplayHelper::global_handler,
118+
&ignore
119+
};
120+
121+
wl_registry_add_listener(fCurrentRegistry, &registry_listener, const_cast<plWaylandDisplayHelper*>(this));
122+
123+
__wl_display_roundtrip(fCurrentDisplay);
124+
__wl_display_roundtrip(fCurrentDisplay);
125+
126+
if (fCurrentOutput) {
127+
wl_output_destroy(fCurrentOutput);
128+
fCurrentOutput = nullptr;
129+
}
130+
131+
std::sort(fDisplayModes.begin(), fDisplayModes.end(), std::greater());
132+
auto last = std::unique(fDisplayModes.begin(), fDisplayModes.end());
133+
fDisplayModes.erase(last, fDisplayModes.end());
134+
}
135+
136+
std::vector<plDisplayMode> plWaylandDisplayHelper::GetSupportedDisplayModes(hsDisplayHndl display, int ColorDepth) const
137+
{
138+
// Cache the current display so we can answer repeat requests quickly.
139+
// SetCurrentScreen will catch redundant sets.
140+
SetCurrentScreen(reinterpret_cast<wl_display*>(display));
141+
return fDisplayModes;
142+
}
143+
144+
hsDisplayHndl plWaylandDisplayHelper::DefaultDisplay() const
145+
{
146+
if (!fCurrentDisplay) {
147+
wl_display* display = *__wl_display_connect(nullptr);
148+
SetCurrentScreen(display);
149+
}
150+
151+
return reinterpret_cast<hsDisplayHndl>(fCurrentDisplay);
152+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*==LICENSE==*
2+
3+
CyanWorlds.com Engine - MMOG client, server and tools
4+
Copyright (C) 2011 Cyan Worlds, Inc.
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
Additional permissions under GNU GPL version 3 section 7
20+
21+
If you modify this Program, or any covered work, by linking or
22+
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
23+
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
24+
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
25+
(or a modified version of those libraries),
26+
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
27+
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
28+
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
29+
licensors of this Program grant you additional
30+
permission to convey the resulting work. Corresponding Source for a
31+
non-source form of such a combination shall include the source code for
32+
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
33+
work.
34+
35+
You can contact Cyan Worlds, Inc. by email legal@cyan.com
36+
or by snail mail at:
37+
Cyan Worlds, Inc.
38+
14617 N Newport Hwy
39+
Mead, WA 99021
40+
41+
*==LICENSE==*/
42+
43+
#ifndef plWaylandDisplayHelper_h
44+
#define plWaylandDisplayHelper_h
45+
46+
#include "plPipeline/hsG3DDeviceSelector.h"
47+
#include "plPipeline/pl3DPipeline.h"
48+
49+
struct wl_display;
50+
struct wl_output;
51+
struct wl_registry;
52+
53+
class plWaylandDisplayHelper : public plDisplayHelper
54+
{
55+
public:
56+
plWaylandDisplayHelper();
57+
~plWaylandDisplayHelper() override;
58+
59+
plDisplayMode DesktopDisplayMode() override { return fDesktopDisplayMode; };
60+
std::vector<plDisplayMode> GetSupportedDisplayModes(hsDisplayHndl display, int ColorDepth = 32) const override;
61+
hsDisplayHndl DefaultDisplay() const override;
62+
63+
private:
64+
mutable wl_display* fCurrentDisplay;
65+
mutable wl_registry* fCurrentRegistry;
66+
mutable wl_output* fCurrentOutput;
67+
mutable plDisplayMode fDesktopDisplayMode;
68+
mutable std::vector<plDisplayMode> fDisplayModes;
69+
70+
void SetCurrentScreen(wl_display* screen) const;
71+
72+
static void global_handler(void* data, wl_registry* registry, uint32_t id, const char* interface, uint32_t version);
73+
static void output_handle_mode(void* data, wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh);
74+
};
75+
76+
#endif /* plWaylandDisplayHelper_h */

0 commit comments

Comments
 (0)