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 ':demo', ':cameraview' |
||||||
|
include ':egloo' |
||||||
|
project(':egloo').projectDir = file('../Egloo/library') |
||||||
|
Loading…
Reference in new issue