From 3d39e85376f82f8673f017f627ffcadb8da4d1b9 Mon Sep 17 00:00:00 2001
From: Matthias Baesken <mbaesken@openjdk.org>
Date: Wed, 24 Jul 2024 08:58:43 +0000
Subject: [PATCH] 8320655: awt screencast robot spin and sync issues with
 native libpipewire api

Backport-of: c17b8cfafe5a2bbe29d38cfc6793c72b0430f6ca
---
 .../libawt_xawt/awt/screencast_pipewire.c     | 34 ++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
index f2c145ff345..bb6c3b445fb 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
@@ -43,7 +43,8 @@ int DEBUG_SCREENCAST_ENABLED = FALSE;
                                       (*env)->ExceptionDescribe(env); \
                                    }
 
-static volatile gboolean sessionClosed = TRUE;
+static gboolean hasPipewireFailed = FALSE;
+static gboolean sessionClosed = TRUE;
 static GString *activeSessionToken;
 
 struct ScreenSpace screenSpace = {0};
@@ -171,6 +172,7 @@ static gboolean initScreencast(const gchar *token,
     }
 
     gtk->g_string_printf(activeSessionToken, "%s", token);
+    hasPipewireFailed = FALSE;
     sessionClosed = FALSE;
     return TRUE;
 }
@@ -338,6 +340,8 @@ static void onStreamProcess(void *userdata) {
 
     DEBUG_SCREEN_PREFIX(screen, "data ready\n", NULL);
     fp_pw_stream_queue_buffer(data->stream, pwBuffer);
+
+    fp_pw_thread_loop_signal(pw.loop, FALSE);
 }
 
 static void onStreamStateChanged(
@@ -351,6 +355,12 @@ static void onStreamStateChanged(
                      old, fp_pw_stream_state_as_string(old),
                      state, fp_pw_stream_state_as_string(state),
                      error);
+    if (state == PW_STREAM_STATE_ERROR
+        || state == PW_STREAM_STATE_UNCONNECTED) {
+
+        hasPipewireFailed = TRUE;
+        fp_pw_thread_loop_signal(pw.loop, FALSE);
+    }
 }
 
 static const struct pw_stream_events streamEvents = {
@@ -473,6 +483,11 @@ static gboolean connectStream(int index) {
 
     while (!data->hasFormat) {
         fp_pw_thread_loop_wait(pw.loop);
+        fp_pw_thread_loop_accept(pw.loop);
+        if (hasPipewireFailed) {
+            fp_pw_thread_loop_unlock(pw.loop);
+            return FALSE;
+        }
     }
 
     DEBUG_SCREEN_PREFIX(data->screenProps,
@@ -480,8 +495,6 @@ static gboolean connectStream(int index) {
             data->rawFormat.size.width, data->rawFormat.size.height
     );
 
-    fp_pw_thread_loop_accept(pw.loop);
-
     return TRUE;
 }
 
@@ -539,7 +552,12 @@ static void onCoreError(
             "!!! pipewire error: id %u, seq: %d, res: %d (%s): %s\n",
             id, seq, res, strerror(res), message
     );
-    fp_pw_thread_loop_unlock(pw.loop);
+    if (id == PW_ID_CORE) {
+        fp_pw_thread_loop_lock(pw.loop);
+        hasPipewireFailed = TRUE;
+        fp_pw_thread_loop_signal(pw.loop, FALSE);
+        fp_pw_thread_loop_unlock(pw.loop);
+    }
 }
 
 static const struct pw_core_events coreEvents = {
@@ -904,7 +922,15 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
     }
 
     while (!isAllDataReady()) {
+        fp_pw_thread_loop_lock(pw.loop);
         fp_pw_thread_loop_wait(pw.loop);
+        if (hasPipewireFailed) {
+            fp_pw_thread_loop_unlock(pw.loop);
+            doCleanup();
+            releaseToken(env, jtoken, token);
+            return RESULT_ERROR;
+        }
+        fp_pw_thread_loop_unlock(pw.loop);
     }
 
     DEBUG_SCREENCAST("\nall data ready\n", NULL);
-- 
GitLab