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 onCreate(Bundle savedInstanceState)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 stopGlThread()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 onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)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 onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)201 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 202 Log.d(LOG_TAG, "onSurfaceTextureSizeChanged"); 203 } 204 205 @Override onSurfaceTextureDestroyed(SurfaceTexture surface)206 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 207 Log.d(LOG_TAG, "onSurfaceTextureDestroyed"); 208 stopGlThread(); 209 return true; 210 } 211 212 @Override onSurfaceTextureUpdated(SurfaceTexture surface)213 public void onSurfaceTextureUpdated(SurfaceTexture surface) { 214 Log.d(LOG_TAG, "onSurfaceTextureUpdated"); 215 mPreview.setVisibility(View.GONE); 216 } 217 } 218