1 /* 2 * Copyright (C) 2012 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 package android.view.cts; 17 18 import android.graphics.SurfaceTexture; 19 import android.opengl.GLUtils; 20 21 import junit.framework.Assert; 22 23 import java.util.concurrent.Semaphore; 24 import java.util.concurrent.atomic.AtomicBoolean; 25 26 import javax.microedition.khronos.egl.EGL10; 27 import javax.microedition.khronos.egl.EGLConfig; 28 import javax.microedition.khronos.egl.EGLContext; 29 import javax.microedition.khronos.egl.EGLDisplay; 30 import javax.microedition.khronos.egl.EGLSurface; 31 32 public class GLProducerThread extends Thread { 33 private final int mFrames; 34 private final int mDelayMs; 35 private final Semaphore mSemaphore; 36 private final SurfaceTexture mSurfaceTexture; 37 private final AtomicBoolean mShouldRender; 38 private final GLRenderer mRenderer; 39 40 private EGL10 mEgl; 41 private EGLDisplay mEglDisplay = EGL10.EGL_NO_DISPLAY; 42 private EGLContext mEglContext = EGL10.EGL_NO_CONTEXT; 43 private EGLSurface mEglSurface = EGL10.EGL_NO_SURFACE; 44 45 private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 46 private static final int EGL_OPENGL_ES2_BIT = 4; 47 48 public interface GLRenderer { 49 void drawFrame(int frame); 50 } 51 52 private GLProducerThread(SurfaceTexture surfaceTexture, GLRenderer renderer, 53 AtomicBoolean shouldRender, 54 int frames, int delayMs, Semaphore semaphore) { 55 mShouldRender = shouldRender; 56 mFrames = frames; 57 mDelayMs = delayMs; 58 mSemaphore = semaphore; 59 mSurfaceTexture = surfaceTexture; 60 mRenderer = renderer; 61 } 62 63 GLProducerThread(SurfaceTexture surfaceTexture, GLRenderer renderer, int frames, int delayMs, 64 Semaphore semaphore) { 65 this(surfaceTexture, renderer, null, frames, delayMs, semaphore); 66 } 67 68 GLProducerThread(SurfaceTexture surfaceTexture, GLRenderer renderer, AtomicBoolean shouldRender, 69 int delayMs, Semaphore semaphore) { 70 this(surfaceTexture, renderer, shouldRender, 0, delayMs, semaphore); 71 } 72 73 private void initGL() { 74 mEgl = (EGL10) EGLContext.getEGL(); 75 76 mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 77 if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 78 throw new RuntimeException("eglGetDisplay() failed " 79 + GLUtils.getEGLErrorString(mEgl.eglGetError())); 80 } 81 82 int[] version = new int[2]; 83 if (!mEgl.eglInitialize(mEglDisplay, version)) { 84 throw new RuntimeException("eglInitialize() failed " 85 + GLUtils.getEGLErrorString(mEgl.eglGetError())); 86 } 87 88 int[] configAttribs = { 89 EGL10.EGL_BUFFER_SIZE, 32, 90 EGL10.EGL_ALPHA_SIZE, 8, 91 EGL10.EGL_BLUE_SIZE, 8, 92 EGL10.EGL_GREEN_SIZE, 8, 93 EGL10.EGL_RED_SIZE, 8, 94 EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 95 EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, 96 EGL10.EGL_NONE 97 }; 98 99 int[] numConfigs = new int[1]; 100 EGLConfig[] configs = new EGLConfig[1]; 101 if (!mEgl.eglChooseConfig(mEglDisplay, configAttribs, configs, 1, numConfigs) 102 || numConfigs[0] == 0) { 103 throw new RuntimeException("eglChooseConfig() failed"); 104 } 105 106 int[] contextAttribs = { 107 EGL_CONTEXT_CLIENT_VERSION, 2, 108 EGL10.EGL_NONE }; 109 110 mEglContext = mEgl.eglCreateContext(mEglDisplay, 111 configs[0], EGL10.EGL_NO_CONTEXT, contextAttribs); 112 113 mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, 114 configs[0], mSurfaceTexture, null); 115 116 if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 117 int error = mEgl.eglGetError(); 118 if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 119 throw new RuntimeException( 120 "eglCreateWindowSurface() returned EGL_BAD_NATIVE_WINDOW."); 121 } 122 throw new RuntimeException("eglCreateWindowSurface() failed " 123 + GLUtils.getEGLErrorString(error)); 124 } 125 126 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 127 throw new RuntimeException("eglMakeCurrent() failed " 128 + GLUtils.getEGLErrorString(mEgl.eglGetError())); 129 } 130 } 131 132 private void destroyGL() { 133 mEgl.eglMakeCurrent(mEglDisplay, 134 EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 135 mEgl.eglDestroyContext(mEglDisplay, mEglContext); 136 mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 137 mEglContext = EGL10.EGL_NO_CONTEXT; 138 mEglSurface = EGL10.EGL_NO_SURFACE; 139 } 140 141 @Override 142 public void run() { 143 initGL(); 144 145 int frame = 0; 146 while (frame < mFrames || (mShouldRender != null && mShouldRender.get())) { 147 if (mRenderer != null) { 148 mRenderer.drawFrame(frame); 149 } 150 mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); 151 Assert.assertEquals(EGL10.EGL_SUCCESS, mEgl.eglGetError()); 152 try { 153 sleep(mDelayMs); 154 } catch (InterruptedException e) { 155 } 156 frame++; 157 } 158 159 mSemaphore.release(); 160 destroyGL(); 161 } 162 } 163