Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.test.hwui;
     18 
     19 import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
     20 import static android.opengl.GLES20.glClear;
     21 import static android.opengl.GLES20.glClearColor;
     22 
     23 import android.app.Activity;
     24 import android.graphics.Color;
     25 import android.graphics.SurfaceTexture;
     26 import android.opengl.GLUtils;
     27 import android.os.Bundle;
     28 import android.util.Log;
     29 import android.view.TextureView;
     30 import android.view.TextureView.SurfaceTextureListener;
     31 import android.view.View;
     32 import android.view.ViewGroup.LayoutParams;
     33 import android.widget.FrameLayout;
     34 import android.widget.TextView;
     35 
     36 import javax.microedition.khronos.egl.EGL10;
     37 import javax.microedition.khronos.egl.EGLConfig;
     38 import javax.microedition.khronos.egl.EGLContext;
     39 import javax.microedition.khronos.egl.EGLDisplay;
     40 import javax.microedition.khronos.egl.EGLSurface;
     41 
     42 public class SingleFrameTextureViewTestActivity extends Activity implements SurfaceTextureListener {
     43     private static final String LOG_TAG = "SingleFrameTest";
     44 
     45     private View mPreview;
     46     private TextureView mTextureView;
     47     private Thread mGLThread;
     48 
     49     @Override
     50     protected void onCreate(Bundle savedInstanceState) {
     51         super.onCreate(savedInstanceState);
     52         TextView preview = new TextView(this);
     53         preview.setText("This is a preview");
     54         preview.setBackgroundColor(Color.WHITE);
     55         mPreview = preview;
     56         mTextureView = new TextureView(this);
     57         mTextureView.setSurfaceTextureListener(this);
     58 
     59         FrameLayout content = new FrameLayout(this);
     60         content.addView(mTextureView,
     61                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
     62         content.addView(mPreview,
     63                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
     64 
     65         setContentView(content);
     66     }
     67 
     68     private void stopGlThread() {
     69         if (mGLThread != null) {
     70             try {
     71                 mGLThread.join();
     72                 mGLThread = null;
     73             } catch (InterruptedException e) { }
     74         }
     75     }
     76 
     77     @Override
     78     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
     79         Log.d(LOG_TAG, "onSurfaceAvailable");
     80         mGLThread = new Thread() {
     81             static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
     82             static final int EGL_OPENGL_ES2_BIT = 4;
     83 
     84             private EGL10 mEgl;
     85             private EGLDisplay mEglDisplay;
     86             private EGLConfig mEglConfig;
     87             private EGLContext mEglContext;
     88             private EGLSurface mEglSurface;
     89 
     90             @Override
     91             public void run() {
     92                 initGL();
     93                 try {
     94                     Thread.sleep(500);
     95                 } catch (InterruptedException e) {}
     96 
     97                 for (int i = 0; i < 2; i++) {
     98                     if (i == 0) {
     99                         glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    100                     } else {
    101                         glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    102                     }
    103                     glClear(GL_COLOR_BUFFER_BIT);
    104                     Log.d(LOG_TAG, "eglSwapBuffers");
    105                     if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
    106                         throw new RuntimeException("Cannot swap buffers");
    107                     }
    108                     try {
    109                         Thread.sleep(50);
    110                     } catch (InterruptedException e) {}
    111                 }
    112 
    113                 try {
    114                     Thread.sleep(500);
    115                 } catch (InterruptedException e) {}
    116 
    117                 finishGL();
    118             }
    119 
    120             private void finishGL() {
    121                 mEgl.eglDestroyContext(mEglDisplay, mEglContext);
    122                 mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
    123             }
    124 
    125             private void initGL() {
    126                 mEgl = (EGL10) EGLContext.getEGL();
    127 
    128                 mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    129                 if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
    130                     throw new RuntimeException("eglGetDisplay failed "
    131                             + GLUtils.getEGLErrorString(mEgl.eglGetError()));
    132                 }
    133 
    134                 int[] version = new int[2];
    135                 if (!mEgl.eglInitialize(mEglDisplay, version)) {
    136                     throw new RuntimeException("eglInitialize failed " +
    137                             GLUtils.getEGLErrorString(mEgl.eglGetError()));
    138                 }
    139 
    140                 mEglConfig = chooseEglConfig();
    141                 if (mEglConfig == null) {
    142                     throw new RuntimeException("eglConfig not initialized");
    143                 }
    144 
    145                 mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
    146 
    147                 mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null);
    148 
    149                 if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
    150                     int error = mEgl.eglGetError();
    151                     if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
    152                         Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
    153                         return;
    154                     }
    155                     throw new RuntimeException("createWindowSurface failed "
    156                             + GLUtils.getEGLErrorString(error));
    157                 }
    158 
    159                 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
    160                     throw new RuntimeException("eglMakeCurrent failed "
    161                             + GLUtils.getEGLErrorString(mEgl.eglGetError()));
    162                 }
    163             }
    164 
    165 
    166             EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
    167                 int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
    168                 return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
    169             }
    170 
    171             private EGLConfig chooseEglConfig() {
    172                 int[] configsCount = new int[1];
    173                 EGLConfig[] configs = new EGLConfig[1];
    174                 int[] configSpec = getConfig();
    175                 if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
    176                     throw new IllegalArgumentException("eglChooseConfig failed " +
    177                             GLUtils.getEGLErrorString(mEgl.eglGetError()));
    178                 } else if (configsCount[0] > 0) {
    179                     return configs[0];
    180                 }
    181                 return null;
    182             }
    183 
    184             private int[] getConfig() {
    185                 return new int[] {
    186                         EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    187                         EGL10.EGL_RED_SIZE, 8,
    188                         EGL10.EGL_GREEN_SIZE, 8,
    189                         EGL10.EGL_BLUE_SIZE, 8,
    190                         EGL10.EGL_ALPHA_SIZE, 8,
    191                         EGL10.EGL_DEPTH_SIZE, 0,
    192                         EGL10.EGL_STENCIL_SIZE, 0,
    193                         EGL10.EGL_NONE
    194                 };
    195             }
    196         };
    197         mGLThread.start();
    198     }
    199 
    200     @Override
    201     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    202         Log.d(LOG_TAG, "onSurfaceTextureSizeChanged");
    203     }
    204 
    205     @Override
    206     public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    207         Log.d(LOG_TAG, "onSurfaceTextureDestroyed");
    208         stopGlThread();
    209         return true;
    210     }
    211 
    212     @Override
    213     public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    214         Log.d(LOG_TAG, "onSurfaceTextureUpdated");
    215         mPreview.setVisibility(View.GONE);
    216     }
    217 }
    218