GL: Request OpenGL ES 3.0 context on API 29+, with fallback to 2.0.
Despite GL 3.0 not being required on API 29+, it is experimentally determined to always be supported on our testing devices, on API 29+. That said, still fall back to OpenGL 2.0 if 3.0 is not supported, just in case. PiperOrigin-RevId: 590569772
This commit is contained in:
parent
2fa5430417
commit
a15dfd75be
@ -366,11 +366,23 @@ public final class GlUtil {
|
|||||||
return eglSurface;
|
return eglSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link EGL14#EGL_CONTEXT_CLIENT_VERSION} of the current context.
|
||||||
|
*
|
||||||
|
* <p>Returns {@code 0} if no {@link EGLContext} {@linkplain #createFocusedPlaceholderEglSurface
|
||||||
|
* is focused}.
|
||||||
|
*/
|
||||||
|
@RequiresApi(17)
|
||||||
|
public static long getContextMajorVersion() throws GlException {
|
||||||
|
return Api17.getContextMajorVersion();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a newly created sync object and inserts it into the GL command stream.
|
* Returns a newly created sync object and inserts it into the GL command stream.
|
||||||
*
|
*
|
||||||
* <p>Returns {@code 0} if the operation failed or the {@link EGLContext} version is less than
|
* <p>Returns {@code 0} if the operation failed, no {@link EGLContext} {@linkplain
|
||||||
* 3.0.
|
* #createFocusedPlaceholderEglSurface is focused}, or the focused {@link EGLContext} version is
|
||||||
|
* less than 3.0.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(17)
|
@RequiresApi(17)
|
||||||
public static long createGlSyncFence() throws GlException {
|
public static long createGlSyncFence() throws GlException {
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkArgument;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.common.util.Util.SDK_INT;
|
||||||
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_RECEIVE_END_OF_INPUT;
|
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_RECEIVE_END_OF_INPUT;
|
||||||
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_REGISTER_NEW_INPUT_STREAM;
|
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_REGISTER_NEW_INPUT_STREAM;
|
||||||
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_SIGNAL_ENDED;
|
import static androidx.media3.effect.DebugTraceUtil.EVENT_VFP_SIGNAL_ENDED;
|
||||||
@ -637,18 +638,20 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
ColorInfo.isTransferHdr(outputColorInfo)
|
ColorInfo.isTransferHdr(outputColorInfo)
|
||||||
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
|
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
|
||||||
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
|
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
|
||||||
int openGlVersion =
|
|
||||||
ColorInfo.isTransferHdr(inputColorInfo) || ColorInfo.isTransferHdr(outputColorInfo) ? 3 : 2;
|
|
||||||
EGLContext eglContext =
|
EGLContext eglContext =
|
||||||
glObjectsProvider.createEglContext(eglDisplay, openGlVersion, configAttributes);
|
createFocusedEglContextWithFallback(glObjectsProvider, eglDisplay, configAttributes);
|
||||||
glObjectsProvider.createFocusedPlaceholderEglSurface(eglContext, eglDisplay);
|
if ((ColorInfo.isTransferHdr(inputColorInfo) || ColorInfo.isTransferHdr(outputColorInfo))
|
||||||
|
&& GlUtil.getContextMajorVersion() != 3) {
|
||||||
|
throw new VideoFrameProcessingException(
|
||||||
|
"OpenGL ES 3.0 context support is required for HDR input or output.");
|
||||||
|
}
|
||||||
|
|
||||||
// Not renderFramesAutomatically means outputting to a display surface. HDR display surfaces
|
// Not renderFramesAutomatically means outputting to a display surface. HDR display surfaces
|
||||||
// require the BT2020 PQ GL extension.
|
// require the BT2020 PQ GL extension.
|
||||||
if (!renderFramesAutomatically && ColorInfo.isTransferHdr(outputColorInfo)) {
|
if (!renderFramesAutomatically && ColorInfo.isTransferHdr(outputColorInfo)) {
|
||||||
// Display hardware supports PQ only.
|
// Display hardware supports PQ only.
|
||||||
checkArgument(outputColorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084);
|
checkArgument(outputColorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084);
|
||||||
if (Util.SDK_INT < 33 || !GlUtil.isBt2020PqExtensionSupported()) {
|
if (SDK_INT < 33 || !GlUtil.isBt2020PqExtensionSupported()) {
|
||||||
GlUtil.destroyEglContext(eglDisplay, eglContext);
|
GlUtil.destroyEglContext(eglDisplay, eglContext);
|
||||||
// On API<33, the system cannot display PQ content correctly regardless of whether BT2020 PQ
|
// On API<33, the system cannot display PQ content correctly regardless of whether BT2020 PQ
|
||||||
// GL extension is supported.
|
// GL extension is supported.
|
||||||
@ -882,6 +885,43 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates an OpenGL ES 3.0 context if possible, and an OpenGL ES 2.0 context otherwise. */
|
||||||
|
private static EGLContext createFocusedEglContextWithFallback(
|
||||||
|
GlObjectsProvider glObjectsProvider, EGLDisplay eglDisplay, int[] configAttributes)
|
||||||
|
throws GlUtil.GlException {
|
||||||
|
if (SDK_INT < 29) {
|
||||||
|
return createFocusedEglContext(
|
||||||
|
glObjectsProvider, eglDisplay, /* openGlVersion= */ 2, configAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return createFocusedEglContext(
|
||||||
|
glObjectsProvider, eglDisplay, /* openGlVersion= */ 3, configAttributes);
|
||||||
|
} catch (GlUtil.GlException e) {
|
||||||
|
return createFocusedEglContext(
|
||||||
|
glObjectsProvider, eglDisplay, /* openGlVersion= */ 2, configAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link EGLContext} and focus it using a {@linkplain
|
||||||
|
* GlObjectsProvider#createFocusedPlaceholderEglSurface placeholder EGL Surface}.
|
||||||
|
*/
|
||||||
|
private static EGLContext createFocusedEglContext(
|
||||||
|
GlObjectsProvider glObjectsProvider,
|
||||||
|
EGLDisplay eglDisplay,
|
||||||
|
int openGlVersion,
|
||||||
|
int[] configAttributes)
|
||||||
|
throws GlUtil.GlException {
|
||||||
|
EGLContext eglContext =
|
||||||
|
glObjectsProvider.createEglContext(eglDisplay, openGlVersion, configAttributes);
|
||||||
|
// Some OpenGL ES 3.0 contexts returned from createEglContext may throw EGL_BAD_MATCH when being
|
||||||
|
// used to createFocusedPlaceHolderEglSurface, despite GL documentation suggesting the contexts,
|
||||||
|
// if successfully created, are valid. Check early whether the context is really valid.
|
||||||
|
glObjectsProvider.createFocusedPlaceholderEglSurface(eglContext, eglDisplay);
|
||||||
|
return eglContext;
|
||||||
|
}
|
||||||
|
|
||||||
private static final class InputStreamInfo {
|
private static final class InputStreamInfo {
|
||||||
public final @InputType int inputType;
|
public final @InputType int inputType;
|
||||||
public final List<Effect> effects;
|
public final List<Effect> effects;
|
||||||
|
@ -48,6 +48,7 @@ import androidx.test.core.app.ApplicationProvider;
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@ -268,13 +269,15 @@ public final class HdrEditingTest {
|
|||||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||||
assertFileHasColorTransfer(context, exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
assertFileHasColorTransfer(context, exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||||
} catch (ExportException exception) {
|
} catch (ExportException exception) {
|
||||||
if (exception.getCause() != null
|
if (exception.getCause() != null) {
|
||||||
&& (Objects.equals(
|
@Nullable String message = exception.getCause().getMessage();
|
||||||
exception.getCause().getMessage(),
|
if (message != null
|
||||||
"Decoding HDR is not supported on this device.")
|
&& (Objects.equals(message, "Decoding HDR is not supported on this device.")
|
||||||
|| Objects.equals(
|
|| message.contains(
|
||||||
exception.getCause().getMessage(), "Device lacks YUV extension support."))) {
|
"OpenGL ES 3.0 context support is required for HDR input or output.")
|
||||||
return;
|
|| Objects.equals(message, "Device lacks YUV extension support."))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
@ -330,13 +333,15 @@ public final class HdrEditingTest {
|
|||||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||||
assertFileHasColorTransfer(context, exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
assertFileHasColorTransfer(context, exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||||
} catch (ExportException exception) {
|
} catch (ExportException exception) {
|
||||||
if (exception.getCause() != null
|
if (exception.getCause() != null) {
|
||||||
&& (Objects.equals(
|
@Nullable String message = exception.getCause().getMessage();
|
||||||
exception.getCause().getMessage(),
|
if (message != null
|
||||||
"Decoding HDR is not supported on this device.")
|
&& (Objects.equals(message, "Decoding HDR is not supported on this device.")
|
||||||
|| Objects.equals(
|
|| message.contains(
|
||||||
exception.getCause().getMessage(), "Device lacks YUV extension support."))) {
|
"OpenGL ES 3.0 context support is required for HDR input or output.")
|
||||||
return;
|
|| Objects.equals(message, "Device lacks YUV extension support."))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user