webrtc_m130/sdk/android/api/org/webrtc/EglThread.java
Linus Nilsson 4e5b89f77b Create the EGLContext on the thread it will be used on.
Not doing so seems to have caused issues with creating window surfaces
on that context later on.

Bug: b/225229697
Change-Id: Id202c93c4e51d1661e79a4b37751d11fcd64c119
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/311462
Reviewed-by: Xavier Lepaul‎ <xalep@webrtc.org>
Commit-Queue: Linus Nilsson <lnilsson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40411}
2023-07-10 10:11:12 +00:00

92 lines
3.4 KiB
Java

/*
* 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());
// Not creating the EGLContext on the thread it will be used on seems to cause issues with
// creating window surfaces on certain devices. So keep the same legacy behavior as EglRenderer
// and create the context on the render thread.
EglConnection eglConnection = ThreadUtils.invokeAtFrontUninterruptibly(handler, () -> {
// 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.
if (sharedContext == null) {
return EglConnection.createEgl10(configAttributes);
} else {
return 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;
}
}