mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Refactor DummySurfaceThread, move code to generate SurfaceTexture to new class
This makes way for reusing EGLSurfaceTexture in other places, such as metadata and frame retriever. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=196240576
This commit is contained in:
parent
36d24c7aaa
commit
0fce0a0bcb
2 changed files with 285 additions and 137 deletions
|
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.opengl.EGL14;
|
||||||
|
import android.opengl.EGLConfig;
|
||||||
|
import android.opengl.EGLContext;
|
||||||
|
import android.opengl.EGLDisplay;
|
||||||
|
import android.opengl.EGLSurface;
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.annotation.IntDef;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/** Generates a {@link SurfaceTexture} using EGL/GLES functions. */
|
||||||
|
@TargetApi(17)
|
||||||
|
public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableListener, Runnable {
|
||||||
|
|
||||||
|
/** Secure mode to be used by the EGL surface and context. */
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER})
|
||||||
|
public @interface SecureMode {}
|
||||||
|
|
||||||
|
/** No secure EGL surface and context required. */
|
||||||
|
public static final int SECURE_MODE_NONE = 0;
|
||||||
|
/** Creating a surfaceless, secured EGL context. */
|
||||||
|
public static final int SECURE_MODE_SURFACELESS_CONTEXT = 1;
|
||||||
|
/** Creating a secure surface backed by a pixel buffer. */
|
||||||
|
public static final int SECURE_MODE_PROTECTED_PBUFFER = 2;
|
||||||
|
|
||||||
|
private static final int[] EGL_CONFIG_ATTRIBUTES =
|
||||||
|
new int[] {
|
||||||
|
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL14.EGL_RED_SIZE, 8,
|
||||||
|
EGL14.EGL_GREEN_SIZE, 8,
|
||||||
|
EGL14.EGL_BLUE_SIZE, 8,
|
||||||
|
EGL14.EGL_ALPHA_SIZE, 8,
|
||||||
|
EGL14.EGL_DEPTH_SIZE, 0,
|
||||||
|
EGL14.EGL_CONFIG_CAVEAT, EGL14.EGL_NONE,
|
||||||
|
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_WINDOW_BIT,
|
||||||
|
EGL14.EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int EGL_PROTECTED_CONTENT_EXT = 0x32C0;
|
||||||
|
|
||||||
|
/** A runtime exception to be thrown if some EGL operations failed. */
|
||||||
|
public static final class GlException extends RuntimeException {
|
||||||
|
private GlException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Handler handler;
|
||||||
|
private final int[] textureIdHolder;
|
||||||
|
|
||||||
|
private @Nullable EGLDisplay display;
|
||||||
|
private @Nullable EGLContext context;
|
||||||
|
private @Nullable EGLSurface surface;
|
||||||
|
private @Nullable SurfaceTexture texture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param handler The {@link Handler} that will be used to call {@link
|
||||||
|
* SurfaceTexture#updateTexImage()} to update images on the {@link SurfaceTexture}. Note that
|
||||||
|
* {@link #init(int)} has to be called on the same looper thread as the {@link Handler}'s
|
||||||
|
* looper.
|
||||||
|
*/
|
||||||
|
public EGLSurfaceTexture(Handler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
textureIdHolder = new int[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes required EGL parameters and creates the {@link SurfaceTexture}.
|
||||||
|
*
|
||||||
|
* @param secureMode The {@link SecureMode} to be used for EGL surface.
|
||||||
|
*/
|
||||||
|
public void init(@SecureMode int secureMode) {
|
||||||
|
display = getDefaultDisplay();
|
||||||
|
EGLConfig config = chooseEGLConfig(display);
|
||||||
|
context = createEGLContext(display, config, secureMode);
|
||||||
|
surface = createEGLSurface(display, config, context, secureMode);
|
||||||
|
generateTextureIds(textureIdHolder);
|
||||||
|
texture = new SurfaceTexture(textureIdHolder[0]);
|
||||||
|
texture.setOnFrameAvailableListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Releases all allocated resources. */
|
||||||
|
@SuppressWarnings({"nullness:argument.type.incompatible"})
|
||||||
|
public void release() {
|
||||||
|
handler.removeCallbacks(this);
|
||||||
|
try {
|
||||||
|
if (texture != null) {
|
||||||
|
texture.release();
|
||||||
|
GLES20.glDeleteTextures(1, textureIdHolder, 0);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (surface != null && !surface.equals(EGL14.EGL_NO_SURFACE)) {
|
||||||
|
EGL14.eglDestroySurface(display, surface);
|
||||||
|
}
|
||||||
|
if (context != null) {
|
||||||
|
EGL14.eglDestroyContext(display, context);
|
||||||
|
}
|
||||||
|
display = null;
|
||||||
|
context = null;
|
||||||
|
surface = null;
|
||||||
|
texture = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wrapped {@link SurfaceTexture}. This can only be called after {@link #init(int)}.
|
||||||
|
*/
|
||||||
|
public SurfaceTexture getSurfaceTexture() {
|
||||||
|
return Assertions.checkNotNull(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SurfaceTexture.OnFrameAvailableListener
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
|
||||||
|
handler.post(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runnable
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (texture != null) {
|
||||||
|
texture.updateTexImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EGLDisplay getDefaultDisplay() {
|
||||||
|
EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
|
||||||
|
if (display == null) {
|
||||||
|
throw new GlException("eglGetDisplay failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] version = new int[2];
|
||||||
|
boolean eglInitialized =
|
||||||
|
EGL14.eglInitialize(display, version, /* majorOffset= */ 0, version, /* minorOffset= */ 1);
|
||||||
|
if (!eglInitialized) {
|
||||||
|
throw new GlException("eglInitialize failed");
|
||||||
|
}
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EGLConfig chooseEGLConfig(EGLDisplay display) {
|
||||||
|
EGLConfig[] configs = new EGLConfig[1];
|
||||||
|
int[] numConfigs = new int[1];
|
||||||
|
boolean success =
|
||||||
|
EGL14.eglChooseConfig(
|
||||||
|
display,
|
||||||
|
EGL_CONFIG_ATTRIBUTES,
|
||||||
|
/* attrib_listOffset= */ 0,
|
||||||
|
configs,
|
||||||
|
/* configsOffset= */ 0,
|
||||||
|
/* config_size= */ 1,
|
||||||
|
numConfigs,
|
||||||
|
/* num_configOffset= */ 0);
|
||||||
|
if (!success || numConfigs[0] <= 0 || configs[0] == null) {
|
||||||
|
throw new GlException(
|
||||||
|
Util.formatInvariant(
|
||||||
|
/* format= */ "eglChooseConfig failed: success=%b, numConfigs[0]=%d, configs[0]=%s",
|
||||||
|
success, numConfigs[0], configs[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EGLContext createEGLContext(
|
||||||
|
EGLDisplay display, EGLConfig config, @SecureMode int secureMode) {
|
||||||
|
int[] glAttributes;
|
||||||
|
if (secureMode == SECURE_MODE_NONE) {
|
||||||
|
glAttributes = new int[] {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
|
||||||
|
} else {
|
||||||
|
glAttributes =
|
||||||
|
new int[] {
|
||||||
|
EGL14.EGL_CONTEXT_CLIENT_VERSION,
|
||||||
|
2,
|
||||||
|
EGL_PROTECTED_CONTENT_EXT,
|
||||||
|
EGL14.EGL_TRUE,
|
||||||
|
EGL14.EGL_NONE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EGLContext context =
|
||||||
|
EGL14.eglCreateContext(
|
||||||
|
display, config, android.opengl.EGL14.EGL_NO_CONTEXT, glAttributes, 0);
|
||||||
|
if (context == null) {
|
||||||
|
throw new GlException("eglCreateContext failed");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EGLSurface createEGLSurface(
|
||||||
|
EGLDisplay display, EGLConfig config, EGLContext context, @SecureMode int secureMode) {
|
||||||
|
EGLSurface surface;
|
||||||
|
if (secureMode == SECURE_MODE_SURFACELESS_CONTEXT) {
|
||||||
|
surface = EGL14.EGL_NO_SURFACE;
|
||||||
|
} else {
|
||||||
|
int[] pbufferAttributes;
|
||||||
|
if (secureMode == SECURE_MODE_PROTECTED_PBUFFER) {
|
||||||
|
pbufferAttributes =
|
||||||
|
new int[] {
|
||||||
|
EGL14.EGL_WIDTH,
|
||||||
|
1,
|
||||||
|
EGL14.EGL_HEIGHT,
|
||||||
|
1,
|
||||||
|
EGL_PROTECTED_CONTENT_EXT,
|
||||||
|
EGL14.EGL_TRUE,
|
||||||
|
EGL14.EGL_NONE
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
pbufferAttributes =
|
||||||
|
new int[] {
|
||||||
|
EGL14.EGL_WIDTH, 1,
|
||||||
|
EGL14.EGL_HEIGHT, 1,
|
||||||
|
EGL14.EGL_NONE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
surface = EGL14.eglCreatePbufferSurface(display, config, pbufferAttributes, /* offset= */ 0);
|
||||||
|
if (surface == null) {
|
||||||
|
throw new GlException("eglCreatePbufferSurface failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean eglMadeCurrent =
|
||||||
|
EGL14.eglMakeCurrent(display, /* draw= */ surface, /* read= */ surface, context);
|
||||||
|
if (!eglMadeCurrent) {
|
||||||
|
throw new GlException("eglMakeCurrent failed");
|
||||||
|
}
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void generateTextureIds(int[] textureIdHolder) {
|
||||||
|
GLES20.glGenTextures(/* n= */ 1, textureIdHolder, /* offset= */ 0);
|
||||||
|
int errorCode = GLES20.glGetError();
|
||||||
|
if (errorCode != GLES20.GL_NO_ERROR) {
|
||||||
|
throw new GlException("glGenTextures failed. Error: " + Integer.toHexString(errorCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,29 +15,29 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.video;
|
package com.google.android.exoplayer2.video;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.EGLSurfaceTexture.SECURE_MODE_NONE;
|
||||||
|
import static com.google.android.exoplayer2.util.EGLSurfaceTexture.SECURE_MODE_PROTECTED_PBUFFER;
|
||||||
|
import static com.google.android.exoplayer2.util.EGLSurfaceTexture.SECURE_MODE_SURFACELESS_CONTEXT;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.graphics.SurfaceTexture.OnFrameAvailableListener;
|
|
||||||
import android.opengl.EGL14;
|
import android.opengl.EGL14;
|
||||||
import android.opengl.EGLConfig;
|
|
||||||
import android.opengl.EGLContext;
|
|
||||||
import android.opengl.EGLDisplay;
|
import android.opengl.EGLDisplay;
|
||||||
import android.opengl.EGLSurface;
|
|
||||||
import android.opengl.GLES20;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Handler.Callback;
|
import android.os.Handler.Callback;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.support.annotation.IntDef;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
import com.google.android.exoplayer2.util.EGLSurfaceTexture;
|
||||||
|
import com.google.android.exoplayer2.util.EGLSurfaceTexture.SecureMode;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import javax.microedition.khronos.egl.EGL10;
|
import javax.microedition.khronos.egl.EGL10;
|
||||||
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dummy {@link Surface}.
|
* A dummy {@link Surface}.
|
||||||
|
|
@ -50,16 +50,6 @@ public final class DummySurface extends Surface {
|
||||||
private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
|
private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
|
||||||
private static final String EXTENSION_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
|
private static final String EXTENSION_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
|
||||||
|
|
||||||
private static final int EGL_PROTECTED_CONTENT_EXT = 0x32C0;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER})
|
|
||||||
private @interface SecureMode {}
|
|
||||||
|
|
||||||
private static final int SECURE_MODE_NONE = 0;
|
|
||||||
private static final int SECURE_MODE_SURFACELESS_CONTEXT = 1;
|
|
||||||
private static final int SECURE_MODE_PROTECTED_PBUFFER = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the surface is secure.
|
* Whether the surface is secure.
|
||||||
*/
|
*/
|
||||||
|
|
@ -161,32 +151,25 @@ public final class DummySurface extends Surface {
|
||||||
: SECURE_MODE_PROTECTED_PBUFFER;
|
: SECURE_MODE_PROTECTED_PBUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DummySurfaceThread extends HandlerThread implements OnFrameAvailableListener,
|
private static class DummySurfaceThread extends HandlerThread implements Callback {
|
||||||
Callback {
|
|
||||||
|
|
||||||
private static final int MSG_INIT = 1;
|
private static final int MSG_INIT = 1;
|
||||||
private static final int MSG_UPDATE_TEXTURE = 2;
|
private static final int MSG_RELEASE = 2;
|
||||||
private static final int MSG_RELEASE = 3;
|
|
||||||
|
|
||||||
private final int[] textureIdHolder;
|
private @MonotonicNonNull EGLSurfaceTexture eglSurfaceTexure;
|
||||||
private EGLDisplay display;
|
private @MonotonicNonNull Handler handler;
|
||||||
private EGLContext context;
|
private @Nullable Error initError;
|
||||||
private EGLSurface pbuffer;
|
private @Nullable RuntimeException initException;
|
||||||
private Handler handler;
|
private @Nullable DummySurface surface;
|
||||||
private SurfaceTexture surfaceTexture;
|
|
||||||
|
|
||||||
private Error initError;
|
|
||||||
private RuntimeException initException;
|
|
||||||
private DummySurface surface;
|
|
||||||
|
|
||||||
public DummySurfaceThread() {
|
public DummySurfaceThread() {
|
||||||
super("dummySurface");
|
super("dummySurface");
|
||||||
textureIdHolder = new int[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DummySurface init(@SecureMode int secureMode) {
|
public DummySurface init(@SecureMode int secureMode) {
|
||||||
start();
|
start();
|
||||||
handler = new Handler(getLooper(), this);
|
handler = new Handler(getLooper(), /* callback= */ this);
|
||||||
|
eglSurfaceTexure = new EGLSurfaceTexture(handler);
|
||||||
boolean wasInterrupted = false;
|
boolean wasInterrupted = false;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
handler.obtainMessage(MSG_INIT, secureMode, 0).sendToTarget();
|
handler.obtainMessage(MSG_INIT, secureMode, 0).sendToTarget();
|
||||||
|
|
@ -207,19 +190,15 @@ public final class DummySurface extends Surface {
|
||||||
} else if (initError != null) {
|
} else if (initError != null) {
|
||||||
throw initError;
|
throw initError;
|
||||||
} else {
|
} else {
|
||||||
return surface;
|
return Assertions.checkNotNull(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
|
Assertions.checkNotNull(handler);
|
||||||
handler.sendEmptyMessage(MSG_RELEASE);
|
handler.sendEmptyMessage(MSG_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
|
|
||||||
handler.sendEmptyMessage(MSG_UPDATE_TEXTURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleMessage(Message msg) {
|
public boolean handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
|
@ -238,9 +217,6 @@ public final class DummySurface extends Surface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case MSG_UPDATE_TEXTURE:
|
|
||||||
surfaceTexture.updateTexImage();
|
|
||||||
return true;
|
|
||||||
case MSG_RELEASE:
|
case MSG_RELEASE:
|
||||||
try {
|
try {
|
||||||
releaseInternal();
|
releaseInternal();
|
||||||
|
|
@ -256,103 +232,16 @@ public final class DummySurface extends Surface {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initInternal(@SecureMode int secureMode) {
|
private void initInternal(@SecureMode int secureMode) {
|
||||||
display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
|
Assertions.checkNotNull(eglSurfaceTexure);
|
||||||
Assertions.checkState(display != null, "eglGetDisplay failed");
|
eglSurfaceTexure.init(secureMode);
|
||||||
|
this.surface =
|
||||||
int[] version = new int[2];
|
new DummySurface(
|
||||||
boolean eglInitialized = EGL14.eglInitialize(display, version, 0, version, 1);
|
this, eglSurfaceTexure.getSurfaceTexture(), secureMode != SECURE_MODE_NONE);
|
||||||
Assertions.checkState(eglInitialized, "eglInitialize failed");
|
|
||||||
|
|
||||||
int[] eglAttributes =
|
|
||||||
new int[] {
|
|
||||||
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
|
||||||
EGL14.EGL_RED_SIZE, 8,
|
|
||||||
EGL14.EGL_GREEN_SIZE, 8,
|
|
||||||
EGL14.EGL_BLUE_SIZE, 8,
|
|
||||||
EGL14.EGL_ALPHA_SIZE, 8,
|
|
||||||
EGL14.EGL_DEPTH_SIZE, 0,
|
|
||||||
EGL14.EGL_CONFIG_CAVEAT, EGL14.EGL_NONE,
|
|
||||||
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_WINDOW_BIT,
|
|
||||||
EGL14.EGL_NONE
|
|
||||||
};
|
|
||||||
EGLConfig[] configs = new EGLConfig[1];
|
|
||||||
int[] numConfigs = new int[1];
|
|
||||||
boolean eglChooseConfigSuccess =
|
|
||||||
EGL14.eglChooseConfig(display, eglAttributes, 0, configs, 0, 1, numConfigs, 0);
|
|
||||||
Assertions.checkState(eglChooseConfigSuccess && numConfigs[0] > 0 && configs[0] != null,
|
|
||||||
"eglChooseConfig failed");
|
|
||||||
|
|
||||||
EGLConfig config = configs[0];
|
|
||||||
int[] glAttributes;
|
|
||||||
if (secureMode == SECURE_MODE_NONE) {
|
|
||||||
glAttributes = new int[] {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
|
|
||||||
} else {
|
|
||||||
glAttributes =
|
|
||||||
new int[] {
|
|
||||||
EGL14.EGL_CONTEXT_CLIENT_VERSION,
|
|
||||||
2,
|
|
||||||
EGL_PROTECTED_CONTENT_EXT,
|
|
||||||
EGL14.EGL_TRUE,
|
|
||||||
EGL14.EGL_NONE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
context =
|
|
||||||
EGL14.eglCreateContext(
|
|
||||||
display, config, android.opengl.EGL14.EGL_NO_CONTEXT, glAttributes, 0);
|
|
||||||
Assertions.checkState(context != null, "eglCreateContext failed");
|
|
||||||
|
|
||||||
EGLSurface surface;
|
|
||||||
if (secureMode == SECURE_MODE_SURFACELESS_CONTEXT) {
|
|
||||||
surface = EGL14.EGL_NO_SURFACE;
|
|
||||||
} else {
|
|
||||||
int[] pbufferAttributes;
|
|
||||||
if (secureMode == SECURE_MODE_PROTECTED_PBUFFER) {
|
|
||||||
pbufferAttributes =
|
|
||||||
new int[] {
|
|
||||||
EGL14.EGL_WIDTH,
|
|
||||||
1,
|
|
||||||
EGL14.EGL_HEIGHT,
|
|
||||||
1,
|
|
||||||
EGL_PROTECTED_CONTENT_EXT,
|
|
||||||
EGL14.EGL_TRUE,
|
|
||||||
EGL14.EGL_NONE
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
pbufferAttributes = new int[] {EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE};
|
|
||||||
}
|
|
||||||
pbuffer = EGL14.eglCreatePbufferSurface(display, config, pbufferAttributes, 0);
|
|
||||||
Assertions.checkState(pbuffer != null, "eglCreatePbufferSurface failed");
|
|
||||||
surface = pbuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean eglMadeCurrent = EGL14.eglMakeCurrent(display, surface, surface, context);
|
|
||||||
Assertions.checkState(eglMadeCurrent, "eglMakeCurrent failed");
|
|
||||||
|
|
||||||
GLES20.glGenTextures(1, textureIdHolder, 0);
|
|
||||||
surfaceTexture = new SurfaceTexture(textureIdHolder[0]);
|
|
||||||
surfaceTexture.setOnFrameAvailableListener(this);
|
|
||||||
this.surface = new DummySurface(this, surfaceTexture, secureMode != SECURE_MODE_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseInternal() {
|
private void releaseInternal() {
|
||||||
try {
|
Assertions.checkNotNull(eglSurfaceTexure);
|
||||||
if (surfaceTexture != null) {
|
eglSurfaceTexure.release();
|
||||||
surfaceTexture.release();
|
|
||||||
GLES20.glDeleteTextures(1, textureIdHolder, 0);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (pbuffer != null) {
|
|
||||||
EGL14.eglDestroySurface(display, pbuffer);
|
|
||||||
}
|
|
||||||
if (context != null) {
|
|
||||||
EGL14.eglDestroyContext(display, context);
|
|
||||||
}
|
|
||||||
pbuffer = null;
|
|
||||||
context = null;
|
|
||||||
display = null;
|
|
||||||
surface = null;
|
|
||||||
surfaceTexture = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue