第三章 TextureView

      在〈第三章 TextureView〉中尚無留言

TextureView

在TextureView裏也可以使用OpenGL來繪制. 其原理其實很簡單, 就是把TextureView裏面的SurfaceTexture傳給OpenGL, 然後於此SurfaceTexture進行繪制. 畫完後再使用 mEgl.eglSwapBuffers(mEglDisplay, mEglSurface) 將surfaceTexture送回TextureView中顯示

TextureView沒有自己的執行緒, 所以需要在onSurfaceTextureAvailable中啟動Rendder執行緒. 而onSurfaceTextureUpdate, 每秒會更新約60次左右

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener{
    TextureView textureView;
    Thread thread;
    int count=0;
    long t1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textureView=(TextureView)findViewById(R.id.textureView);
        textureView.setSurfaceTextureListener(this);
    }
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
        Log.d("Thomas", "available");
        thread=new MyRenderer(this, surfaceTexture);
    }
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
        Log.d("Thomas", "Changed");
    }
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return false;
    }
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
        count++;
        long now = System.currentTimeMillis();
        if (now - t1 >= 1000) {
            t1 = now;
            Log.d("Thomas", Thread.currentThread().getName() + " : " + count);
            count = 0;
        }
    }
}

Renderer

如同第二章, 需要一個Renderer. 此Renderer需要手動撰寫獨立的執行緒, 並初始化OpenGL.  initGL() 的目的是將TextureView裏的SurfaceTexture與OpenGL的mEglSurface進行連結, 然後在於surfaceTexture開始繪制三角型. 當surfaceTexture繪制完成後, 使用 mEgl.eglSwapBuffers(mEglDisplay, mEglSurface) 將surfaceTexture送到mEglDisplay, 如此TextureView就可以看到圖型了

請注意, 需要初始化initGL()後, 才可以產生Triangle物件, 並開始繪圖onDraw(). 迴圈裏若沒有使用Thread.sleep(10), 則會高速執行, 每秒約執行800多次. 但實際送到TextureView的每秒只有60次, 所以可以睡一下節省電量.

public class MyRenderer extends Thread{
    private EGL10 mEgl;
    private EGLDisplay mEglDisplay;
    private EGLConfig mEglConfig;
    private EGLContext mEglContext;
    private EGLSurface mEglSurface;
    Context context;
    SurfaceTexture surfaceTexture;
    Triangle triangle;
    public MyRenderer(Context context, SurfaceTexture surfaceTexture){
        this.context=context;
        this.surfaceTexture=surfaceTexture;
        start();
    }
    public synchronized void run(){
        initGL();
        triangle=new Triangle();
        while(true){
            triangle.onDraw();
            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)){
                throw new RuntimeException("Cannot swap buffers");
            }
            try {
                Thread.sleep(10);//UI的onSurfaceTextureUpdated每秒只會更新60frame左右, 所以睡一下,較省電
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private void initGL() {
        mEgl = (EGL10) EGLContext.getEGL();
        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
        int versions[] = new int[2];
        mEgl.eglInitialize(mEglDisplay, versions);
        int configsCount[] = new int[1];
        EGLConfig configs[] = new EGLConfig[1];
        int configSpec[] = new int[]{
                EGL10.EGL_RENDERABLE_TYPE,
                EGL14.EGL_OPENGL_ES2_BIT,
                EGL10.EGL_RED_SIZE, 8,
                EGL10.EGL_GREEN_SIZE, 8,
                EGL10.EGL_BLUE_SIZE, 8,
                EGL10.EGL_ALPHA_SIZE, 8,
                EGL10.EGL_DEPTH_SIZE, 0,
                EGL10.EGL_STENCIL_SIZE, 0,
                EGL10.EGL_NONE };
        mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount);
        mEglConfig = configs[0];
        int contextSpec[] = new int[]{
                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL10.EGL_NONE };
        mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, contextSpec);
        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceTexture, null);
        mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
    }
}

Triangle

Triangle.java及MyShaderFactory著色器與第二章一模一樣

完整程式碼下載 : OpenGL_TextureView.rar

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *