| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package android.textureview.cts; |
| |
| import android.graphics.SurfaceTexture; |
| import android.opengl.GLUtils; |
| |
| import java.lang.Thread; |
| import java.util.concurrent.Semaphore; |
| |
| import junit.framework.Assert; |
| |
| import javax.microedition.khronos.egl.EGL10; |
| import javax.microedition.khronos.egl.EGLConfig; |
| import javax.microedition.khronos.egl.EGLContext; |
| import javax.microedition.khronos.egl.EGLDisplay; |
| import javax.microedition.khronos.egl.EGLSurface; |
| import javax.microedition.khronos.opengles.GL; |
| |
| import static android.opengl.GLES20.*; |
| |
| public class GLProducerThread extends Thread { |
| private Thread mProducerThread; |
| private final int mFrames; |
| private final int mDelayMs; |
| private final Semaphore mSemaphore; |
| private final SurfaceTexture mSurfaceTexture; |
| |
| private EGL10 mEgl; |
| private EGLDisplay mEglDisplay = EGL10.EGL_NO_DISPLAY; |
| private EGLContext mEglContext = EGL10.EGL_NO_CONTEXT; |
| private EGLSurface mEglSurface = EGL10.EGL_NO_SURFACE; |
| private GL mGl; |
| |
| private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; |
| private static final int EGL_OPENGL_ES2_BIT = 4; |
| |
| GLProducerThread(SurfaceTexture surfaceTexture, int frames, int delayMs, Semaphore semaphore) { |
| mFrames = frames; |
| mDelayMs = delayMs; |
| mSemaphore = semaphore; |
| mSurfaceTexture = surfaceTexture; |
| } |
| |
| private void initGL() { |
| mEgl = (EGL10) EGLContext.getEGL(); |
| |
| mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); |
| if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { |
| throw new RuntimeException("eglGetDisplay() failed " |
| + GLUtils.getEGLErrorString(mEgl.eglGetError())); |
| } |
| |
| int[] version = new int[2]; |
| if (!mEgl.eglInitialize(mEglDisplay, version)) { |
| throw new RuntimeException("eglInitialize() failed " + |
| GLUtils.getEGLErrorString(mEgl.eglGetError())); |
| } |
| |
| int[] configAttribs = { |
| EGL10.EGL_BUFFER_SIZE, 32, |
| EGL10.EGL_ALPHA_SIZE, 8, |
| EGL10.EGL_BLUE_SIZE, 8, |
| EGL10.EGL_GREEN_SIZE, 8, |
| EGL10.EGL_RED_SIZE, 8, |
| EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
| EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, |
| EGL10.EGL_NONE |
| }; |
| |
| int[] numConfigs = new int[1]; |
| EGLConfig[] configs = new EGLConfig[1]; |
| if (!mEgl.eglChooseConfig(mEglDisplay, configAttribs, configs, 1, numConfigs) || numConfigs[0] == 0) { |
| throw new RuntimeException("eglChooseConfig() failed"); |
| } |
| |
| int[] contextAttribs = { |
| EGL_CONTEXT_CLIENT_VERSION, 2, |
| EGL10.EGL_NONE }; |
| |
| mEglContext = mEgl.eglCreateContext(mEglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, contextAttribs); |
| |
| mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, configs[0], mSurfaceTexture, null); |
| |
| if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { |
| int error = mEgl.eglGetError(); |
| if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { |
| throw new RuntimeException("eglCreateWindowSurface() returned EGL_BAD_NATIVE_WINDOW."); |
| } |
| throw new RuntimeException("eglCreateWindowSurface() failed " |
| + GLUtils.getEGLErrorString(error)); |
| } |
| |
| if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { |
| throw new RuntimeException("eglMakeCurrent() failed " |
| + GLUtils.getEGLErrorString(mEgl.eglGetError())); |
| } |
| |
| mGl = mEglContext.getGL(); |
| } |
| |
| void destroyGL() { |
| mEgl.eglDestroyContext(mEglDisplay, mEglContext); |
| mEgl.eglDestroySurface(mEglDisplay, mEglSurface); |
| mEglContext = EGL10.EGL_NO_CONTEXT; |
| mEglSurface = EGL10.EGL_NO_SURFACE; |
| } |
| |
| @Override |
| public void run() { |
| initGL(); |
| final int numColors = 4; |
| final float[][] color = |
| { { 1.0f, 0.0f, 0.0f }, |
| { 0.0f, 1.0f, 0.0f }, |
| { 0.0f, 0.0f, 1.0f }, |
| { 1.0f, 1.0f, 1.0f } }; |
| |
| for (int index = 0, frame = 0; |
| frame < mFrames; index = (index + 1) % numColors, frame++) { |
| glClearColor(color[index][0], color[index][1], color[index][2], 1.0f); |
| glClear(GL_COLOR_BUFFER_BIT); |
| mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); |
| Assert.assertEquals(EGL10.EGL_SUCCESS, mEgl.eglGetError()); |
| try { |
| sleep(mDelayMs); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| mSemaphore.release(); |
| destroyGL(); |
| } |
| } |