Skip to content
Snippets Groups Projects
Commit 07be2e55 authored by Matthias Baesken's avatar Matthias Baesken
Browse files

8313697: [XWayland][Screencast] consequent getPixelColor calls are slow

8310334: [XWayland][Screencast] screen capture error message in debug

Backport-of: 2f04bc5f934887029d8bcc13cf722d8498a35120
parent 2464d8c1
No related branches found
No related tags found
No related merge requests found
......@@ -35,6 +35,8 @@ import java.security.AccessController;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.IntStream;
/**
......@@ -54,6 +56,13 @@ public class ScreencastHelper {
private static final int DENIED = -11;
private static final int OUT_OF_BOUNDS = -12;
private static final int DELAY_BEFORE_SESSION_CLOSE = 2000;
private static volatile TimerTask timerTask = null;
private static final Timer timerCloseSession
= new Timer("auto-close screencast session", true);
private ScreencastHelper() {
}
......@@ -105,11 +114,30 @@ public class ScreencastHelper {
).toList();
}
private static synchronized native void closeSession();
private static void timerCloseSessionRestart() {
if (timerTask != null) {
timerTask.cancel();
}
timerTask = new TimerTask() {
@Override
public void run() {
closeSession();
}
};
timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE);
}
public static synchronized void getRGBPixels(
int x, int y, int width, int height, int[] pixelArray
) {
if (!IS_NATIVE_LOADED) return;
timerCloseSessionRestart();
Rectangle captureArea = new Rectangle(x, y, width, height);
List<Rectangle> affectedScreenBounds = getSystemScreensBounds()
......
......@@ -324,6 +324,10 @@ final class TokenStorage {
return tokenItem;
})
.filter(Objects::nonNull)
.sorted((t1, t2) -> //Token with more screens preferred
t2.allowedScreensBounds.size()
- t1.allowedScreensBounds.size()
)
.toList();
}
......
......@@ -602,6 +602,7 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
fp_g_string_new = dl_symbol("g_string_new");
fp_g_string_erase = dl_symbol("g_string_erase");
fp_g_string_set_size = dl_symbol("g_string_set_size");
fp_g_string_free = dl_symbol("g_string_free");
glib_version_2_68 = !fp_glib_check_version(2, 68, 0);
......@@ -3091,6 +3092,7 @@ static void gtk3_init(GtkApi* gtk) {
gtk->g_string_new = fp_g_string_new;
gtk->g_string_erase = fp_g_string_erase;
gtk->g_string_set_size = fp_g_string_set_size;
gtk->g_string_free = fp_g_string_free;
gtk->g_string_replace = fp_g_string_replace;
gtk->g_string_printf = fp_g_string_printf;
......
......@@ -758,6 +758,9 @@ static GString *(*fp_g_string_erase)(GString *string,
gssize pos,
gssize len);
static GString *(*fp_g_string_set_size)(GString* string,
gsize len);
static gchar *(*fp_g_string_free)(GString *string,
gboolean free_segment);
......
......@@ -716,6 +716,10 @@ typedef struct GtkApi {
gssize pos,
gssize len);
GString *(*g_string_set_size)(GString* string,
gsize len);
gchar *(*g_string_free)(GString *string,
gboolean free_segment);
......
......@@ -43,6 +43,9 @@ int DEBUG_SCREENCAST_ENABLED = FALSE;
(*env)->ExceptionDescribe(env); \
}
static volatile gboolean sessionClosed = TRUE;
static GString *activeSessionToken;
struct ScreenSpace screenSpace = {0};
static struct PwLoopData pw = {0};
......@@ -89,8 +92,8 @@ static void doCleanup() {
struct ScreenProps *screenProps = &screenSpace.screens[i];
if (screenProps->data) {
if (screenProps->data->stream) {
fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_disconnect(screenProps->data->stream);
fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_destroy(screenProps->data->stream);
fp_pw_thread_loop_unlock(pw.loop);
screenProps->data->stream = NULL;
......@@ -123,7 +126,11 @@ static void doCleanup() {
if (screenSpace.screens) {
free(screenSpace.screens);
screenSpace.screens = NULL;
screenSpace.screenCount = 0;
}
gtk->g_string_set_size(activeSessionToken, 0);
sessionClosed = TRUE;
}
/**
......@@ -132,6 +139,24 @@ static void doCleanup() {
static gboolean initScreencast(const gchar *token,
GdkRectangle *affectedBounds,
gint affectedBoundsLength) {
gboolean isSameToken = !token
? FALSE
: strcmp(token, activeSessionToken->str) == 0;
if (!sessionClosed) {
if (isSameToken) {
DEBUG_SCREENCAST("Reusing active session.\n", NULL);
return TRUE;
} else {
DEBUG_SCREENCAST(
"Active session has a different token |%s| -> |%s|,"
" closing current session.\n",
activeSessionToken->str, token
);
doCleanup();
}
}
fp_pw_init(NULL, NULL);
pw.pwFd = RESULT_ERROR;
......@@ -145,6 +170,8 @@ static gboolean initScreencast(const gchar *token,
return FALSE;
}
gtk->g_string_printf(activeSessionToken, "%s", token);
sessionClosed = FALSE;
return TRUE;
}
......@@ -386,8 +413,19 @@ static gboolean connectStream(int index) {
data->screenProps = &screenSpace.screens[index];
data->hasFormat = FALSE;
if (!sessionClosed && data->stream) {
fp_pw_thread_loop_lock(pw.loop);
int result = fp_pw_stream_set_active(data->stream, TRUE);
fp_pw_thread_loop_unlock(pw.loop);
DEBUG_SCREEN_PREFIX(data->screenProps,
"stream %p: activate result |%i|\n",
data->stream, result);
return result == 0; // 0 - success
};
data->hasFormat = FALSE;
data->stream = fp_pw_stream_new(
pw.core,
......@@ -505,6 +543,7 @@ static const struct pw_core_events coreEvents = {
* @return TRUE on success
*/
static gboolean doLoop(GdkRectangle requestedArea) {
if (!pw.loop && !sessionClosed) {
pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL);
if (!pw.loop) {
......@@ -546,8 +585,11 @@ static gboolean doLoop(GdkRectangle requestedArea) {
}
pw_core_add_listener(pw.core, &pw.coreListener, &coreEvents, NULL);
}
for (int i = 0; i < screenSpace.screenCount; ++i) {
struct ScreenProps *screen = &screenSpace.screens[i];
if (!screen->data && !sessionClosed) {
struct PwStreamData *data =
(struct PwStreamData*) malloc(sizeof (struct PwStreamData));
if (!data) {
......@@ -557,8 +599,8 @@ static gboolean doLoop(GdkRectangle requestedArea) {
memset(data, 0, sizeof (struct PwStreamData));
struct ScreenProps *screen = &screenSpace.screens[i];
screen->data = data;
}
DEBUG_SCREEN_PREFIX(screen, "@@@ adding screen %i\n", i);
if (checkScreen(i, requestedArea)) {
......@@ -746,6 +788,8 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire
return JNI_FALSE;
}
activeSessionToken = gtk->g_string_new("");
gboolean usable = initXdgDesktopPortal();
portalScreenCastCleanup();
return usable;
......@@ -783,6 +827,17 @@ static void arrayToRectangles(JNIEnv *env,
(*env)->ReleaseIntArrayElements(env, boundsArray, body, 0);
}
/*
* Class: sun_awt_screencast_ScreencastHelper
* Method: closeSession
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_screencast_ScreencastHelper_closeSession(JNIEnv *env, jclass cls) {
DEBUG_SCREENCAST("closing screencast session\n\n", NULL);
doCleanup();
}
/*
* Class: sun_awt_screencast_ScreencastHelper
* Method: getRGBPixelsImpl
......@@ -805,7 +860,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
boundsLen = (*env)->GetArrayLength(env, affectedScreensBoundsArray);
EXCEPTION_CHECK_DESCRIBE();
if (boundsLen % 4 != 0) {
DEBUG_SCREENCAST("%s:%i incorrect array length\n", __FUNCTION__, __LINE__);
DEBUG_SCREENCAST("incorrect array length\n", NULL);
return RESULT_ERROR;
}
affectedBoundsLength = boundsLen / 4;
......@@ -896,11 +951,12 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_set_active(screenProps->data->stream, FALSE);
fp_pw_stream_disconnect(screenProps->data->stream);
fp_pw_thread_loop_unlock(pw.loop);
screenProps->captureDataReady = FALSE;
}
}
doCleanup();
releaseToken(env, jtoken, token);
return 0;
}
......@@ -777,6 +777,10 @@ int portalScreenCastOpenPipewireRemote() {
}
void portalScreenCastCleanup() {
if (!portal) {
return;
}
if (portal->screenCastSessionHandle) {
gtk->g_dbus_connection_call_sync(
portal->connection,
......@@ -796,9 +800,6 @@ void portalScreenCastCleanup() {
portal->screenCastSessionHandle = NULL;
}
if (!portal) {
return;
}
if (portal->connection) {
gtk->g_object_unref(portal->connection);
portal->connection = NULL;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment