You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
Bitmap: use thread local GdkDisplay to fix glitches on X11
GdkDisplay is not thread safe on X11. We can't even use the default display from main thread, because a GTK render thread may run concurrently.
This commit is contained in:
@@ -19,14 +19,20 @@ JNIEXPORT jlong JNICALL Java_android_graphics_Bitmap_native_1create_1snapshot(JN
|
|||||||
JNIEXPORT jlong JNICALL Java_android_graphics_Bitmap_native_1create_1texture(JNIEnv *env, jclass class, jlong snapshot_ptr, jint width, jint height, jint stride, jint format)
|
JNIEXPORT jlong JNICALL Java_android_graphics_Bitmap_native_1create_1texture(JNIEnv *env, jclass class, jlong snapshot_ptr, jint width, jint height, jint stride, jint format)
|
||||||
{
|
{
|
||||||
static GType renderer_type = 0;
|
static GType renderer_type = 0;
|
||||||
|
/* GdkDisplay is not thread safe on X11. We can't even use the default
|
||||||
|
* display from main thread, because a GTK render thread may run concurrently.*/
|
||||||
|
static GPrivate off_screen_display_thread_local = G_PRIVATE_INIT(g_object_unref);
|
||||||
GtkSnapshot *snapshot = _PTR(snapshot_ptr);
|
GtkSnapshot *snapshot = _PTR(snapshot_ptr);
|
||||||
GskRenderNode *node = snapshot ? gtk_snapshot_free_to_node(snapshot) : NULL;
|
GskRenderNode *node = snapshot ? gtk_snapshot_free_to_node(snapshot) : NULL;
|
||||||
GdkTexture *texture = NULL;
|
GdkTexture *texture = NULL;
|
||||||
if (node) {
|
if (node) {
|
||||||
graphene_rect_t bounds = GRAPHENE_RECT_INIT(0, 0, width, height);
|
graphene_rect_t bounds = GRAPHENE_RECT_INIT(0, 0, width, height);
|
||||||
|
GdkDisplay *off_screen_display = g_private_get(&off_screen_display_thread_local);
|
||||||
|
if (!off_screen_display)
|
||||||
|
g_private_set(&off_screen_display_thread_local, off_screen_display = gdk_display_open(NULL));
|
||||||
if (!renderer_type) {
|
if (!renderer_type) {
|
||||||
// Use same renderer type as for onscreen rendering.
|
// Create and destroy a dummy surface to get the renderer type
|
||||||
GdkSurface *surface = gdk_surface_new_toplevel(gdk_display_get_default());
|
GdkSurface *surface = gdk_surface_new_toplevel(off_screen_display);
|
||||||
GskRenderer *renderer = gsk_renderer_new_for_surface(surface);
|
GskRenderer *renderer = gsk_renderer_new_for_surface(surface);
|
||||||
renderer_type = G_OBJECT_TYPE(renderer);
|
renderer_type = G_OBJECT_TYPE(renderer);
|
||||||
gsk_renderer_unrealize(renderer);
|
gsk_renderer_unrealize(renderer);
|
||||||
@@ -34,7 +40,7 @@ JNIEXPORT jlong JNICALL Java_android_graphics_Bitmap_native_1create_1texture(JNI
|
|||||||
gdk_surface_destroy(surface);
|
gdk_surface_destroy(surface);
|
||||||
}
|
}
|
||||||
GskRenderer *renderer = g_object_new(renderer_type, NULL);
|
GskRenderer *renderer = g_object_new(renderer_type, NULL);
|
||||||
gsk_renderer_realize(renderer, NULL, NULL);
|
gsk_renderer_realize_for_display(renderer, off_screen_display, NULL);
|
||||||
texture = gsk_renderer_render_texture(renderer, node, &bounds);
|
texture = gsk_renderer_render_texture(renderer, node, &bounds);
|
||||||
gsk_render_node_unref(node);
|
gsk_render_node_unref(node);
|
||||||
gsk_renderer_unrealize(renderer);
|
gsk_renderer_unrealize(renderer);
|
||||||
|
|||||||
Reference in New Issue
Block a user