111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown/* 211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * Copyright (C) 2012 The Android Open Source Project 311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * 411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * you may not use this file except in compliance with the License. 611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * You may obtain a copy of the License at 711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * 811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * 1011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * Unless required by applicable law or agreed to in writing, software 1111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * See the License for the specific language governing permissions and 1411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * limitations under the License. 1511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown */ 1611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 1711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownpackage com.android.dreams.basic; 1811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 1911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.graphics.Color; 2011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.graphics.SurfaceTexture; 2111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.util.Log; 2211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.view.Choreographer; 23c3441bcb11dc414911dd5681fd01ca1d2dde74d2Leif Hendrik Wildenimport android.view.Surface; 2411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.os.SystemClock; 2511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 2611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport javax.microedition.khronos.egl.EGL10; 2711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport javax.microedition.khronos.egl.EGLConfig; 2811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport javax.microedition.khronos.egl.EGLContext; 2911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport javax.microedition.khronos.egl.EGLDisplay; 3011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport javax.microedition.khronos.egl.EGLSurface; 3111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 3211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.opengl.EGL14; 3311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport android.opengl.GLUtils; 3411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 3511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport java.nio.ByteBuffer; 3611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport java.nio.ByteOrder; 3711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport java.nio.FloatBuffer; 3811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport java.nio.ShortBuffer; 3911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 4011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownimport static android.opengl.GLES20.*; 4111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 4211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown/** 4311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * The OpenGL renderer for the {@link Colors} dream. 4411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * <p> 4511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * This class is single-threaded. Its methods must only be called on the 4611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * rendering thread. 4711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown * </p> 4811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown */ 4911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brownfinal class ColorsGLRenderer implements Choreographer.FrameCallback { 5011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown static final String TAG = ColorsGLRenderer.class.getSimpleName(); 5111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown static final boolean DEBUG = false; 5211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 53a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy private static void LOG(String fmt, Object... args) { 5411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!DEBUG) return; 5511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.v(TAG, String.format(fmt, args)); 5611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 5711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 58c3441bcb11dc414911dd5681fd01ca1d2dde74d2Leif Hendrik Wilden private final Surface mSurface; 5911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int mWidth; 6011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int mHeight; 6111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 6211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final Choreographer mChoreographer; 6311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 6411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private Square mSquare; 6511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private long mLastFrameTime; 6611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int mFrameNum = 0; 6711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 6811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // It's so easy to use OpenGLES 2.0! 6911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private EGL10 mEgl; 7011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private EGLDisplay mEglDisplay; 7111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private EGLContext mEglContext; 7211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private EGLSurface mEglSurface; 7311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 74c3441bcb11dc414911dd5681fd01ca1d2dde74d2Leif Hendrik Wilden public ColorsGLRenderer(Surface surface, int width, int height) { 7511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mSurface = surface; 7611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mWidth = width; 7711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mHeight = height; 7811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 7911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mChoreographer = Choreographer.getInstance(); 8011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 8111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 8211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public void start() { 8311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown initGL(); 8411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mSquare = new Square(); 8511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 8611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mFrameNum = 0; 8711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mChoreographer.postFrameCallback(this); 8811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 8911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 9011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public void stop() { 9111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mChoreographer.removeFrameCallback(this); 9211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 9311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mSquare = null; 9411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown finishGL(); 9511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 9611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 9711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public void setSize(int width, int height) { 9811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mWidth = width; 9911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mHeight = height; 10011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 10111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 10211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown @Override 10311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public void doFrame(long frameTimeNanos) { 10411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mFrameNum += 1; 10511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 10611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Clear on first frame. 10711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (mFrameNum == 1) { 10811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glClearColor(1f, 0f, 0f, 1.0f); 10911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (DEBUG) { 11011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mLastFrameTime = frameTimeNanos; 11111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 11211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 11311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 11411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Draw new frame. 11511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkCurrent(); 11611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 11711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glViewport(0, 0, mWidth, mHeight); 11811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 11911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (DEBUG) { 120a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy final long dt = frameTimeNanos - mLastFrameTime; 12111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final int fps = (int) (1e9f / dt); 12211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (0 == (mFrameNum % 10)) { 12311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown LOG("frame %d fps=%d", mFrameNum, fps); 12411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 12511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (fps < 40) { 12611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown LOG("JANK! (%d ms)", dt); 12711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 128a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy mLastFrameTime = frameTimeNanos; 12911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 13011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 13111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glClear(GL_COLOR_BUFFER_BIT); 13211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 13311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 13411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mSquare.draw(); 13511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 13611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 13711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("Cannot swap buffers"); 13811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 13911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkEglError(); 14011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 14111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Animate. Post callback to run on next vsync. 14211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mChoreographer.postFrameCallback(this); 14311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 14411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 14511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private void checkCurrent() { 14611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || 14711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { 14811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 14911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("eglMakeCurrent failed " 15011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown + GLUtils.getEGLErrorString(mEgl.eglGetError())); 15111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 15211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 15311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 15411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 15511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private void initGL() { 15611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mEgl = (EGL10) EGLContext.getEGL(); 15711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 15811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 15911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 16011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("eglGetDisplay failed " 16111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown + GLUtils.getEGLErrorString(mEgl.eglGetError())); 16211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 16311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 16411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] version = new int[2]; 16511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEgl.eglInitialize(mEglDisplay, version)) { 16611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("eglInitialize failed " + 16711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown GLUtils.getEGLErrorString(mEgl.eglGetError())); 16811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 16911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 170a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy EGLConfig eglConfig = chooseEglConfig(); 171a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy if (eglConfig == null) { 17211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("eglConfig not initialized"); 17311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 17411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 175a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy mEglContext = createContext(mEgl, mEglDisplay, eglConfig); 17611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 177a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, eglConfig, mSurface, null); 17811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 17911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 18011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int error = mEgl.eglGetError(); 18111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 18211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.e(TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 18311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return; 18411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 18511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("createWindowSurface failed " 18611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown + GLUtils.getEGLErrorString(error)); 18711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 18811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 18911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 19011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new RuntimeException("eglMakeCurrent failed " 19111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown + GLUtils.getEGLErrorString(mEgl.eglGetError())); 19211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 19311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 19411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 19511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private void finishGL() { 19611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mEgl.eglDestroyContext(mEglDisplay, mEglContext); 19711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 19811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 19911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 200a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy private static EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 20111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] attrib_list = { EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 20211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); 20311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 20411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 20511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private EGLConfig chooseEglConfig() { 20611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] configsCount = new int[1]; 20711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGLConfig[] configs = new EGLConfig[1]; 20811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] configSpec = getConfig(); 20911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { 21011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown throw new IllegalArgumentException("eglChooseConfig failed " + 21111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown GLUtils.getEGLErrorString(mEgl.eglGetError())); 21211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } else if (configsCount[0] > 0) { 21311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return configs[0]; 21411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 21511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return null; 21611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 21711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 21811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private static int[] getConfig() { 21911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return new int[] { 22011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, 22111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_RED_SIZE, 8, 22211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_GREEN_SIZE, 8, 22311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_BLUE_SIZE, 8, 224a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy EGL10.EGL_ALPHA_SIZE, 0, 22511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_DEPTH_SIZE, 0, 22611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_STENCIL_SIZE, 0, 22711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown EGL10.EGL_NONE 22811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown }; 22911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 23011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 23111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private static int buildProgram(String vertex, String fragment) { 23211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); 23311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (vertexShader == 0) return 0; 23411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 23511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); 23611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (fragmentShader == 0) return 0; 23711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 23811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int program = glCreateProgram(); 23911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glAttachShader(program, vertexShader); 24011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 24111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 24211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glAttachShader(program, fragmentShader); 24311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 24411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 24511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glLinkProgram(program); 24611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 24711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 24811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] status = new int[1]; 24911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glGetProgramiv(program, GL_LINK_STATUS, status, 0); 25011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (status[0] != GL_TRUE) { 25111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown String error = glGetProgramInfoLog(program); 25211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.d(TAG, "Error while linking program:\n" + error); 25311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glDeleteShader(vertexShader); 25411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glDeleteShader(fragmentShader); 25511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glDeleteProgram(program); 25611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return 0; 25711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 25811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 25911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return program; 26011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 26111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 26211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private static int buildShader(String source, int type) { 26311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int shader = glCreateShader(type); 26411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 26511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glShaderSource(shader, source); 26611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 26711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 26811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glCompileShader(shader); 26911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(); 27011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 27111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int[] status = new int[1]; 27211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); 27311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (status[0] != GL_TRUE) { 27411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown String error = glGetShaderInfoLog(shader); 27511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.d(TAG, "Error while compiling shader:\n" + error); 27611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glDeleteShader(shader); 27711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return 0; 27811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 27911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 28011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown return shader; 28111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 28211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 28311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private void checkEglError() { 28411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int error = mEgl.eglGetError(); 28511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (error != EGL10.EGL_SUCCESS) { 28611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.w(TAG, "EGL error = 0x" + Integer.toHexString(error)); 28711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 28811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 28911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 29011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private static void checkGlError() { 29111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError(""); 29211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 29311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 29411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private static void checkGlError(String what) { 29511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown int error = glGetError(); 29611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown if (error != GL_NO_ERROR) { 29711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown Log.w(TAG, "GL error: (" + what + ") = 0x" + Integer.toHexString(error)); 29811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 29911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 30011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 30111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final static class Square { 30211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Straight from the API guide 30311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final String vertexShaderCode = 30411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "attribute vec4 a_position;" + 30511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "attribute vec4 a_color;" + 30611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "varying vec4 v_color;" + 30711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "void main() {" + 30811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown " gl_Position = a_position;" + 30911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown " v_color = a_color;" + 31011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "}"; 31111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 31211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final String fragmentShaderCode = 31311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "precision mediump float;" + 31411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "varying vec4 v_color;" + 31511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "void main() {" + 31611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown " gl_FragColor = v_color;" + 31711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown "}"; 31811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 31911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final FloatBuffer vertexBuffer; 32011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final FloatBuffer colorBuffer; 32111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final int mProgram; 32211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int mPositionHandle; 32311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int mColorHandle; 32411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 32511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private ShortBuffer drawListBuffer; 32611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 32711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 32811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // number of coordinates per vertex in this array 32911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final int COORDS_PER_VERTEX = 3; 33011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown float squareCoords[] = { -1f, 1f, 0f, // top left 33111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown -1f, -1f, 0f, // bottom left 33211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 1f, -1f, 0f, // bottom right 33311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 1f, 1f, 0f }; // top right 33411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 33511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices (CCW) 33611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 33711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final float HUES[] = { // reverse order due to CCW winding 33811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 60, // yellow 33911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 120, // green 34011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 343, // red 34111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 200, // blue 34211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown }; 34311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 34411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final int vertexCount = squareCoords.length / COORDS_PER_VERTEX; 34511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex 34611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 34711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private float cornerFrequencies[] = new float[vertexCount]; 34811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private int cornerRotation; 34911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 35011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final int COLOR_PLANES_PER_VERTEX = 4; 35111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown private final int colorStride = COLOR_PLANES_PER_VERTEX * 4; // bytes per vertex 35211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 35311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Set color with red, green, blue and alpha (opacity) values 354a042f4a114a5fd728fa3aa8539e377727860f1d9Romain Guy // float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; 35511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 35611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public Square() { 35711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown for (int i=0; i<vertexCount; i++) { 35811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown cornerFrequencies[i] = 1f + (float)(Math.random() * 5); 35911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 36011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown cornerRotation = (int)(Math.random() * vertexCount); 36111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // initialize vertex byte buffer for shape coordinates 36211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown ByteBuffer bb = ByteBuffer.allocateDirect( 36311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // (# of coordinate values * 4 bytes per float) 36411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown squareCoords.length * 4); 36511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown bb.order(ByteOrder.nativeOrder()); 36611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown vertexBuffer = bb.asFloatBuffer(); 36711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown vertexBuffer.put(squareCoords); 36811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown vertexBuffer.position(0); 36911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 37011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown bb = ByteBuffer.allocateDirect(vertexCount * colorStride); 37111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown bb.order(ByteOrder.nativeOrder()); 37211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer = bb.asFloatBuffer(); 37311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 37411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // initialize byte buffer for the draw list 37511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown ByteBuffer dlb = ByteBuffer.allocateDirect( 37611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // (# of coordinate values * 2 bytes per short) 37711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown drawOrder.length * 2); 37811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown dlb.order(ByteOrder.nativeOrder()); 37911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown drawListBuffer = dlb.asShortBuffer(); 38011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown drawListBuffer.put(drawOrder); 38111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown drawListBuffer.position(0); 38211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 38311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mProgram = buildProgram(vertexShaderCode, fragmentShaderCode); 38411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 38511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Add program to OpenGL environment 38611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glUseProgram(mProgram); 38711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError("glUseProgram(" + mProgram + ")"); 38811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 38911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // get handle to vertex shader's a_position member 39011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mPositionHandle = glGetAttribLocation(mProgram, "a_position"); 39111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError("glGetAttribLocation(a_position)"); 39211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 39311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Enable a handle to the triangle vertices 39411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glEnableVertexAttribArray(mPositionHandle); 39511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 39611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Prepare the triangle coordinate data 39711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 39811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown GL_FLOAT, false, 39911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown vertexStride, vertexBuffer); 40011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 40111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown mColorHandle = glGetAttribLocation(mProgram, "a_color"); 40211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError("glGetAttribLocation(a_color)"); 40311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glEnableVertexAttribArray(mColorHandle); 40411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError("glEnableVertexAttribArray"); 40511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 40611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 40711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final float[] _tmphsv = new float[3]; 40811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown public void draw() { 40911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // same thing for colors 41011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown long now = SystemClock.uptimeMillis(); 41111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.clear(); 41211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final float t = now / 4000f; // set the base period to 4sec 41311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown for(int i=0; i<vertexCount; i++) { 41411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final float freq = (float) Math.sin(2 * Math.PI * t / cornerFrequencies[i]); 41511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown _tmphsv[0] = HUES[(i + cornerRotation) % vertexCount]; 41611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown _tmphsv[1] = 1f; 41711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown _tmphsv[2] = freq * 0.25f + 0.75f; 41811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown final int c = Color.HSVToColor(_tmphsv); 41911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.put((float)((c & 0xFF0000) >> 16) / 0xFF); 42011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.put((float)((c & 0x00FF00) >> 8) / 0xFF); 42111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.put((float)(c & 0x0000FF) / 0xFF); 42211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.put(/*a*/ 1f); 42311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 42411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorBuffer.position(0); 42511348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glVertexAttribPointer(mColorHandle, COLOR_PLANES_PER_VERTEX, 42611348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown GL_FLOAT, false, 42711348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown colorStride, colorBuffer); 42811348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown checkGlError("glVertexAttribPointer"); 42911348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown 43011348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown // Draw the triangle 43111348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount); 43211348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 43311348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown } 43411348f99ee2ffaeb3f705b669ae886beda97656fJeff Brown} 435