GLTextureViewActivity.java revision 8f0095cd33558e9cc8a440047908e53b68906f5f
1/* 2 * Copyright (C) 2011 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 17package com.android.test.hwui; 18 19import android.animation.ObjectAnimator; 20import android.animation.ValueAnimator; 21import android.app.Activity; 22import android.graphics.SurfaceTexture; 23import android.opengl.GLES20; 24import android.os.Bundle; 25import android.util.Log; 26import android.view.Gravity; 27import android.view.TextureView; 28import android.view.View; 29import android.widget.FrameLayout; 30 31import javax.microedition.khronos.egl.EGL10; 32import javax.microedition.khronos.egl.EGL11; 33import javax.microedition.khronos.egl.EGLConfig; 34import javax.microedition.khronos.egl.EGLContext; 35import javax.microedition.khronos.egl.EGLDisplay; 36import javax.microedition.khronos.egl.EGLSurface; 37import javax.microedition.khronos.opengles.GL; 38 39@SuppressWarnings({"UnusedDeclaration"}) 40public class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener { 41 private RenderThread mRenderThread; 42 private TextureView mTextureView; 43 44 @Override 45 protected void onCreate(Bundle savedInstanceState) { 46 super.onCreate(savedInstanceState); 47 48 mTextureView = new TextureView(this); 49 mTextureView.setSurfaceTextureListener(this); 50 51 setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER)); 52 } 53 54 @Override 55 protected void onDestroy() { 56 super.onDestroy(); 57 mRenderThread.finish(); 58 } 59 60 @Override 61 public void onSurfaceTextureAvailable(SurfaceTexture surface) { 62 mRenderThread = new RenderThread(surface); 63 mRenderThread.start(); 64 65 mTextureView.setCameraDistance(5000); 66 67 ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); 68 animator.setRepeatMode(ObjectAnimator.REVERSE); 69 animator.setRepeatCount(ObjectAnimator.INFINITE); 70 animator.setDuration(4000); 71 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 72 @Override 73 public void onAnimationUpdate(ValueAnimator animation) { 74 ((View) mTextureView.getParent()).invalidate(); 75 } 76 }); 77 animator.start(); 78 } 79 80 @Override 81 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 82 } 83 84 private static class RenderThread extends Thread { 85 private static final String LOG_TAG = "GLTextureView"; 86 87 static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 88 static final int EGL_SURFACE_TYPE = 0x3033; 89 static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400; 90 static final int EGL_OPENGL_ES2_BIT = 4; 91 92 private volatile boolean mFinished; 93 94 private SurfaceTexture mSurface; 95 96 private EGL10 mEgl; 97 private EGLDisplay mEglDisplay; 98 private EGLConfig mEglConfig; 99 private EGLContext mEglContext; 100 private EGLSurface mEglSurface; 101 private GL mGL; 102 103 RenderThread(SurfaceTexture surface) { 104 mSurface = surface; 105 } 106 107 @Override 108 public void run() { 109 initGL(); 110 111 float red = 0.0f; 112 while (!mFinished) { 113 checkCurrent(); 114 115 GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f); 116 int error = GLES20.glGetError(); 117 if (error != GLES20.GL_NO_ERROR) { 118 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error)); 119 } 120 121 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 122 error = GLES20.glGetError(); 123 if (error != GLES20.GL_NO_ERROR) { 124 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error)); 125 } 126 127 if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 128 throw new RuntimeException("Cannot swap buffers"); 129 } 130 131 try { 132 Thread.sleep(20); 133 } catch (InterruptedException e) { 134 // Ignore 135 } 136 137 red += 0.021f; 138 if (red > 1.0f) red = 0.0f; 139 } 140 141 finishGL(); 142 } 143 144 private void finishGL() { 145 mEgl.eglDestroyContext(mEglDisplay, mEglContext); 146 mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 147 } 148 149 private void checkCurrent() { 150 if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || 151 !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { 152 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 153 throw new RuntimeException("eglMakeCurrent failed " 154 + getEGLErrorString(mEgl.eglGetError())); 155 } 156 } 157 } 158 159 private void initGL() { 160 mEgl = (EGL10) EGLContext.getEGL(); 161 162 mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 163 if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 164 throw new RuntimeException("eglGetDisplay failed " 165 + getEGLErrorString(mEgl.eglGetError())); 166 } 167 168 int[] version = new int[2]; 169 if (!mEgl.eglInitialize(mEglDisplay, version)) { 170 throw new RuntimeException("eglInitialize failed " + 171 getEGLErrorString(mEgl.eglGetError())); 172 } 173 174 mEglConfig = chooseEglConfig(); 175 if (mEglConfig == null) { 176 throw new RuntimeException("eglConfig not initialized"); 177 } 178 179 mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); 180 181 mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null); 182 183 if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 184 int error = mEgl.eglGetError(); 185 if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 186 Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 187 return; 188 } 189 throw new RuntimeException("createWindowSurface failed " 190 + getEGLErrorString(error)); 191 } 192 193 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 194 throw new RuntimeException("eglMakeCurrent failed " 195 + getEGLErrorString(mEgl.eglGetError())); 196 } 197 198 mGL = mEglContext.getGL(); 199 } 200 201 202 EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 203 int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 204 return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); 205 } 206 207 private EGLConfig chooseEglConfig() { 208 int[] configsCount = new int[1]; 209 EGLConfig[] configs = new EGLConfig[1]; 210 int[] configSpec = getConfig(); 211 if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { 212 throw new IllegalArgumentException("eglChooseConfig failed " + 213 getEGLErrorString(mEgl.eglGetError())); 214 } else if (configsCount[0] > 0) { 215 return configs[0]; 216 } 217 return null; 218 } 219 220 private int[] getConfig() { 221 return new int[] { 222 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 223 EGL10.EGL_RED_SIZE, 8, 224 EGL10.EGL_GREEN_SIZE, 8, 225 EGL10.EGL_BLUE_SIZE, 8, 226 EGL10.EGL_ALPHA_SIZE, 8, 227 EGL10.EGL_DEPTH_SIZE, 0, 228 EGL10.EGL_STENCIL_SIZE, 0, 229 EGL10.EGL_NONE 230 }; 231 } 232 233 static String getEGLErrorString(int error) { 234 switch (error) { 235 case EGL10.EGL_SUCCESS: 236 return "EGL_SUCCESS"; 237 case EGL10.EGL_NOT_INITIALIZED: 238 return "EGL_NOT_INITIALIZED"; 239 case EGL10.EGL_BAD_ACCESS: 240 return "EGL_BAD_ACCESS"; 241 case EGL10.EGL_BAD_ALLOC: 242 return "EGL_BAD_ALLOC"; 243 case EGL10.EGL_BAD_ATTRIBUTE: 244 return "EGL_BAD_ATTRIBUTE"; 245 case EGL10.EGL_BAD_CONFIG: 246 return "EGL_BAD_CONFIG"; 247 case EGL10.EGL_BAD_CONTEXT: 248 return "EGL_BAD_CONTEXT"; 249 case EGL10.EGL_BAD_CURRENT_SURFACE: 250 return "EGL_BAD_CURRENT_SURFACE"; 251 case EGL10.EGL_BAD_DISPLAY: 252 return "EGL_BAD_DISPLAY"; 253 case EGL10.EGL_BAD_MATCH: 254 return "EGL_BAD_MATCH"; 255 case EGL10.EGL_BAD_NATIVE_PIXMAP: 256 return "EGL_BAD_NATIVE_PIXMAP"; 257 case EGL10.EGL_BAD_NATIVE_WINDOW: 258 return "EGL_BAD_NATIVE_WINDOW"; 259 case EGL10.EGL_BAD_PARAMETER: 260 return "EGL_BAD_PARAMETER"; 261 case EGL10.EGL_BAD_SURFACE: 262 return "EGL_BAD_SURFACE"; 263 case EGL11.EGL_CONTEXT_LOST: 264 return "EGL_CONTEXT_LOST"; 265 default: 266 return "0x" + Integer.toHexString(error); 267 } 268 } 269 270 void finish() { 271 mFinished = true; 272 } 273 } 274} 275