parent
24b02caa28
commit
8bad417cf2
@ -0,0 +1,96 @@ |
||||
package com.otaliastudios.cameraview.internal; |
||||
|
||||
|
||||
import android.opengl.GLES11Ext; |
||||
import android.opengl.GLES20; |
||||
|
||||
import androidx.annotation.NonNull; |
||||
|
||||
import com.otaliastudios.cameraview.CameraLogger; |
||||
import com.otaliastudios.cameraview.filter.Filter; |
||||
import com.otaliastudios.cameraview.filter.NoFilter; |
||||
import com.otaliastudios.opengl.core.Egloo; |
||||
import com.otaliastudios.opengl.program.GlProgram; |
||||
import com.otaliastudios.opengl.texture.GlTexture; |
||||
|
||||
|
||||
public class GlTextureDrawer { |
||||
|
||||
private final static String TAG = GlTextureDrawer.class.getSimpleName(); |
||||
private final static CameraLogger LOG = CameraLogger.create(TAG); |
||||
|
||||
private final static int TEXTURE_TARGET = GLES11Ext.GL_TEXTURE_EXTERNAL_OES; |
||||
private final static int TEXTURE_UNIT = GLES20.GL_TEXTURE0; |
||||
|
||||
private final GlTexture mTexture; |
||||
private final float[] mTextureTransform = Egloo.IDENTITY_MATRIX.clone(); |
||||
|
||||
@NonNull |
||||
private Filter mFilter = new NoFilter(); |
||||
private Filter mPendingFilter = null; |
||||
private int mProgramHandle = -1; |
||||
|
||||
@SuppressWarnings("unused") |
||||
public GlTextureDrawer() { |
||||
this(new GlTexture(TEXTURE_UNIT, TEXTURE_TARGET)); |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
public GlTextureDrawer(int textureId) { |
||||
this(new GlTexture(TEXTURE_UNIT, TEXTURE_TARGET, textureId)); |
||||
} |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
public GlTextureDrawer(@NonNull GlTexture texture) { |
||||
mTexture = texture; |
||||
} |
||||
|
||||
public void setFilter(@NonNull Filter filter) { |
||||
mPendingFilter = filter; |
||||
} |
||||
|
||||
@NonNull |
||||
public GlTexture getTexture() { |
||||
return mTexture; |
||||
} |
||||
|
||||
@NonNull |
||||
public float[] getTextureTransform() { |
||||
return mTextureTransform; |
||||
} |
||||
|
||||
public void draw(long timestampUs) { |
||||
if (mPendingFilter != null) { |
||||
release(); |
||||
mFilter = mPendingFilter; |
||||
mPendingFilter = null; |
||||
} |
||||
|
||||
if (mProgramHandle == -1) { |
||||
mProgramHandle = GlProgram.create( |
||||
mFilter.getVertexShader(), |
||||
mFilter.getFragmentShader()); |
||||
mFilter.onCreate(mProgramHandle); |
||||
} |
||||
|
||||
Egloo.checkGlError("draw start"); |
||||
// Select the program and the active texture.
|
||||
GLES20.glUseProgram(mProgramHandle); |
||||
Egloo.checkGlError("glUseProgram"); |
||||
GLES20.glActiveTexture(mTexture.getUnit()); |
||||
GLES20.glBindTexture(mTexture.getTarget(), mTexture.getId()); |
||||
|
||||
// Draw and release.
|
||||
mFilter.draw(timestampUs, mTextureTransform); |
||||
GLES20.glBindTexture(mTexture.getTarget(), 0); |
||||
GLES20.glUseProgram(0); |
||||
Egloo.checkGlError("draw end"); |
||||
} |
||||
|
||||
public void release() { |
||||
if (mProgramHandle == -1) return; |
||||
mFilter.onDestroy(); |
||||
GLES20.glDeleteProgram(mProgramHandle); |
||||
mProgramHandle = -1; |
||||
} |
||||
} |
@ -1,96 +0,0 @@ |
||||
package com.otaliastudios.cameraview.internal; |
||||
|
||||
|
||||
import android.opengl.GLES20; |
||||
import android.opengl.Matrix; |
||||
|
||||
import androidx.annotation.NonNull; |
||||
|
||||
import com.otaliastudios.cameraview.CameraLogger; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.nio.ByteOrder; |
||||
import java.nio.FloatBuffer; |
||||
|
||||
public class GlUtils { |
||||
|
||||
private final static String TAG = GlUtils.class.getSimpleName(); |
||||
private final static CameraLogger LOG = CameraLogger.create(TAG); |
||||
|
||||
// Identity matrix for general use.
|
||||
public static final float[] IDENTITY_MATRIX = new float[16]; |
||||
static { |
||||
Matrix.setIdentityM(IDENTITY_MATRIX, 0); |
||||
} |
||||
|
||||
public static void checkError(@NonNull String opName) { |
||||
int error = GLES20.glGetError(); |
||||
if (error != GLES20.GL_NO_ERROR) { |
||||
String message = LOG.e("Error during", opName, "glError 0x", |
||||
Integer.toHexString(error)); |
||||
throw new RuntimeException(message); |
||||
} |
||||
} |
||||
|
||||
public static void checkLocation(int location, @NonNull String name) { |
||||
if (location < 0) { |
||||
String message = LOG.e("Unable to locate", name, "in program"); |
||||
throw new RuntimeException(message); |
||||
} |
||||
} |
||||
// Compiles the given shader, returns a handle.
|
||||
@SuppressWarnings("WeakerAccess") |
||||
public static int loadShader(int shaderType, @NonNull String source) { |
||||
int shader = GLES20.glCreateShader(shaderType); |
||||
checkError("glCreateShader type=" + shaderType); |
||||
GLES20.glShaderSource(shader, source); |
||||
GLES20.glCompileShader(shader); |
||||
int[] compiled = new int[1]; |
||||
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); |
||||
if (compiled[0] == 0) { |
||||
LOG.e("Could not compile shader", shaderType, ":", |
||||
GLES20.glGetShaderInfoLog(shader)); |
||||
GLES20.glDeleteShader(shader); |
||||
shader = 0; |
||||
} |
||||
return shader; |
||||
} |
||||
|
||||
// Creates a program with given vertex shader and pixel shader.
|
||||
public static int createProgram(@NonNull String vertexSource, @NonNull String fragmentSource) { |
||||
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); |
||||
if (vertexShader == 0) return 0; |
||||
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); |
||||
if (pixelShader == 0) return 0; |
||||
|
||||
int program = GLES20.glCreateProgram(); |
||||
checkError("glCreateProgram"); |
||||
if (program == 0) { |
||||
LOG.e("Could not create program"); |
||||
} |
||||
GLES20.glAttachShader(program, vertexShader); |
||||
checkError("glAttachShader"); |
||||
GLES20.glAttachShader(program, pixelShader); |
||||
checkError("glAttachShader"); |
||||
GLES20.glLinkProgram(program); |
||||
int[] linkStatus = new int[1]; |
||||
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); |
||||
if (linkStatus[0] != GLES20.GL_TRUE) { |
||||
LOG.e("Could not link program:", GLES20.glGetProgramInfoLog(program)); |
||||
GLES20.glDeleteProgram(program); |
||||
program = 0; |
||||
} |
||||
return program; |
||||
} |
||||
|
||||
// Allocates a direct float buffer, and populates it with the float array data.
|
||||
public static FloatBuffer floatBuffer(@NonNull float[] coords) { |
||||
// Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it.
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * 4); |
||||
bb.order(ByteOrder.nativeOrder()); |
||||
FloatBuffer fb = bb.asFloatBuffer(); |
||||
fb.put(coords); |
||||
fb.position(0); |
||||
return fb; |
||||
} |
||||
} |
@ -1 +1,3 @@ |
||||
include ':demo', ':cameraview' |
||||
include ':egloo' |
||||
project(':egloo').projectDir = file('../Egloo/library') |
||||
|
Loading…
Reference in new issue