From 3369729100845950af37cf7883e5c2b8f09b3bd1 Mon Sep 17 00:00:00 2001 From: Linus Nilsson Date: Wed, 17 May 2023 22:07:42 +0200 Subject: [PATCH] Add EglThread class wrapping EglConnection and handler. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EglThread can be shared by multiple clients each using their own EglBase instance, but sharing thread and EglConnection. go/meet-android-eglcontext-reduction Bug: b/225229697 Change-Id: I2d18b92bdef51362a9dbd9c0af56cb868e29869d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/305462 Reviewed-by: Magnus Jedvert Commit-Queue: Linus Nilsson Reviewed-by: Xavier Lepaul‎ Cr-Commit-Position: refs/heads/main@{#40121} --- sdk/android/BUILD.gn | 1 + sdk/android/api/org/webrtc/EglThread.java | 87 +++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 sdk/android/api/org/webrtc/EglThread.java diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 4c386444a0..8a3e20c4e9 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -212,6 +212,7 @@ if (is_android) { "api/org/webrtc/EglBase10.java", "api/org/webrtc/EglBase14.java", "api/org/webrtc/EglRenderer.java", + "api/org/webrtc/EglThread.java", "api/org/webrtc/GlRectDrawer.java", "api/org/webrtc/GlShader.java", "api/org/webrtc/GlTextureFrameBuffer.java", diff --git a/sdk/android/api/org/webrtc/EglThread.java b/sdk/android/api/org/webrtc/EglThread.java new file mode 100644 index 0000000000..09122108be --- /dev/null +++ b/sdk/android/api/org/webrtc/EglThread.java @@ -0,0 +1,87 @@ +/* + * Copyright 2022 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc; + +import android.os.Handler; +import android.os.HandlerThread; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import org.webrtc.EglBase.EglConnection; + +/** EGL graphics thread that allows multiple clients to share the same underlying EGLContext. */ +public class EglThread { + /** Callback for externally managed reference count. */ + public interface ReleaseMonitor { + /** + * Called by EglThread when a client releases its reference. Returns true when there are no more + * references and resources should be released. + */ + boolean onRelease(EglThread eglThread); + } + + public static EglThread create(@Nullable ReleaseMonitor releaseMonitor, + @Nullable final EglBase.Context sharedContext, final int[] configAttributes) { + final HandlerThread renderThread = new HandlerThread("EglThread"); + renderThread.start(); + Handler handler = new Handler(renderThread.getLooper()); + + // If sharedContext is null, then texture frames are disabled. This is typically for old + // devices that might not be fully spec compliant, so force EGL 1.0 since EGL 1.4 has + // caused trouble on some weird devices. + EglConnection eglConnection; + if (sharedContext == null) { + eglConnection = EglConnection.createEgl10(configAttributes); + } else { + eglConnection = EglConnection.create(sharedContext, configAttributes); + } + + return new EglThread( + releaseMonitor != null ? releaseMonitor : eglThread -> true, handler, eglConnection); + } + + private final ReleaseMonitor releaseMonitor; + private final Handler handler; + private final EglConnection eglConnection; + + @VisibleForTesting + EglThread(ReleaseMonitor releaseMonitor, Handler handler, EglConnection eglConnection) { + this.releaseMonitor = releaseMonitor; + this.handler = handler; + this.eglConnection = eglConnection; + } + + public void release() { + if (!releaseMonitor.onRelease(this)) { + // Thread is still in use, do not release yet. + return; + } + + handler.post(eglConnection::release); + handler.getLooper().quitSafely(); + } + + /** + * Creates an EglBase instance with the EglThread's EglConnection. This method can be called on + * any thread, but the returned EglBase instance should only be used on this EglThread's Handler. + */ + public EglBase createEglBaseWithSharedConnection() { + return EglBase.create(eglConnection); + } + + /** + * Returns the Handler to interact with Gl/EGL on. Callers need to make sure that their own + * EglBase is current on the handler before running any graphics operations since the EglThread + * can be shared by multiple clients. + */ + public Handler getHandler() { + return handler; + } +}