├── .gitignore ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── copygpu │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── copygpu │ │ │ ├── GLCopyJni.java │ │ │ ├── MainActivity.java │ │ │ ├── MyGLRenderer.java │ │ │ ├── Picture.java │ │ │ ├── gpu │ │ │ ├── EGLManager.java │ │ │ ├── EGLUtil.java │ │ │ ├── GLUtil.java │ │ │ └── RenderThread.java │ │ │ └── view │ │ │ └── MySurfaceView.java │ ├── jni │ │ ├── Android.mk │ │ ├── GPUIPCommon.cpp │ │ ├── GPUIPCommon.h │ │ ├── GraphicBufferEx.cpp │ │ ├── GraphicBufferEx.h │ │ ├── NubiaGLCopy.cpp │ │ ├── NubiaGLCopy.h │ │ ├── Utils.cpp │ │ └── Utils.h │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ ├── texture_2d_fragment_shader.glsl │ │ ├── texture_oes2oes_fragment_shader.glsl │ │ ├── texture_oes_fragment_shader.glsl │ │ └── texture_vertex_shader.glsl │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── copygpu │ └── ExampleUnitTest.java ├── build.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.example.copygpu" 7 | minSdkVersion 26 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | ndk{ 18 | abiFilters "arm64-v8a" 19 | } 20 | } 21 | } 22 | externalNativeBuild { 23 | ndkBuild { 24 | path 'src/main/jni/Android.mk' 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 32 | testImplementation 'junit:junit:4.12' 33 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/copygpu/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.copygpu", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/GLCopyJni.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | /* 4 | * Author : chenguoting on 2018-8-1 17:23 5 | * Email : chen.guoting@nubia.com 6 | * Company : NUBIA TECHNOLOGY CO., LTD. 7 | */ 8 | public class GLCopyJni { 9 | static { 10 | System.loadLibrary("NubiaGLCopy"); 11 | } 12 | private long mHandler; 13 | 14 | public GLCopyJni(int width, int height, int texture) { 15 | mHandler = initHardwareBuffer(width, height, texture); 16 | } 17 | 18 | public void release() { 19 | releaseHardwareBuffer(mHandler); 20 | } 21 | 22 | public byte[] getBuffer() { 23 | return getBuffer(mHandler); 24 | } 25 | 26 | public void setBuffer(byte[] buffer) { 27 | setBuffer(mHandler, buffer); 28 | } 29 | 30 | private static native long initHardwareBuffer(int width, int height, int texture); 31 | private static native void releaseHardwareBuffer(long handler); 32 | private static native byte[] getBuffer(long handler); 33 | private static native void setBuffer(long handler, byte[] buffer); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.pm.PackageManager; 6 | import android.graphics.SurfaceTexture; 7 | import android.hardware.Camera; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | 11 | import com.example.copygpu.view.MySurfaceView; 12 | 13 | import java.io.IOException; 14 | import java.util.ArrayList; 15 | 16 | public class MainActivity extends Activity { 17 | private final static String TAG = "GPUActivity"; 18 | private SurfaceTexture mSurfaceTexture = new SurfaceTexture(0); 19 | private MySurfaceView mSurfaceView; 20 | private Camera mCamera; 21 | private int mCameraId = 0; 22 | private Camera.Parameters mParameters; 23 | private final static int PERMISSION_REQUEST_CODE = 1234; 24 | private boolean mIsPause = true; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | Log.i(TAG, "onCreate"); 30 | setContentView(R.layout.activity_main); 31 | initView(); 32 | checkPermiss(); 33 | } 34 | 35 | @Override 36 | protected void onResume() { 37 | super.onResume(); 38 | Log.i(TAG, "onResume"); 39 | mIsPause = false; 40 | openCamera(); 41 | } 42 | 43 | @Override 44 | protected void onPause() { 45 | Log.i(TAG, "onPause"); 46 | closeCamera(); 47 | mIsPause = true; 48 | super.onPause(); 49 | } 50 | 51 | private void initView() { 52 | mSurfaceView = (MySurfaceView)findViewById(R.id.surfaceView); 53 | mSurfaceView.addRenderer(new MyGLRenderer(this, mSurfaceTexture)); 54 | } 55 | 56 | private void checkPermiss() { 57 | ArrayList list = new ArrayList<>(); 58 | if (checkSelfPermission(Manifest.permission.CAMERA) 59 | != PackageManager.PERMISSION_GRANTED) { 60 | list.add(Manifest.permission.CAMERA); 61 | } 62 | if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) 63 | != PackageManager.PERMISSION_GRANTED) { 64 | list.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); 65 | } 66 | if(!list.isEmpty()) { 67 | requestPermissions(list.toArray(new String[list.size()]), PERMISSION_REQUEST_CODE); 68 | } 69 | } 70 | 71 | private boolean openCamera() { 72 | if(mIsPause || mCamera != null) { 73 | return false; 74 | } 75 | try { 76 | Log.i(TAG, "openCamera E"); 77 | mCamera = Camera.open(mCameraId); 78 | mCamera.setPreviewTexture(mSurfaceTexture); 79 | mParameters = mCamera.getParameters(); 80 | mParameters.setPreviewSize(1920, 1080); 81 | mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 82 | mCamera.setParameters(mParameters); 83 | mCamera.setDisplayOrientation(90); 84 | mCamera.startPreview(); 85 | Log.i(TAG, "openCamera X"); 86 | } catch (IOException e) { 87 | Log.e(TAG, e.getMessage()); 88 | return false; 89 | } 90 | return true; 91 | } 92 | 93 | private void closeCamera() { 94 | if(mCamera == null) { 95 | return; 96 | } 97 | mCamera.release(); 98 | mCamera = null; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/MyGLRenderer.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | import android.content.Context; 4 | import android.graphics.SurfaceTexture; 5 | import android.opengl.GLES11Ext; 6 | import android.opengl.GLES20; 7 | import android.util.Log; 8 | 9 | import com.example.copygpu.gpu.GLUtil; 10 | import com.example.copygpu.view.MySurfaceView; 11 | 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.util.Arrays; 15 | 16 | public class MyGLRenderer implements MySurfaceView.Renderer { 17 | private final static String TAG = "GPURenderer"; 18 | private Context mContext; 19 | private int mPreviewTextureId = -1; 20 | private SurfaceTexture mPreviewTexture; 21 | private GLCopyJni mGLCopyJni; 22 | private int mOESTextureId = -1; 23 | private Picture mPreview; 24 | private Picture m2DPicture; 25 | private Picture mOesPicture; 26 | private Picture mOes2OesPicture; 27 | private int[] mFrameBuffer; 28 | private int m2DTextureId = -1; 29 | 30 | 31 | public MyGLRenderer(Context c, SurfaceTexture texture) { 32 | mContext = c; 33 | mPreviewTexture = texture; 34 | } 35 | 36 | @Override 37 | public void onSurfaceCreated() { 38 | Log.i(TAG, "onSurfaceCreated"); 39 | GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 40 | 41 | mPreviewTextureId = GLUtil.getOneTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 42 | mPreviewTexture.detachFromGLContext(); 43 | mPreviewTexture.attachToGLContext(mPreviewTextureId); 44 | mPreview = new Picture(mContext.getResources(), R.raw.texture_vertex_shader, R.raw.texture_oes_fragment_shader, 45 | mPreviewTextureId, GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 46 | mOes2OesPicture = new Picture(mContext.getResources(), R.raw.texture_vertex_shader, R.raw.texture_oes2oes_fragment_shader, 47 | mPreviewTextureId, GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 48 | 49 | mOESTextureId = GLUtil.getOneTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 50 | mGLCopyJni = new GLCopyJni(1080, 1920, mOESTextureId); 51 | mOesPicture = new Picture(mContext.getResources(), R.raw.texture_vertex_shader, R.raw.texture_oes_fragment_shader, 52 | mOESTextureId, GLES11Ext.GL_TEXTURE_EXTERNAL_OES); 53 | 54 | m2DTextureId = GLUtil.getOneTexture(GLES20.GL_TEXTURE_2D); 55 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 1080, 1920, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 56 | m2DPicture = new Picture(mContext.getResources(), R.raw.texture_vertex_shader, R.raw.texture_2d_fragment_shader, 57 | m2DTextureId, GLES20.GL_TEXTURE_2D); 58 | } 59 | 60 | @Override 61 | public void onSurfaceChanged(int width, int height) { 62 | Log.i(TAG, "onSurfaceChanged "+width+" "+height); 63 | GLES20.glViewport(0, 0, width, height); 64 | } 65 | 66 | @Override 67 | public void onSurfaceDraw() { 68 | // Redraw background color 69 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 70 | 71 | mPreviewTexture.updateTexImage(); 72 | //直接将预览绘制到屏幕 73 | //mPreview.draw(); 74 | 75 | //将一个YUV数据放到OES纹理,再将纹理绘制到屏幕 76 | /*byte[] bytes = new byte[1080*1920*3/2]; 77 | Arrays.fill(bytes, (byte)127); 78 | mGLCopyJni.setBuffer(bytes); 79 | mOesPicture.draw();*/ 80 | 81 | //将预览绘制到一个2D纹理,再将纹理绘制到屏幕 82 | /*beginRenderTarget(GLES20.GL_TEXTURE_2D, m2DTextureId); 83 | GLUtil.checkGlError(); 84 | mPreview.draw(); 85 | GLUtil.checkGlError(); 86 | endRenderTarget(); 87 | m2DPicture.draw();*/ 88 | 89 | long start = System.currentTimeMillis(); 90 | //将预览绘制到一个OES纹理,将纹理的数据拷贝出来并保存,再将纹理绘制到屏幕 91 | beginRenderTarget(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESTextureId); 92 | GLUtil.checkGlError(); 93 | mOes2OesPicture.draw(); 94 | GLUtil.checkGlError(); 95 | GLES20.glFinish(); 96 | endRenderTarget(); 97 | yuv = mGLCopyJni.getBuffer(); 98 | long end = System.currentTimeMillis(); 99 | time = time * 0.8f + (end-start) * 0.2f; 100 | Log.i(TAG, "time "+time); 101 | save(yuv); 102 | mOesPicture.draw(); 103 | } 104 | float time = 0; 105 | byte[] yuv; 106 | 107 | @Override 108 | public void onSurfaceDestroyed() { 109 | Log.i(TAG, "onSurfaceDestroyed"); 110 | mPreviewTexture.detachFromGLContext(); 111 | GLES20.glDeleteTextures(1, new int[]{mPreviewTextureId}, 0); 112 | mPreviewTextureId = -1; 113 | 114 | mGLCopyJni.release(); 115 | GLES20.glDeleteTextures(1, new int[]{mOESTextureId}, 0); 116 | mOESTextureId = -1; 117 | 118 | if(mFrameBuffer != null) { 119 | GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); 120 | } 121 | } 122 | 123 | public void beginRenderTarget(int target, int textureId){ 124 | if(mFrameBuffer == null){ 125 | mFrameBuffer = new int[1]; 126 | GLES20.glGenFramebuffers(1, mFrameBuffer, 0); 127 | GLUtil.checkGlError(); 128 | } 129 | 130 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); 131 | GLUtil.checkGlError(); 132 | 133 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 134 | target, textureId, 0); 135 | GLUtil.checkFramebufferStatus(); 136 | } 137 | 138 | public void endRenderTarget(){ 139 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 140 | GLUtil.checkGlError(); 141 | } 142 | 143 | private static void save(byte[] yuv) { 144 | try { 145 | String pathName = "/sdcard/hw.yuv"; 146 | FileOutputStream outputStream = new FileOutputStream(pathName); 147 | outputStream.write(yuv); 148 | outputStream.close(); 149 | } catch (IOException e) { 150 | e.printStackTrace(); 151 | } 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/Picture.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | import android.content.res.Resources; 4 | import android.opengl.GLES20; 5 | import android.opengl.Matrix; 6 | 7 | import com.example.copygpu.gpu.GLUtil; 8 | 9 | import java.nio.FloatBuffer; 10 | 11 | /* 12 | * Author : chenguoting on 2018-7-10 10:24 13 | * Email : chen.guoting@nubia.com 14 | * Company : NUBIA TECHNOLOGY CO., LTD. 15 | */ 16 | public class Picture { 17 | private final int mProgram; 18 | private int mPositionHandle; 19 | private int mTextureCoordHandle; 20 | private int mMVPMatrixHandle; 21 | private int mSTMatrixHandle; 22 | private int mTextureHandle; 23 | 24 | private float[] mMVPMatrix = new float[16]; 25 | private float[] mSTMatrix = new float[16]; 26 | private final int vertexCount = rectCoords.length / COORDS_PER_VERTEX; 27 | private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex 28 | private FloatBuffer vertexBuffer; 29 | private FloatBuffer textureCoordBuffer; 30 | private int mTextureID; 31 | private int mTextureTarget; 32 | 33 | // number of coordinates per vertex in this array 34 | static final int COORDS_PER_VERTEX = 3; 35 | 36 | static final float rectCoords[] = { 37 | -1, 1, 0, //左上 38 | 1, 1, 0, //右上 39 | -1, -1, 0, //左下 40 | 1, -1, 0 //右下 41 | }; 42 | 43 | static final float textureCoords[] = { 44 | 0, 0, 45 | 1, 0, 46 | 0, 1, 47 | 1, 1 48 | }; 49 | 50 | public Picture(Resources res, int vertexId, int fragmentId, int textureId, int target) { 51 | Matrix.setIdentityM(mMVPMatrix, 0); 52 | Matrix.setIdentityM(mSTMatrix, 0); 53 | 54 | vertexBuffer = GLUtil.arrayToBuffer(rectCoords); 55 | textureCoordBuffer = GLUtil.arrayToBuffer(textureCoords); 56 | 57 | mTextureID = textureId; 58 | mTextureTarget = target; 59 | 60 | int vertexShader = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, 61 | GLUtil.readRawFile(res, vertexId)); 62 | int fragmentShader = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, 63 | GLUtil.readRawFile(res, fragmentId)); 64 | mProgram = GLUtil.createProgram(vertexShader, fragmentShader); 65 | 66 | mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 67 | mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 68 | mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 69 | mSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix"); 70 | mTextureHandle = GLES20.glGetUniformLocation(mProgram, "uTextureSampler"); 71 | 72 | } 73 | 74 | 75 | public void draw() { 76 | // Add program to OpenGL ES environment 77 | GLES20.glUseProgram(mProgram); 78 | 79 | // Enable a handle to the rect vertices 80 | GLES20.glEnableVertexAttribArray(mPositionHandle); 81 | // Prepare the rect coordinate data 82 | GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 83 | GLES20.GL_FLOAT, false, 84 | vertexStride, vertexBuffer); 85 | 86 | GLES20.glEnableVertexAttribArray(mTextureCoordHandle); 87 | GLES20.glVertexAttribPointer(mTextureCoordHandle, 2, 88 | GLES20.GL_FLOAT, false, 89 | 2*4, textureCoordBuffer); 90 | 91 | GLES20.glActiveTexture(GLES20.GL_TEXTURE3); 92 | GLES20.glBindTexture(mTextureTarget, mTextureID); 93 | GLES20.glUniform1i(mTextureHandle, 3); 94 | 95 | GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 96 | GLES20.glUniformMatrix4fv(mSTMatrixHandle, 1, false, mSTMatrix, 0); 97 | 98 | // Draw the triangle 99 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount); 100 | 101 | // Disable vertex array 102 | GLES20.glDisableVertexAttribArray(mPositionHandle); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/gpu/EGLManager.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu.gpu; 2 | /* 3 | * Author : jinrong on 2017-7-21 9:16 4 | * Email : jin.rong1@nubia.com 5 | * Company : NUBIA TECHNOLOGY CO., LTD. 6 | */ 7 | 8 | import android.opengl.EGL14; 9 | import android.opengl.EGLConfig; 10 | import android.opengl.EGLContext; 11 | import android.opengl.EGLDisplay; 12 | import android.opengl.EGLSurface; 13 | import android.view.SurfaceHolder; 14 | 15 | public class EGLManager { 16 | 17 | 18 | private EGLDisplay mEglDisplay; 19 | private EGLConfig mEGLConfig; 20 | private EGLContext mEGLContext; 21 | private EGLSurface mEglWindowSurface; 22 | private EGLSurface mEglSnapshotSurface = null; 23 | private State mState = State.UNINIT; 24 | public enum State{ 25 | UNINIT, 26 | INITED, 27 | SURFACED, 28 | REGISTERD, 29 | UNREGISTERD, 30 | } 31 | 32 | public EGLManager() throws Exception { 33 | mEglDisplay = EGLUtil.getEGLDisplay(); 34 | mEGLConfig = EGLUtil.getEGLConfig(mEglDisplay); 35 | mEGLContext = EGLUtil.getEGLContext(mEglDisplay, mEGLConfig); 36 | mState = State.INITED; 37 | } 38 | 39 | public void release() { 40 | if (mState.ordinal() > State.UNINIT.ordinal()) { 41 | EGL14.eglDestroyContext(mEglDisplay, mEGLContext); 42 | mEGLContext = null; 43 | if(mEglSnapshotSurface != null){ 44 | EGL14.eglDestroySurface(mEglDisplay, mEglSnapshotSurface); 45 | mEglSnapshotSurface=null; 46 | } 47 | EGL14.eglTerminate(mEglDisplay); 48 | } 49 | 50 | mEglDisplay = null; 51 | mEGLConfig = null; 52 | 53 | mState = State.UNINIT; 54 | } 55 | 56 | public void swapBuffer(){ 57 | EGL14.eglSwapBuffers(mEglDisplay, mEglWindowSurface); 58 | } 59 | 60 | public boolean registerContext(){ 61 | return EGL14.eglMakeCurrent(mEglDisplay, mEglWindowSurface, 62 | mEglWindowSurface, mEGLContext); 63 | } 64 | 65 | public void unregisterContext(){ 66 | EGL14.eglMakeCurrent(mEglDisplay, EGL14.EGL_NO_SURFACE, 67 | EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT); 68 | } 69 | 70 | public EGLSurface createWindowSurface(SurfaceHolder surface) throws Exception { 71 | int[] surfaceAttribs = { EGL14.EGL_NONE }; 72 | mEglWindowSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEGLConfig, surface, surfaceAttribs, 0); 73 | int error = EGL14.eglGetError(); 74 | if(error != EGL14.EGL_SUCCESS){ 75 | throw new Exception("fail to get window surface error: "+error); 76 | } 77 | return mEglWindowSurface; 78 | } 79 | 80 | public void releaseWindowSurface() { 81 | if(mEglWindowSurface != null) { 82 | EGL14.eglDestroySurface(mEglDisplay, mEglWindowSurface); 83 | mEglWindowSurface=null; 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/gpu/EGLUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu.gpu; 2 | /* 3 | * Author : jinrong on 2017-7-21 9:16 4 | * Email : jin.rong1@nubia.com 5 | * Company : NUBIA TECHNOLOGY CO., LTD. 6 | */ 7 | 8 | import android.opengl.EGL14; 9 | import android.opengl.EGLConfig; 10 | import android.opengl.EGLContext; 11 | import android.opengl.EGLDisplay; 12 | import android.util.Log; 13 | 14 | public class EGLUtil { 15 | private final static String TAG = "EGLUtil"; 16 | public static final int EGL_RECORDABLE_ANDROID = 0x3142; 17 | 18 | public static void arraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length) { 19 | for(int s=srcPos,d=dstPos,i=0; s mRendererList = new ArrayList(); 29 | 30 | 31 | public RenderThread(SurfaceHolder holder, ArrayList list){ 32 | super("Nubia Render Thread"); 33 | mWindowSurfaceHolder = holder; 34 | mRendererList = list; 35 | } 36 | 37 | public void setSurfaceSize(int w, int h) { 38 | width = w; 39 | height = h; 40 | isSurfaceChanged = true; 41 | synchronized (this) { 42 | notify(); 43 | } 44 | } 45 | 46 | private void notifyRendererCreated() { 47 | if(mRendererList.isEmpty()) { 48 | return; 49 | } 50 | MySurfaceView.Renderer[] renderers = mRendererList.toArray(new MySurfaceView.Renderer[mRendererList.size()]); 51 | for(MySurfaceView.Renderer renderer : renderers) { 52 | renderer.onSurfaceCreated(); 53 | } 54 | } 55 | private void notifyRendererChanged() { 56 | if(mRendererList.isEmpty()) { 57 | return; 58 | } 59 | MySurfaceView.Renderer[] renderers = mRendererList.toArray(new MySurfaceView.Renderer[mRendererList.size()]); 60 | for(MySurfaceView.Renderer renderer : renderers) { 61 | renderer.onSurfaceChanged(width, height); 62 | } 63 | } 64 | private void notifyRendererDraw() { 65 | if(mRendererList.isEmpty()) { 66 | return; 67 | } 68 | MySurfaceView.Renderer[] renderers = mRendererList.toArray(new MySurfaceView.Renderer[mRendererList.size()]); 69 | for(MySurfaceView.Renderer renderer : renderers) { 70 | renderer.onSurfaceDraw(); 71 | } 72 | } 73 | private void notifyRendererDestroyed() { 74 | if(mRendererList.isEmpty()) { 75 | return; 76 | } 77 | MySurfaceView.Renderer[] renderers = mRendererList.toArray(new MySurfaceView.Renderer[mRendererList.size()]); 78 | for(MySurfaceView.Renderer renderer : renderers) { 79 | renderer.onSurfaceDestroyed(); 80 | } 81 | } 82 | 83 | public void finish(){ 84 | mFinished = true; 85 | mWindowSurfaceHolder = null; 86 | synchronized (this) { 87 | notify(); 88 | } 89 | } 90 | 91 | @Override 92 | public void run() { 93 | Log.i(TAG, "thread "+getId()+" start"); 94 | initEglEnv(); 95 | 96 | notifyRendererCreated(); 97 | 98 | while (!mFinished) { 99 | synchronized (this) { 100 | if(width == 0 || height == 0) { 101 | try { 102 | wait(); 103 | } catch (InterruptedException e) { 104 | e.printStackTrace(); 105 | } 106 | continue; 107 | } 108 | } 109 | 110 | if(isSurfaceChanged) { 111 | notifyRendererChanged(); 112 | isSurfaceChanged = false; 113 | } 114 | 115 | notifyRendererDraw(); 116 | 117 | GLES20.glFinish(); 118 | mEGLManager.swapBuffer(); 119 | } 120 | notifyRendererDestroyed(); 121 | 122 | releaseEglEnv(); 123 | Log.i(TAG, "thread "+getId()+" end"); 124 | } 125 | 126 | private void initEglEnv() { 127 | try { 128 | mEGLManager = new EGLManager(); 129 | mEGLManager.createWindowSurface(mWindowSurfaceHolder); 130 | mEGLManager.registerContext(); 131 | isEGLSurfaceCreate = true; 132 | } catch (Exception e) { 133 | e.printStackTrace(); 134 | } 135 | } 136 | 137 | private void releaseEglEnv() { 138 | Log.i(TAG, "releaseEglEnv"); 139 | if(isEGLSurfaceCreate) { 140 | mEGLManager.unregisterContext(); 141 | mEGLManager.releaseWindowSurface(); 142 | mEGLManager.release(); 143 | isEGLSurfaceCreate = false; 144 | } 145 | } 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/copygpu/view/MySurfaceView.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu.view; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.util.Log; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | 9 | import com.example.copygpu.gpu.RenderThread; 10 | 11 | import java.util.ArrayList; 12 | 13 | /* 14 | * Author : chenguoting on 2018-8-4 10:42 15 | * Email : chen.guoting@nubia.com 16 | * Company : NUBIA TECHNOLOGY CO., LTD. 17 | */ 18 | public class MySurfaceView extends SurfaceView { 19 | private final static String TAG = "MySurfaceView"; 20 | private RenderThread mRenderThread; 21 | private ArrayList mRendererList = new ArrayList(); 22 | 23 | public interface Renderer { 24 | public void onSurfaceCreated(); 25 | public void onSurfaceChanged(int width, int height); 26 | public void onSurfaceDraw(); 27 | public void onSurfaceDestroyed(); 28 | } 29 | 30 | public MySurfaceView(Context context) { 31 | this(context, null); 32 | } 33 | 34 | public MySurfaceView(Context context, AttributeSet attrs) { 35 | this(context, attrs, 0); 36 | } 37 | 38 | public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { 39 | this(context, attrs, defStyleAttr, 0); 40 | } 41 | 42 | public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 43 | super(context, attrs, defStyleAttr, defStyleRes); 44 | getHolder().addCallback(Callback); 45 | } 46 | 47 | public void addRenderer(Renderer renderer) { 48 | mRendererList.add(renderer); 49 | } 50 | 51 | public void removeRenderer(Renderer renderer) { 52 | mRendererList.remove(renderer); 53 | } 54 | 55 | SurfaceHolder.Callback Callback = new SurfaceHolder.Callback() { 56 | @Override 57 | public void surfaceCreated(SurfaceHolder surfaceHolder) { 58 | Log.i(TAG, "surfaceCreated"); 59 | mRenderThread = new RenderThread(surfaceHolder, mRendererList); 60 | mRenderThread.start(); 61 | } 62 | 63 | @Override 64 | public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { 65 | Log.i(TAG, "surfaceChanged "+i+" "+i1+" "+i2); 66 | mRenderThread.setSurfaceSize(i1, i2); 67 | } 68 | 69 | @Override 70 | public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 71 | Log.i(TAG, "surfaceDestroyed"); 72 | mRenderThread.finish(); 73 | } 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE := libNubiaGLCopy 6 | 7 | LOCAL_SRC_FILES += GraphicBufferEx.cpp \ 8 | GPUIPCommon.cpp \ 9 | Utils.cpp \ 10 | NubiaGLCopy.cpp 11 | 12 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/GPUIP \ 13 | $(LOCAL_PATH)/GPUIP/Utils \ 14 | $(NDK_INCLUDE) 15 | 16 | LOCAL_LDLIBS += -llog -lEGL -lGLESv3 -lnativewindow 17 | LOCAL_CPPFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wno-unused-parameter 18 | include $(BUILD_SHARED_LIBRARY) 19 | -------------------------------------------------------------------------------- /app/src/main/jni/GPUIPCommon.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUIPCommon.h" 2 | 3 | void GPUIPBuffer_NV21_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer) 4 | { 5 | if ((srcBuffer->width != dstBuffer->width) 6 | || (srcBuffer->height != dstBuffer->height)) 7 | { 8 | LOGE("GPUIPBuffer_NV21_COPY error. srcW = %d, dstW = %d, srcH = %d, dstH = %d\n", 9 | srcBuffer->width, dstBuffer->width, srcBuffer->height, dstBuffer->height); 10 | return; 11 | } 12 | 13 | if (srcBuffer->stride == dstBuffer->stride) 14 | { 15 | int size = srcBuffer->stride * srcBuffer->height; 16 | 17 | memcpy(dstBuffer->pY, srcBuffer->pY, size); 18 | memcpy(dstBuffer->pU, srcBuffer->pU, size / 2); 19 | } 20 | else 21 | { 22 | int i; 23 | uint8_t *pSrc; 24 | uint8_t *pDst; 25 | 26 | //LOGE("GPUIPBuffer_NV21_COPY warning! srcStride = %d, dstStride = %d", 27 | // srcBuffer->stride, dstBuffer->stride); 28 | pSrc = (uint8_t *)srcBuffer->pY; 29 | pDst = (uint8_t *)dstBuffer->pY; 30 | 31 | for (i = 0; i < srcBuffer->height; i++) 32 | { 33 | memcpy(pDst, pSrc, srcBuffer->width); 34 | pSrc += srcBuffer->stride; 35 | pDst += dstBuffer->stride; 36 | } 37 | 38 | pSrc = (uint8_t *)srcBuffer->pU; 39 | pDst = (uint8_t *)dstBuffer->pU; 40 | 41 | for (i = 0; i < srcBuffer->height / 2; i++) 42 | { 43 | memcpy(pDst, pSrc, srcBuffer->width); 44 | pSrc += srcBuffer->stride; 45 | pDst += dstBuffer->stride; 46 | } 47 | } 48 | } 49 | 50 | void GPUIPBuffer_RGB_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer) 51 | { 52 | int size; 53 | 54 | if ((srcBuffer->width != dstBuffer->width) 55 | || (srcBuffer->height != dstBuffer->height)) 56 | { 57 | LOGE("GPUIPBuffer_RGB_COPY error. srcW = %d, dstW = %d, srcH = %d, dstH = %d\n", 58 | srcBuffer->width, dstBuffer->width, srcBuffer->height, dstBuffer->height); 59 | return; 60 | } 61 | 62 | if (srcBuffer->stride == dstBuffer->stride) 63 | { 64 | size = srcBuffer->stride * srcBuffer->height * 3; 65 | memcpy(dstBuffer->pY, srcBuffer->pY, size); 66 | } 67 | else 68 | { 69 | int i; 70 | int srcSize; 71 | int dstSize; 72 | uint8_t *pSrcBuffer; 73 | uint8_t *pDstBuffer; 74 | 75 | LOGE("GPUIPBuffer_RGB_COPY warning! srcStride = %d, dstStride = %d", 76 | srcBuffer->stride, dstBuffer->stride); 77 | pSrcBuffer = (uint8_t *)srcBuffer->pY; 78 | pDstBuffer = (uint8_t *)dstBuffer->pY; 79 | size = srcBuffer->width * 3; 80 | srcSize = srcBuffer->stride * 3; 81 | dstSize = dstBuffer->stride * 3; 82 | 83 | for (i = 0; i < srcBuffer->height; i++) 84 | { 85 | memcpy(pDstBuffer, pSrcBuffer, size); 86 | pSrcBuffer += srcSize; 87 | pDstBuffer += dstSize; 88 | } 89 | } 90 | } 91 | 92 | void GPUIPBuffer_RGBA_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer) 93 | { 94 | int size; 95 | 96 | if ((srcBuffer->width != dstBuffer->width) 97 | || (srcBuffer->height != dstBuffer->height)) 98 | { 99 | LOGE("GPUIPBuffer_RGBA_COPY error. srcW = %d, dstW = %d, srcH = %d, dstH = %d\n", 100 | srcBuffer->width, dstBuffer->width, srcBuffer->height, dstBuffer->height); 101 | return; 102 | } 103 | 104 | if (srcBuffer->stride == dstBuffer->stride) 105 | { 106 | size = srcBuffer->stride * srcBuffer->height * 4; 107 | memcpy(dstBuffer->pY, srcBuffer->pY, size); 108 | } 109 | else 110 | { 111 | int i; 112 | int srcSize; 113 | int dstSize; 114 | uint8_t *pSrcBuffer; 115 | uint8_t *pDstBuffer; 116 | 117 | LOGE("GPUIPBuffer_RGBA_COPY warning! srcStride = %d, dstStride = %d", 118 | srcBuffer->stride, dstBuffer->stride); 119 | pSrcBuffer = (uint8_t *)srcBuffer->pY; 120 | pDstBuffer = (uint8_t *)dstBuffer->pY; 121 | size = srcBuffer->width * 4; 122 | srcSize = srcBuffer->stride * 4; 123 | dstSize = dstBuffer->stride * 4; 124 | 125 | for (i = 0; i < srcBuffer->height; i++) 126 | { 127 | memcpy(pDstBuffer, pSrcBuffer, size); 128 | pSrcBuffer += srcSize; 129 | pDstBuffer += dstSize; 130 | } 131 | } 132 | } 133 | 134 | void GPUIPBuffer_Y8U8V8_NV21(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer) 135 | { 136 | int i, j; 137 | int width, height; 138 | uint8_t *pSrcBuffer; 139 | uint8_t *pDstBuffer; 140 | 141 | if ((srcBuffer->width != dstBuffer->width) 142 | || (srcBuffer->height != dstBuffer->height)) 143 | { 144 | LOGE("GPUIPBuffer_Y8U8V8_NV21 error. srcW = %d, dstW = %d, srcH = %d, dstH = %d\n", 145 | srcBuffer->width, dstBuffer->width, srcBuffer->height, dstBuffer->height); 146 | return; 147 | } 148 | 149 | width = srcBuffer->width; 150 | height = srcBuffer->height; 151 | 152 | //Y8U8V8 -> YUV 153 | for (j = 0; j < height; j++) 154 | { 155 | pSrcBuffer = (uint8_t *)srcBuffer->pY; 156 | pSrcBuffer += (srcBuffer->stride * j * 3); 157 | pDstBuffer = (uint8_t *)dstBuffer->pY; 158 | pDstBuffer += (dstBuffer->stride * j); 159 | 160 | for (i = 0; i < width; i++) 161 | { 162 | *pDstBuffer = *pSrcBuffer; 163 | pSrcBuffer += 3; 164 | pDstBuffer++; 165 | } 166 | } 167 | 168 | for (j = 0; j < height / 2; j++) 169 | { 170 | pSrcBuffer = (uint8_t *)srcBuffer->pY; 171 | pSrcBuffer += (srcBuffer->stride * j * 3 * 2 + 1); 172 | pDstBuffer = (uint8_t *)dstBuffer->pU; 173 | pDstBuffer += (dstBuffer->stride * j); 174 | 175 | for (i = 0; i < width / 2; i++) 176 | { 177 | *pDstBuffer = *pSrcBuffer; 178 | pSrcBuffer++; 179 | pDstBuffer++; 180 | 181 | *pDstBuffer = *pSrcBuffer; 182 | pSrcBuffer += 5; 183 | pDstBuffer++; 184 | } 185 | } 186 | } 187 | 188 | -------------------------------------------------------------------------------- /app/src/main/jni/GPUIPCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef GPUIP_COMMON_H 2 | #define GPUIP_COMMON_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define PI 3.1415926f 11 | #define MAX_BINARY_PROGRAM_SIZE (50 * 1024) 12 | 13 | #undef LOG_TAG 14 | #define LOG_TAG "[libGPUIP]" 15 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) 16 | #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) 17 | #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) 18 | #define PRINTF LOGI 19 | 20 | //#define JNI_INTERFACE_BOKEH 21 | //#define JNI_INTERFACE_ROTATION 22 | //#define JNI_INTERFACE_ZOOMBLUR 23 | 24 | #define USE_GRAPHIC_BUFFER 25 | //#define USE_HARDWARE_BUFFER 26 | 27 | //#define SHADER_PROGRAM_BINARY 28 | 29 | typedef enum 30 | { 31 | /*8 bit Y plane followed by 8 bit 2x2 subsampled UV planes*/ 32 | PIX_FORMAT_NV12, 33 | /*8 bit Y plane followed by 8 bit 2x2 subsampled VU planes*/ 34 | PIX_FORMAT_NV21, 35 | /*8 bit Y plane followed by 8 bit 2x2 subsampled U and V planes*/ 36 | PIX_FORMAT_I420 37 | }PIX_FORMAT_SUPPORT; 38 | 39 | struct yuvBuffer 40 | { 41 | public: 42 | int w; 43 | int h; 44 | int pixformat; 45 | int yPitch; 46 | int uvPitch; 47 | int len; 48 | void *Y; 49 | void *U; 50 | void *V; 51 | 52 | public: 53 | yuvBuffer() 54 | : w(0) 55 | , h(0) 56 | , pixformat(PIX_FORMAT_NV21) 57 | , yPitch(0) 58 | , uvPitch(0) 59 | , len(0) 60 | , Y(NULL) 61 | , U(NULL) 62 | , V(NULL) { 63 | } 64 | }; 65 | 66 | struct GPUIPBuffer 67 | { 68 | public: 69 | int width; 70 | int height; 71 | int format; 72 | int stride; 73 | int length; 74 | void *pY; 75 | void *pU; 76 | void *pV; 77 | 78 | public: 79 | GPUIPBuffer() 80 | : width(0) 81 | , height(0) 82 | , format(PIX_FORMAT_NV21) 83 | , stride(0) 84 | , length(0) 85 | , pY(NULL) 86 | , pU(NULL) 87 | , pV(NULL) { 88 | } 89 | }; 90 | 91 | void GPUIPBuffer_NV21_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer); 92 | void GPUIPBuffer_RGB_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer); 93 | void GPUIPBuffer_RGBA_COPY(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer); 94 | void GPUIPBuffer_Y8U8V8_NV21(GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer); 95 | 96 | 97 | #endif -------------------------------------------------------------------------------- /app/src/main/jni/GraphicBufferEx.cpp: -------------------------------------------------------------------------------- 1 | #include "GraphicBufferEx.h" 2 | #include "Utils.h" 3 | 4 | static const int USAGE = (AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN 5 | | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN); 6 | 7 | GraphicBufferEx::GraphicBufferEx( 8 | EGLDisplay eglDisplay, EGLContext eglContext) 9 | { 10 | mEGLDisplay = eglDisplay; 11 | mEGLContext = eglContext; 12 | } 13 | 14 | int GraphicBufferEx::getWidth() 15 | { 16 | AHardwareBuffer_Desc outDesc; 17 | AHardwareBuffer_describe(mHardwareBuffer, &outDesc); 18 | return outDesc.width; 19 | } 20 | 21 | int GraphicBufferEx::getHeight() 22 | { 23 | AHardwareBuffer_Desc outDesc; 24 | AHardwareBuffer_describe(mHardwareBuffer, &outDesc); 25 | return outDesc.height; 26 | } 27 | 28 | int GraphicBufferEx::getStride() 29 | { 30 | AHardwareBuffer_Desc outDesc; 31 | AHardwareBuffer_describe(mHardwareBuffer, &outDesc); 32 | return outDesc.stride; 33 | } 34 | 35 | int GraphicBufferEx::getFormat() 36 | { 37 | AHardwareBuffer_Desc outDesc; 38 | AHardwareBuffer_describe(mHardwareBuffer, &outDesc); 39 | return outDesc.format; 40 | } 41 | 42 | void GraphicBufferEx::create(int width, int height, 43 | int textureId, int format) 44 | { 45 | //format 46 | //RGBA_8888 1 47 | //RGB_888 3 48 | //A_8 8 49 | //HAL_PIXEL_FORMAT_YCrCb_420_SP 17 50 | //HAL_PIXEL_FORMAT_YV12 51 | AHardwareBuffer_Desc buffDesc; 52 | buffDesc.width = width; 53 | buffDesc.height = height; 54 | buffDesc.layers = 1; 55 | buffDesc.format = format; 56 | buffDesc.usage = USAGE; 57 | buffDesc.stride = width; 58 | buffDesc.rfu0 = 0; 59 | buffDesc.rfu1 = 0; 60 | 61 | int err = AHardwareBuffer_allocate(&buffDesc, &mHardwareBuffer); 62 | 63 | if (0 != err)//NO_ERROR 64 | { 65 | LOGE("GraphicBufferEx HardwareBuffer create error. (NO_ERROR != err)"); 66 | return; 67 | } 68 | else { 69 | LOGI("AHardwareBuffer_allocate %p", mHardwareBuffer); 70 | } 71 | 72 | EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(mHardwareBuffer); 73 | checkEglError("eglGetNativeClientBufferANDROID"); 74 | mEGLImageKHR = eglCreateImageKHR( 75 | mEGLDisplay, mEGLContext, 76 | EGL_NATIVE_BUFFER_ANDROID, clientBuffer, 0); 77 | checkEglError("eglCreateImageKHR"); 78 | 79 | if (EGL_NO_IMAGE_KHR == mEGLImageKHR) 80 | { 81 | LOGE("GraphicBufferEx create error. (EGL_NO_IMAGE_KHR == mEGLImageKHR)"); 82 | return; 83 | } 84 | 85 | glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); 86 | checkGlError("glBindTexture"); 87 | glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)mEGLImageKHR); 88 | checkGlError("glEGLImageTargetTexture2DOES"); 89 | glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 90 | checkGlError("glTexParameteri"); 91 | glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 92 | checkGlError("glTexParameteri"); 93 | glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); 94 | } 95 | 96 | void GraphicBufferEx::destroy() 97 | { 98 | AHardwareBuffer_release(mHardwareBuffer); 99 | eglDestroyImageKHR(mEGLDisplay, mEGLImageKHR); 100 | } 101 | 102 | void GraphicBufferEx::setBuffer(GPUIPBuffer *srcBuffer) 103 | { 104 | uint8_t *pDstBuffer = NULL; 105 | 106 | if (NULL == srcBuffer) 107 | { 108 | LOGE("GraphicBufferEx setBuffer (NULL == srcBuffer)\n"); 109 | return; 110 | } 111 | 112 | int err = AHardwareBuffer_lock(mHardwareBuffer, USAGE, -1, NULL, (void**)(&pDstBuffer)); 113 | 114 | if (0 != err)//NO_ERROR 115 | { 116 | LOGE("GraphicBufferEx setBuffer AHardwareBuffer_lock failed. err = %d\n", err); 117 | return; 118 | } 119 | 120 | GPUIPBuffer dstBuffer; 121 | 122 | dstBuffer.width = getWidth(); 123 | dstBuffer.height = getHeight(); 124 | dstBuffer.format = getFormat(); 125 | dstBuffer.stride = getStride(); 126 | dstBuffer.pY = pDstBuffer; 127 | dstBuffer.pU = pDstBuffer + dstBuffer.stride * dstBuffer.height; 128 | dstBuffer.pV = dstBuffer.pU; 129 | 130 | switch(getFormat()) 131 | { 132 | case 1://RGBA_8888 133 | { 134 | GPUIPBuffer_RGBA_COPY(srcBuffer, &dstBuffer); 135 | break; 136 | } 137 | 138 | case 3://RGB_888 139 | { 140 | GPUIPBuffer_RGB_COPY(srcBuffer, &dstBuffer); 141 | break; 142 | } 143 | 144 | case 17://HAL_PIXEL_FORMAT_YCrCb_420_SP 145 | { 146 | GPUIPBuffer_NV21_COPY(srcBuffer, &dstBuffer); 147 | break; 148 | } 149 | 150 | default: 151 | { 152 | LOGE("GraphicBufferEx setBuffer do not surpport format = %d.\n", getFormat()); 153 | } 154 | } 155 | 156 | int fence = -1; 157 | err = AHardwareBuffer_unlock(mHardwareBuffer, &fence); 158 | 159 | if (0 != err)//NO_ERROR 160 | { 161 | LOGE("GraphicBufferEx setBuffer AHardwareBuffer_lock failed. err = %d\n", err); 162 | return; 163 | } 164 | } 165 | 166 | void GraphicBufferEx::getBuffer( 167 | GBDataCallBackFun pCallBackFun, GPUIPBuffer *dstBuffer) 168 | { 169 | uint8_t *pSrcBuffer = NULL; 170 | 171 | if ((NULL == pCallBackFun) || (NULL == dstBuffer)) 172 | { 173 | LOGE("GraphicBufferEx getBuffer ((NULL == pCallBackFun) || (NULL == dstBuffer))\n"); 174 | return; 175 | } 176 | 177 | int err = AHardwareBuffer_lock(mHardwareBuffer, USAGE, -1, NULL, (void**)(&pSrcBuffer)); 178 | 179 | if (0 != err)//NO_ERROR 180 | { 181 | LOGE("GraphicBufferEx getBuffer AHardwareBuffer_lock failed. err = %d\n", err); 182 | return; 183 | } 184 | 185 | GPUIPBuffer srcBuffer; 186 | 187 | srcBuffer.width = getWidth(); 188 | srcBuffer.height = getHeight(); 189 | srcBuffer.format = getFormat(); 190 | srcBuffer.stride = getStride(); 191 | srcBuffer.pY = pSrcBuffer; 192 | srcBuffer.pU = pSrcBuffer + srcBuffer.stride * srcBuffer.height; 193 | srcBuffer.pV = srcBuffer.pU; 194 | pCallBackFun(&srcBuffer, dstBuffer); 195 | 196 | int fence = -1; 197 | err = AHardwareBuffer_unlock(mHardwareBuffer, &fence); 198 | 199 | if (0 != err)//NO_ERROR 200 | { 201 | LOGE("GraphicBufferEx getBuffer AHardwareBuffer_unlock failed. err = %d\n", err); 202 | return; 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /app/src/main/jni/GraphicBufferEx.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAHIC_BUFFER_EX_H 2 | #define GRAHIC_BUFFER_EX_H 3 | #include "GPUIPCommon.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef void (*GBDataCallBackFun)(\ 15 | GPUIPBuffer *srcBuffer, GPUIPBuffer *dstBuffer); 16 | 17 | class GraphicBufferEx { 18 | private: 19 | EGLDisplay mEGLDisplay; 20 | EGLContext mEGLContext; 21 | EGLImageKHR mEGLImageKHR; 22 | AHardwareBuffer *mHardwareBuffer; 23 | 24 | public: 25 | GraphicBufferEx( 26 | EGLDisplay eglDisplay, EGLContext eglContext); 27 | int getWidth(); 28 | int getHeight(); 29 | int getStride(); 30 | int getFormat(); 31 | void create(int width, int height, 32 | int textureId, int format); 33 | void destroy(); 34 | void setBuffer(GPUIPBuffer *Buffer); 35 | void getBuffer( 36 | GBDataCallBackFun pCallBackFun, GPUIPBuffer *dstBuffer); 37 | }; 38 | #endif 39 | -------------------------------------------------------------------------------- /app/src/main/jni/NubiaGLCopy.cpp: -------------------------------------------------------------------------------- 1 | #include "NubiaGLCopy.h" 2 | #include "GraphicBufferEx.h" 3 | #include "Utils.h" 4 | 5 | 6 | JNIEXPORT jlong JNICALL 7 | Java_com_example_copygpu_GLCopyJni_initHardwareBuffer( 8 | JNIEnv*env, jclass type, jint width, jint height, jint textureId) 9 | { 10 | GraphicBufferEx* graphicBufferEx = new GraphicBufferEx(eglGetCurrentDisplay(), EGL_NO_CONTEXT); 11 | int format = 17; //HAL_PIXEL_FORMAT_YCrCb_420_SP 12 | graphicBufferEx->create(width, height, textureId, format); 13 | return (jlong)graphicBufferEx; 14 | } 15 | 16 | JNIEXPORT void JNICALL 17 | Java_com_example_copygpu_GLCopyJni_releaseHardwareBuffer( 18 | JNIEnv*env, jclass type, jlong handler) 19 | { 20 | GraphicBufferEx* graphicBufferEx = (GraphicBufferEx*)handler; 21 | graphicBufferEx->destroy(); 22 | delete graphicBufferEx; 23 | } 24 | 25 | JNIEXPORT jbyteArray JNICALL 26 | Java_com_example_copygpu_GLCopyJni_getBuffer( 27 | JNIEnv*env, jclass type, jlong handler) 28 | { 29 | GraphicBufferEx* graphicBufferEx = (GraphicBufferEx*)handler; 30 | jbyteArray jYuvArray = env->NewByteArray(graphicBufferEx->getWidth()*graphicBufferEx->getHeight()*3/2); 31 | jbyte* yuvArray = env->GetByteArrayElements(jYuvArray, NULL); 32 | GPUIPBuffer buffer; 33 | buffer.width = graphicBufferEx->getWidth(); 34 | buffer.height = graphicBufferEx->getHeight(); 35 | buffer.format = graphicBufferEx->getFormat(); 36 | buffer.stride = buffer.width; 37 | buffer.length = buffer.stride * buffer.height * 3 / 2; 38 | buffer.pY = yuvArray; 39 | buffer.pU = yuvArray + buffer.stride * buffer.height; 40 | buffer.pV = buffer.pU; 41 | 42 | graphicBufferEx->getBuffer(GPUIPBuffer_NV21_COPY, &buffer); 43 | //LOGI("dump yuv"); 44 | //dump("/sdcard/123.yuv", buffer.pY, buffer.length); 45 | env->ReleaseByteArrayElements(jYuvArray, yuvArray, 0); 46 | return jYuvArray; 47 | } 48 | 49 | JNIEXPORT void JNICALL 50 | Java_com_example_copygpu_GLCopyJni_setBuffer( 51 | JNIEnv*env, jclass type, jlong handler, jbyteArray jbuffer) 52 | { 53 | GraphicBufferEx* graphicBufferEx = (GraphicBufferEx*)handler; 54 | jbyte* buffer = env->GetByteArrayElements(jbuffer, NULL); 55 | GPUIPBuffer inputBuffer; 56 | inputBuffer.width = graphicBufferEx->getWidth(); 57 | inputBuffer.height = graphicBufferEx->getHeight(); 58 | inputBuffer.format = 17; //HAL_PIXEL_FORMAT_YCrCb_420_SP 59 | inputBuffer.stride = inputBuffer.width; 60 | inputBuffer.length = inputBuffer.stride * inputBuffer.height * 3 / 2; 61 | inputBuffer.pY = buffer; 62 | inputBuffer.pU = buffer + inputBuffer.stride * inputBuffer.height; 63 | inputBuffer.pV = inputBuffer.pU; 64 | graphicBufferEx->setBuffer(&inputBuffer); 65 | env->ReleaseByteArrayElements(jbuffer, buffer, 0); 66 | } -------------------------------------------------------------------------------- /app/src/main/jni/NubiaGLCopy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Author : chenguoting on 2018-8-1 18:38 3 | // Email : chen.guoting@nubia.com 4 | // Company : NUBIA TECHNOLOGY CO., LTD. 5 | // 6 | 7 | #ifndef NEWCAMERA_NUBIAGLCOPY_H 8 | #define NEWCAMERA_NUBIAGLCOPY_H 9 | #include 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | JNIEXPORT jlong JNICALL 15 | Java_com_example_copygpu_GLCopyJni_initHardwareBuffer( 16 | JNIEnv*env, jclass type, jint, jint, jint); 17 | 18 | JNIEXPORT void JNICALL 19 | Java_com_example_copygpu_GLCopyJni_releaseHardwareBuffer( 20 | JNIEnv*env, jclass type, jlong handler); 21 | 22 | JNIEXPORT jbyteArray JNICALL 23 | Java_com_example_copygpu_GLCopyJni_getBuffer( 24 | JNIEnv*env, jclass type, jlong handler); 25 | 26 | JNIEXPORT void JNICALL 27 | Java_com_example_copygpu_GLCopyJni_setBuffer( 28 | JNIEnv*env, jclass type, jlong handler, jbyteArray); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | #endif //NEWCAMERA_NUBIAGLCOPY_H 34 | -------------------------------------------------------------------------------- /app/src/main/jni/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "GPUIPCommon.h" 2 | #include 3 | #include 4 | #include "Utils.h" 5 | 6 | void printGLString(const char *name, GLenum s) 7 | { 8 | const char *str = (const char *) glGetString(s); 9 | LOGI("GL %s = %s\n", name, str); 10 | return; 11 | } 12 | 13 | void checkGlError(const char* op) 14 | { 15 | for (GLint error = glGetError(); error; error = glGetError()) 16 | { 17 | LOGE("after %s() glError (0x%x)\n", op, error); 18 | } 19 | 20 | return; 21 | } 22 | 23 | void checkEglError(const char* op) { 24 | GLint error = eglGetError(); 25 | if(error != EGL_SUCCESS) { 26 | LOGE("after %s() eglError (0x%x)\n", op, error); 27 | } 28 | return; 29 | } 30 | 31 | void printOpenGLInfo() 32 | { 33 | printGLString("Version", GL_VERSION); 34 | printGLString("Vendor", GL_VENDOR); 35 | printGLString("Renderer", GL_RENDERER); 36 | printGLString("Extensions", GL_EXTENSIONS); 37 | return; 38 | } 39 | 40 | float calcAngle(float x, float y) 41 | { 42 | if (x == 0.0f) 43 | { 44 | if (y > 0.0f) 45 | { 46 | return 90.0f; 47 | } 48 | else 49 | { 50 | return 270.0f; 51 | } 52 | } 53 | 54 | float tana = y / x; 55 | float angle = atan(tana) * 180.0f / PI; 56 | 57 | if (x < 0.0f) 58 | { 59 | angle += 180.0f; 60 | } 61 | 62 | if (angle < 0.0f) 63 | { 64 | angle += 360.0f; 65 | } 66 | else if (angle > 360.0f) 67 | { 68 | angle -= 360.0f; 69 | } 70 | 71 | return angle; 72 | } 73 | 74 | 75 | float calcAngleByVec2(float *a, float *b) 76 | { 77 | float aLength = sqrt(a[0] * a[0] + a[1] * a[1]); 78 | float bLength = sqrt(b[0] * b[0] + b[1] * b[1]); 79 | 80 | float cosa = (a[0] * b[0] + a[1] * b[1]) / (aLength * bLength); 81 | return acos(cosa) * 180.0f / PI; 82 | } 83 | 84 | float calcAngleByVec3(float *a, float *b) 85 | { 86 | float aLength = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); 87 | float bLength = sqrt(b[0] * b[0] + b[1] * b[1] + b[2] * b[2]); 88 | 89 | float cosa = (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (aLength * bLength); 90 | return acos(cosa) * 180.0f / PI; 91 | } 92 | 93 | void depth2Bump(int width, int height, 94 | const uint8_t *pDepthBuffer, uint32_t *pBumpBuffer, 95 | float param1, float param2) 96 | { 97 | int i, j; 98 | int value, valueUp, valueRight; 99 | int vecInt[3]; 100 | float vec[3], vecUp[3], vecRight[3]; 101 | float module; 102 | 103 | vecUp[0] = 1.0f; 104 | vecUp[1] = 0.0f; 105 | vecRight[0] = 0.0f; 106 | vecRight[1] = 1.0f; 107 | 108 | for (j = 0; j < height; j++) 109 | { 110 | for (i = 0; i < width; i++) 111 | { 112 | value = pDepthBuffer[j * width + i]; 113 | 114 | if ((j == 0) || (i == width - 1)) 115 | { 116 | pBumpBuffer[j * width + i] = 0x00ff8080 | (value << 24); 117 | continue; 118 | } 119 | 120 | valueUp = pDepthBuffer[(j - 1) * width + i]; 121 | valueRight = pDepthBuffer[j * width + (i + 1)]; 122 | 123 | vecUp[2] = (valueUp - value) / 255.0f * param1; 124 | vecRight[2] = (valueRight - value) / 255.0f * param2; 125 | 126 | //cross product and normal 127 | vec[0] = vecUp[1] * vecRight[2] - vecRight[1] * vecUp[2]; 128 | vec[1] = vecUp[2] * vecRight[0] - vecRight[2] * vecUp[0]; 129 | vec[2] = vecUp[0] * vecRight[1] - vecRight[0] * vecUp[1]; 130 | module = sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]); 131 | vec[0] /= module; 132 | vec[1] /= module; 133 | vec[2] /= module; 134 | 135 | vecInt[0] = (int)(vec[0] * 128.0f) + 128; 136 | vecInt[1] = (int)(vec[1] * 128.0f) + 128; 137 | vecInt[2] = (int)(vec[2] * 128.0f) + 128; 138 | vecInt[0] = (vecInt[0] > 255) ? 255 : vecInt[0]; 139 | vecInt[1] = (vecInt[1] > 255) ? 255 : vecInt[1]; 140 | vecInt[2] = (vecInt[2] > 255) ? 255 : vecInt[2]; 141 | //ABGR 142 | //pBumpBuffer[j * width + i] = 0xff000000 | (vecInt[2] << 16) | (vecInt[1] << 8) | vecInt[0]; 143 | pBumpBuffer[j * width + i] = (value << 24) | (vecInt[2] << 16) | (vecInt[1] << 8) | vecInt[0]; 144 | } 145 | } 146 | } 147 | 148 | void dump(const char *pFileName, void *pBufferSrc, int bufferLen) 149 | { 150 | FILE *pFile = fopen(pFileName, "w+"); 151 | 152 | if (pFile != NULL) 153 | { 154 | int countWrited = 0; 155 | int countRemind = bufferLen; 156 | uint8_t *pBufferSrcEx = (uint8_t *)pBufferSrc; 157 | uint8_t *pBuffer = pBufferSrcEx; 158 | 159 | do 160 | { 161 | countWrited += fwrite(pBuffer, 1, countRemind, pFile); 162 | pBuffer = pBufferSrcEx + countWrited; 163 | countRemind = bufferLen - countWrited; 164 | } while(countRemind > 0); 165 | 166 | fclose(pFile); 167 | } 168 | else 169 | { 170 | LOGE("dump open file %s error!", pFileName); 171 | } 172 | } 173 | 174 | void unDump(const char *pFileName, void *pBufferSrc, int bufferLen) 175 | { 176 | FILE *pFile = fopen(pFileName, "r"); 177 | 178 | if (pFile != NULL) 179 | { 180 | int countRead = 0; 181 | int countRemind = bufferLen; 182 | uint8_t *pBufferSrcEx = (uint8_t *)pBufferSrc; 183 | uint8_t *pBuffer = pBufferSrcEx; 184 | 185 | do 186 | { 187 | countRead += fread(pBuffer, 1, countRemind, pFile); 188 | pBuffer = pBufferSrcEx + countRead; 189 | countRemind = bufferLen - countRead; 190 | } while(countRemind > 0); 191 | 192 | fclose(pFile); 193 | } 194 | else 195 | { 196 | LOGI("unDump open file %s error!", pFileName); 197 | } 198 | } 199 | 200 | void Quaternion::setEulerAngle(const EulerAngle &ea) 201 | { 202 | float cr = cos(ea.roll / 57.3f / 2.0f); 203 | float sr = sin(ea.roll / 57.3f / 2.0f); 204 | float cp = cos(ea.pitch / 57.3f / 2.0f); 205 | float sp = sin(ea.pitch / 57.3f / 2.0f); 206 | float cy = cos(ea.yaw / 57.3f / 2.0f); 207 | float sy = sin(ea.yaw / 57.3f / 2.0f); 208 | 209 | w = cr * cp * cy + sr * sp * sy; 210 | x = cr * sp * cy + sr * cp * sy; 211 | y = cr * cp * sy - sr * sp * cy; 212 | z = sr * cp * cy - cr * sp * sy; 213 | } 214 | 215 | void Quaternion::getEulerAngle(EulerAngle &ea) 216 | { 217 | ea.roll = atan2(2.0f * (w * z + x * y) , 1.0f - 2.0f * (z * z + x * x)); 218 | ea.roll *= 57.3f; 219 | ea.pitch = asin(CLAMP(2.0f * (w * x - y * z) , -1.0f , 1.0f)); 220 | ea.pitch *= 57.3f; 221 | ea.yaw = atan2(2.0f * (w * y + z * x) , 1.0f - 2.0f * (x * x + y * y)); 222 | ea.yaw *= 57.3f; 223 | return; 224 | } -------------------------------------------------------------------------------- /app/src/main/jni/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #define CLAMP(x , min , max) ((x) > (max) ? (max) : ((x) < (min) ? (min) : x)) 5 | 6 | void printGLString(const char *name, GLenum s); 7 | void checkGlError(const char* op); 8 | void checkEglError(const char* op); 9 | void printOpenGLInfo(); 10 | float calcAngle(float x, float y); 11 | float calcAngleByVec2(float *a, float *b); 12 | float calcAngleByVec3(float *a, float *b); 13 | void depth2Bump(int width, int height, 14 | const uint8_t *pDepthBuffer, uint32_t *pBumpBuffer, 15 | float param1, float param2); 16 | void dump(const char *pFileName, void *pBufferSrc, int bufferLen); 17 | void unDump(const char *pFileName, void *pBufferSrc, int bufferLen); 18 | 19 | typedef struct { 20 | float yaw; 21 | float pitch; 22 | float roll; 23 | } EulerAngle; 24 | 25 | class Quaternion 26 | { 27 | public: 28 | float x , y , z , w; 29 | 30 | Quaternion(void) : x(0.0f) , y(0.0f) , z(0.0f) , w(1.0f) {} 31 | ~Quaternion(void) {} 32 | void setEulerAngle(const EulerAngle& ea); 33 | void getEulerAngle(EulerAngle& ea); 34 | }; 35 | #endif -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenguoting/hardwareBuffer/1db3d2ae3267f2250f78ad8beee4cc7e23142c1e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/raw/texture_2d_fragment_shader.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | in vec2 vTextureCoord; 4 | uniform sampler2D uTextureSampler; 5 | 6 | out vec4 gl_FragColor; 7 | 8 | void main() { 9 | gl_FragColor = texture(uTextureSampler, vTextureCoord); 10 | } -------------------------------------------------------------------------------- /app/src/main/res/raw/texture_oes2oes_fragment_shader.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | #extension GL_OES_EGL_image_external_essl3 : require 3 | #extension GL_EXT_YUV_target : require 4 | 5 | in vec2 vTextureCoord; 6 | uniform samplerExternalOES uTextureSampler; 7 | 8 | layout(yuv) out vec4 gl_FragColor; 9 | 10 | void main() { 11 | gl_FragColor = texture(uTextureSampler, vTextureCoord); 12 | } -------------------------------------------------------------------------------- /app/src/main/res/raw/texture_oes_fragment_shader.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | #extension GL_OES_EGL_image_external_essl3 : require 3 | 4 | in vec2 vTextureCoord; 5 | uniform samplerExternalOES uTextureSampler; 6 | 7 | out vec4 gl_FragColor; 8 | 9 | void main() { 10 | gl_FragColor = texture(uTextureSampler, vTextureCoord); 11 | } -------------------------------------------------------------------------------- /app/src/main/res/raw/texture_vertex_shader.glsl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | uniform mat4 uMVPMatrix; 4 | uniform mat4 uSTMatrix; 5 | in vec4 aPosition; 6 | in vec4 aTextureCoord; 7 | 8 | out vec2 vTextureCoord; 9 | 10 | void main() { 11 | gl_Position = uMVPMatrix * aPosition; 12 | vTextureCoord = (uSTMatrix * aTextureCoord).st; 13 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CopyGPU 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/test/java/com/example/copygpu/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.copygpu; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------