Skip to content

Commit 40b4b4f

Browse files
committed
GPU Wayland Display: Add error handling / reporting
1 parent d8b6561 commit 40b4b4f

3 files changed

Lines changed: 51 additions & 12 deletions

File tree

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontend.cxx‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ GPUDisplayFrontend* createGPUDisplayFrontendWayland();
4040

4141
#include "GPULogging.h"
4242
#include <cstring>
43+
#include <exception>
4344
#include <algorithm>
4445
#include <iterator>
4546
#include <thread>
@@ -62,8 +63,14 @@ GPUDisplayFrontend::~GPUDisplayFrontend() = default;
6263
void* GPUDisplayFrontend::FrontendThreadWrapper(void* ptr)
6364
{
6465
GPUDisplayFrontend* me = reinterpret_cast<GPUDisplayFrontend*>(ptr);
65-
int32_t retVal = me->FrontendMain();
66-
if (retVal == -1) {
66+
int32_t retVal;
67+
try {
68+
retVal = me->FrontendMain();
69+
} catch (const std::exception& e) {
70+
GPUError("Error in display frontend: %s", e.what());
71+
retVal = -1;
72+
}
73+
if (retVal && me->mDisplay->mInitResult == 0) { // Failed before InitDisplay was called, report failure to StartDisplay(), which otherwise waits forever
6774
me->InitDisplay(true);
6875
}
6976
return ((void*)(size_t)retVal);

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontendWayland.cxx‎

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <cstdlib>
2424
#include <cstring>
2525
#include <stdexcept>
26+
#include <cerrno>
2627
#include <chrono>
2728
#include <algorithm>
2829

@@ -369,7 +370,10 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
369370
mRegistryListener = wl_registry_listener{.global = registry_global, .global_remove = registry_global_remove};
370371

371372
wl_registry_add_listener(mRegistry, &mRegistryListener, this);
372-
wl_display_roundtrip(mWayland);
373+
if (wl_display_roundtrip(mWayland) == -1) {
374+
reportError("initial roundtrip");
375+
throw std::runtime_error("Wayland initialization failed");
376+
}
373377

374378
if (mCompositor == nullptr || mXdgBase == nullptr || mSeat == nullptr) {
375379
throw std::runtime_error("Error getting wayland objects");
@@ -502,7 +506,8 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
502506
xdg_toplevel_add_listener(mXdgToplevel, &mXdgToplevelListener, this);
503507

504508
xdg_toplevel_set_title(mXdgToplevel, DISPLAY_WINDOW_NAME);
505-
applyInitialWindowState(); // Must be requested before the first commit
509+
xdg_toplevel_set_app_id(mXdgToplevel, "o2-gpu-event-display"); // Used by the compositor for window grouping, window rules, and matching a .desktop file
510+
applyInitialWindowState(); // Must be requested before the first commit
506511

507512
if (mDecManager) { // Must be requested before the first commit. Without the protocol (e.g. GNOME), the window has no decorations
508513
mXdgDecoration = zxdg_decoration_manager_v1_get_toplevel_decoration(mDecManager, mXdgToplevel);
@@ -512,7 +517,10 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
512517
}
513518

514519
wl_surface_commit(mSurface); // Initial commit without buffer, the compositor answers with the first configure
515-
wl_display_roundtrip(mWayland);
520+
if (wl_display_roundtrip(mWayland) == -1) {
521+
reportError("initial roundtrip");
522+
throw std::runtime_error("Wayland initialization failed");
523+
}
516524

517525
if (InitDisplay()) {
518526
return (1);
@@ -523,19 +531,29 @@ int32_t GPUDisplayFrontendWayland::FrontendMain()
523531
pthread_mutex_unlock(&mSemLockExit);
524532

525533
while (mDisplayControl != 2) {
526-
while (wl_display_prepare_read(mWayland) != 0) {
527-
wl_display_dispatch_pending(mWayland);
534+
bool error = false;
535+
while (!error && wl_display_prepare_read(mWayland) != 0) {
536+
error = wl_display_dispatch_pending(mWayland) == -1;
537+
}
538+
if (error) {
539+
reportError("dispatching events");
540+
break;
528541
}
529542
wl_display_flush(mWayland);
530543
pollfd pfd = {wl_display_get_fd(mWayland), POLLIN, 0};
531544
if (poll(&pfd, 1, 0) > 0) {
532545
if (wl_display_read_events(mWayland) == -1) {
546+
reportError("reading events");
533547
break;
534548
}
535549
} else {
536550
wl_display_cancel_read(mWayland);
537551
}
538-
if (wl_display_dispatch_pending(mWayland) == -1 || mDisplayControl == 2) {
552+
if (wl_display_dispatch_pending(mWayland) == -1) {
553+
reportError("dispatching events");
554+
break;
555+
}
556+
if (mDisplayControl == 2) {
539557
break;
540558
}
541559
HandleSendKeys();
@@ -671,6 +689,19 @@ void GPUDisplayFrontendWayland::updateSize()
671689
}
672690
}
673691

692+
void GPUDisplayFrontendWayland::reportError(const char* where)
693+
{
694+
const int32_t err = wl_display_get_error(mWayland);
695+
if (err == EPROTO) {
696+
const wl_interface* iface = nullptr;
697+
uint32_t id = 0;
698+
const uint32_t code = wl_display_get_protocol_error(mWayland, &iface, &id);
699+
GPUError("Wayland protocol error %u on %s@%u while %s", code, iface ? iface->name : "unknown interface", id, where);
700+
} else {
701+
GPUError("Wayland error while %s: %s", where, strerror(err));
702+
}
703+
}
704+
674705
void GPUDisplayFrontendWayland::handleKeyRepeat()
675706
{
676707
if (mRepeatKeyCode < 0) {

‎GPU/GPUTracking/display/frontend/GPUDisplayFrontendWayland.h‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ class GPUDisplayFrontendWayland : public GPUDisplayFrontend
4949
private:
5050
int32_t FrontendMain() override;
5151
int32_t GetKey(uint32_t key, uint32_t state);
52-
void updateScale(); // Buffer scale from wl_surface.preferred_buffer_scale, or max scale of the outputs the surface is on (older compositors)
53-
void updateSize(); // Physical size = logical size * scale, resizes the scene if changed
54-
void handleKeyRepeat(); // Call HandleKey for the held key according to wl_keyboard.repeat_info
55-
void applyScroll(); // Apply scroll events of one wl_pointer.frame: high-resolution wheel (120 = 1 notch = 100 mMouseWheel units) if available, otherwise continuous axis (touchpad, ~15 units per notch)
52+
void updateScale(); // Buffer scale from wl_surface.preferred_buffer_scale, or max scale of the outputs the surface is on (older compositors)
53+
void updateSize(); // Physical size = logical size * scale, resizes the scene if changed
54+
void reportError(const char* where); // Print the Wayland display error (protocol error with interface and object, or errno) after a call returned -1
55+
void handleKeyRepeat(); // Call HandleKey for the held key according to wl_keyboard.repeat_info
56+
void applyScroll(); // Apply scroll events of one wl_pointer.frame: high-resolution wheel (120 = 1 notch = 100 mMouseWheel units) if available, otherwise continuous axis (touchpad, ~15 units per notch)
5657

5758
struct OutputInfo {
5859
wl_output* output;

0 commit comments

Comments
 (0)