Android: Add support for OpenGL ES 3
Bug: webrtc:10642 Change-Id: I736e9e2520b364a817228a6599f4008d58165622 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137424 Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27990}
This commit is contained in:

committed by
Commit Bot

parent
b9979a533c
commit
94079f8452
@ -13,6 +13,7 @@ package org.webrtc;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.Surface;
|
||||
import java.util.ArrayList;
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
|
||||
/**
|
||||
@ -44,51 +45,105 @@ public interface EglBase {
|
||||
// This is similar to how GlSurfaceView does:
|
||||
// http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/opengl/GLSurfaceView.java#760
|
||||
public static final int EGL_OPENGL_ES2_BIT = 4;
|
||||
public static final int EGL_OPENGL_ES3_BIT = 0x40;
|
||||
// Android-specific extension.
|
||||
public static final int EGL_RECORDABLE_ANDROID = 0x3142;
|
||||
|
||||
// clang-format off
|
||||
public static final int[] CONFIG_PLAIN = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
public static final int[] CONFIG_RGBA = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_ALPHA_SIZE, 8,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
public static final int[] CONFIG_PIXEL_BUFFER = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
public static final int[] CONFIG_PIXEL_RGBA_BUFFER = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_ALPHA_SIZE, 8,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
public static final int[] CONFIG_RECORDABLE = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_RECORDABLE_ANDROID, 1,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
// clang-format on
|
||||
public static ConfigBuilder configBuilder() {
|
||||
return new ConfigBuilder();
|
||||
}
|
||||
|
||||
public static class ConfigBuilder {
|
||||
private int openGlesVersion = 2;
|
||||
private boolean hasAlphaChannel;
|
||||
private boolean supportsPixelBuffer;
|
||||
private boolean isRecordable;
|
||||
|
||||
public ConfigBuilder setOpenGlesVersion(int version) {
|
||||
if (version < 1 || version > 3) {
|
||||
throw new IllegalArgumentException("OpenGL ES version " + version + " not supported");
|
||||
}
|
||||
this.openGlesVersion = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigBuilder setHasAlphaChannel(boolean hasAlphaChannel) {
|
||||
this.hasAlphaChannel = hasAlphaChannel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigBuilder setSupportsPixelBuffer(boolean supportsPixelBuffer) {
|
||||
this.supportsPixelBuffer = supportsPixelBuffer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigBuilder setIsRecordable(boolean isRecordable) {
|
||||
this.isRecordable = isRecordable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int[] createConfigAttributes() {
|
||||
ArrayList<Integer> list = new ArrayList<>();
|
||||
list.add(EGL10.EGL_RED_SIZE);
|
||||
list.add(8);
|
||||
list.add(EGL10.EGL_GREEN_SIZE);
|
||||
list.add(8);
|
||||
list.add(EGL10.EGL_BLUE_SIZE);
|
||||
list.add(8);
|
||||
if (hasAlphaChannel) {
|
||||
list.add(EGL10.EGL_ALPHA_SIZE);
|
||||
list.add(8);
|
||||
}
|
||||
if (openGlesVersion == 2 || openGlesVersion == 3) {
|
||||
list.add(EGL10.EGL_RENDERABLE_TYPE);
|
||||
list.add(openGlesVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT);
|
||||
}
|
||||
if (supportsPixelBuffer) {
|
||||
list.add(EGL10.EGL_SURFACE_TYPE);
|
||||
list.add(EGL10.EGL_PBUFFER_BIT);
|
||||
}
|
||||
if (isRecordable) {
|
||||
list.add(EGL_RECORDABLE_ANDROID);
|
||||
list.add(1);
|
||||
}
|
||||
list.add(EGL10.EGL_NONE);
|
||||
|
||||
final int[] res = new int[list.size()];
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
res[i] = list.get(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int[] CONFIG_PLAIN = configBuilder().createConfigAttributes();
|
||||
public static final int[] CONFIG_RGBA =
|
||||
configBuilder().setHasAlphaChannel(true).createConfigAttributes();
|
||||
public static final int[] CONFIG_PIXEL_BUFFER =
|
||||
configBuilder().setSupportsPixelBuffer(true).createConfigAttributes();
|
||||
public static final int[] CONFIG_PIXEL_RGBA_BUFFER = configBuilder()
|
||||
.setHasAlphaChannel(true)
|
||||
.setSupportsPixelBuffer(true)
|
||||
.createConfigAttributes();
|
||||
public static final int[] CONFIG_RECORDABLE =
|
||||
configBuilder().setIsRecordable(true).createConfigAttributes();
|
||||
|
||||
static int getOpenGlesVersionFromConfig(int[] configAttributes) {
|
||||
for (int i = 0; i < configAttributes.length - 1; ++i) {
|
||||
if (configAttributes[i] == EGL10.EGL_RENDERABLE_TYPE) {
|
||||
switch (configAttributes[i + 1]) {
|
||||
case EGL_OPENGL_ES2_BIT:
|
||||
return 2;
|
||||
case EGL_OPENGL_ES3_BIT:
|
||||
return 3;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Default to V1 if no renderable type is specified.
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new context with the specified config attributes, sharing data with |sharedContext|.
|
||||
|
@ -27,6 +27,7 @@ import javax.microedition.khronos.egl.EGLSurface;
|
||||
* and an EGLSurface.
|
||||
*/
|
||||
class EglBase10Impl implements EglBase10 {
|
||||
private static final String TAG = "EglBase10Impl";
|
||||
// This constant is taken from EGL14.EGL_CONTEXT_CLIENT_VERSION.
|
||||
private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
|
||||
@ -64,7 +65,9 @@ class EglBase10Impl implements EglBase10 {
|
||||
this.egl = (EGL10) EGLContext.getEGL();
|
||||
eglDisplay = getEglDisplay();
|
||||
eglConfig = getEglConfig(eglDisplay, configAttributes);
|
||||
eglContext = createEglContext(sharedContext, eglDisplay, eglConfig);
|
||||
final int openGlesVersion = EglBase.getOpenGlesVersionFromConfig(configAttributes);
|
||||
Logging.d(TAG, "Using OpenGL ES version " + openGlesVersion);
|
||||
eglContext = createEglContext(sharedContext, eglDisplay, eglConfig, openGlesVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -309,12 +312,12 @@ class EglBase10Impl implements EglBase10 {
|
||||
}
|
||||
|
||||
// Return an EGLConfig, or die trying.
|
||||
private EGLContext createEglContext(
|
||||
@Nullable EGLContext sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) {
|
||||
private EGLContext createEglContext(@Nullable EGLContext sharedContext, EGLDisplay eglDisplay,
|
||||
EGLConfig eglConfig, int openGlesVersion) {
|
||||
if (sharedContext != null && sharedContext == EGL10.EGL_NO_CONTEXT) {
|
||||
throw new RuntimeException("Invalid sharedContext");
|
||||
}
|
||||
int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
|
||||
int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, openGlesVersion, EGL10.EGL_NONE};
|
||||
EGLContext rootContext = sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext;
|
||||
final EGLContext eglContext;
|
||||
synchronized (EglBase.lock) {
|
||||
|
@ -30,7 +30,7 @@ import org.webrtc.EglBase;
|
||||
@SuppressWarnings("ReferenceEquality") // We want to compare to EGL14 constants.
|
||||
@TargetApi(18)
|
||||
class EglBase14Impl implements EglBase14 {
|
||||
private static final String TAG = "EglBase14";
|
||||
private static final String TAG = "EglBase14Impl";
|
||||
private static final int EGLExt_SDK_VERSION = Build.VERSION_CODES.JELLY_BEAN_MR2;
|
||||
private static final int CURRENT_SDK_VERSION = Build.VERSION.SDK_INT;
|
||||
private EGLContext eglContext;
|
||||
@ -73,7 +73,9 @@ class EglBase14Impl implements EglBase14 {
|
||||
public EglBase14Impl(EGLContext sharedContext, int[] configAttributes) {
|
||||
eglDisplay = getEglDisplay();
|
||||
eglConfig = getEglConfig(eglDisplay, configAttributes);
|
||||
eglContext = createEglContext(sharedContext, eglDisplay, eglConfig);
|
||||
final int openGlesVersion = EglBase.getOpenGlesVersionFromConfig(configAttributes);
|
||||
Logging.d(TAG, "Using OpenGL ES version " + openGlesVersion);
|
||||
eglContext = createEglContext(sharedContext, eglDisplay, eglConfig, openGlesVersion);
|
||||
}
|
||||
|
||||
// Create EGLSurface from the Android Surface.
|
||||
@ -262,12 +264,12 @@ class EglBase14Impl implements EglBase14 {
|
||||
}
|
||||
|
||||
// Return an EGLConfig, or die trying.
|
||||
private static EGLContext createEglContext(
|
||||
@Nullable EGLContext sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) {
|
||||
private static EGLContext createEglContext(@Nullable EGLContext sharedContext,
|
||||
EGLDisplay eglDisplay, EGLConfig eglConfig, int openGlesVersion) {
|
||||
if (sharedContext != null && sharedContext == EGL14.EGL_NO_CONTEXT) {
|
||||
throw new RuntimeException("Invalid sharedContext");
|
||||
}
|
||||
int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
|
||||
int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, openGlesVersion, EGL14.EGL_NONE};
|
||||
EGLContext rootContext = sharedContext == null ? EGL14.EGL_NO_CONTEXT : sharedContext;
|
||||
final EGLContext eglContext;
|
||||
synchronized (EglBase.lock) {
|
||||
|
Reference in New Issue
Block a user