diff options
Diffstat (limited to 'com/android/systemui/ImageWallpaper.java')
-rw-r--r-- | com/android/systemui/ImageWallpaper.java | 517 |
1 files changed, 439 insertions, 78 deletions
diff --git a/com/android/systemui/ImageWallpaper.java b/com/android/systemui/ImageWallpaper.java index 593bb508..907a79e7 100644 --- a/com/android/systemui/ImageWallpaper.java +++ b/com/android/systemui/ImageWallpaper.java @@ -16,6 +16,11 @@ package com.android.systemui; +import static android.opengl.GLES20.*; + +import static javax.microedition.khronos.egl.EGL10.*; + +import android.app.ActivityManager; import android.app.WallpaperManager; import android.content.ComponentCallbacks2; import android.graphics.Bitmap; @@ -23,18 +28,31 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region.Op; +import android.opengl.GLUtils; import android.os.AsyncTask; +import android.os.SystemProperties; import android.os.Trace; +import android.renderscript.Matrix4f; import android.service.wallpaper.WallpaperService; import android.util.Log; import android.view.Display; import android.view.DisplayInfo; +import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.WindowManager; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +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; /** * Default built-in wallpaper that simply shows a static image. @@ -46,13 +64,24 @@ public class ImageWallpaper extends WallpaperService { private static final boolean DEBUG = false; private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu"; - private WallpaperManager mWallpaperManager; - private DrawableEngine mEngine; + static final boolean FIXED_SIZED_SURFACE = true; + static final boolean USE_OPENGL = true; + + WallpaperManager mWallpaperManager; + + DrawableEngine mEngine; + + boolean mIsHwAccelerated; @Override public void onCreate() { super.onCreate(); - mWallpaperManager = getSystemService(WallpaperManager.class); + mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE); + + //noinspection PointlessBooleanExpression,ConstantConditions + if (FIXED_SIZED_SURFACE && USE_OPENGL) { + mIsHwAccelerated = ActivityManager.isHighEndGfx(); + } } @Override @@ -69,12 +98,15 @@ public class ImageWallpaper extends WallpaperService { } class DrawableEngine extends Engine { + static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + static final int EGL_OPENGL_ES2_BIT = 4; + Bitmap mBackground; int mBackgroundWidth = -1, mBackgroundHeight = -1; int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; int mLastRotation = -1; - float mXOffset = 0f; - float mYOffset = 0f; + float mXOffset = 0.5f; + float mYOffset = 0.5f; float mScale = 1f; private Display mDefaultDisplay; @@ -85,6 +117,34 @@ public class ImageWallpaper extends WallpaperService { int mLastXTranslation; int mLastYTranslation; + private EGL10 mEgl; + private EGLDisplay mEglDisplay; + private EGLConfig mEglConfig; + private EGLContext mEglContext; + private EGLSurface mEglSurface; + + private static final String sSimpleVS = + "attribute vec4 position;\n" + + "attribute vec2 texCoords;\n" + + "varying vec2 outTexCoords;\n" + + "uniform mat4 projection;\n" + + "\nvoid main(void) {\n" + + " outTexCoords = texCoords;\n" + + " gl_Position = projection * position;\n" + + "}\n\n"; + private static final String sSimpleFS = + "precision mediump float;\n\n" + + "varying vec2 outTexCoords;\n" + + "uniform sampler2D texture;\n" + + "\nvoid main(void) {\n" + + " gl_FragColor = texture2D(texture, outTexCoords);\n" + + "}\n\n"; + + private static final int FLOAT_SIZE_BYTES = 4; + private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; + private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; + private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; + private int mRotationAtLastSurfaceSizeUpdate = -1; private int mDisplayWidthAtLastSurfaceSizeUpdate = -1; private int mDisplayHeightAtLastSurfaceSizeUpdate = -1; @@ -94,14 +154,13 @@ public class ImageWallpaper extends WallpaperService { private AsyncTask<Void, Void, Bitmap> mLoader; private boolean mNeedsDrawAfterLoadingWallpaper; private boolean mSurfaceValid; - private boolean mSurfaceRedrawNeeded; - DrawableEngine() { + public DrawableEngine() { super(); setFixedSizeAllowed(true); } - void trimMemory(int level) { + public void trimMemory(int level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW && level <= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL && mBackground != null) { @@ -120,7 +179,6 @@ public class ImageWallpaper extends WallpaperService { super.onCreate(surfaceHolder); - //noinspection ConstantConditions mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay(); setOffsetNotificationsEnabled(false); @@ -141,7 +199,7 @@ public class ImageWallpaper extends WallpaperService { // Load background image dimensions, if we haven't saved them yet if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) { // Need to load the image to get dimensions - loadWallpaper(forDraw); + loadWallpaper(forDraw, false /* needsReset */); if (DEBUG) { Log.d(TAG, "Reloading, redoing updateSurfaceSize later."); } @@ -152,13 +210,16 @@ public class ImageWallpaper extends WallpaperService { int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth); int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight); - // Used a fixed size surface, because we are special. We can do - // this because we know the current design of window animations doesn't - // cause this to break. - surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight); - mLastRequestedWidth = surfaceWidth; - mLastRequestedHeight = surfaceHeight; - + if (FIXED_SIZED_SURFACE) { + // Used a fixed size surface, because we are special. We can do + // this because we know the current design of window animations doesn't + // cause this to break. + surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight); + mLastRequestedWidth = surfaceWidth; + mLastRequestedHeight = surfaceHeight; + } else { + surfaceHolder.setSizeFromLayout(); + } return hasWallpaper; } @@ -239,13 +300,6 @@ public class ImageWallpaper extends WallpaperService { Log.d(TAG, "onSurfaceRedrawNeeded"); } super.onSurfaceRedrawNeeded(holder); - // At the end of this method we should have drawn into the surface. - // This means that the bitmap should be loaded synchronously if - // it was already unloaded. - if (mBackground == null) { - updateBitmap(mWallpaperManager.getBitmap(true /* hardware */)); - } - mSurfaceRedrawNeeded = true; drawFrame(); } @@ -282,8 +336,7 @@ public class ImageWallpaper extends WallpaperService { boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight; - boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation - || mSurfaceRedrawNeeded; + boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation; if (!redrawNeeded && !mOffsetsChanged) { if (DEBUG) { Log.d(TAG, "Suppressed drawFrame since redraw is not needed " @@ -292,24 +345,40 @@ public class ImageWallpaper extends WallpaperService { return; } mLastRotation = newRotation; - mSurfaceRedrawNeeded = false; // Load bitmap if it is not yet loaded if (mBackground == null) { - loadWallpaper(true); + if (DEBUG) { + Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " + + mBackground + ", " + + ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " + + ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " + + dw + ", " + dh); + } + loadWallpaper(true /* needDraw */, true /* needReset */); if (DEBUG) { Log.d(TAG, "Reloading, resuming draw later"); } return; } - // Left align the scaled image + // Center the scaled image mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(), dh / (float) mBackground.getHeight())); - final int availw = (int) (mBackground.getWidth() * mScale) - dw; - final int availh = (int) (mBackground.getHeight() * mScale) - dh; - int xPixels = (int) (availw * mXOffset); - int yPixels = (int) (availh * mYOffset); + final int availw = dw - (int) (mBackground.getWidth() * mScale); + final int availh = dh - (int) (mBackground.getHeight() * mScale); + int xPixels = availw / 2; + int yPixels = availh / 2; + + // Adjust the image for xOffset/yOffset values. If window manager is handling offsets, + // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels + // will remain unchanged + final int availwUnscaled = dw - mBackground.getWidth(); + final int availhUnscaled = dh - mBackground.getHeight(); + if (availwUnscaled < 0) + xPixels += (int) (availwUnscaled * (mXOffset - .5f) + .5f); + if (availhUnscaled < 0) + yPixels += (int) (availhUnscaled * (mYOffset - .5f) + .5f); mOffsetsChanged = false; if (surfaceDimensionsChanged) { @@ -330,7 +399,21 @@ public class ImageWallpaper extends WallpaperService { Log.d(TAG, "Redrawing wallpaper"); } - drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); + if (mIsHwAccelerated) { + if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) { + drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); + } + } else { + drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); + if (FIXED_SIZED_SURFACE) { + // If the surface is fixed-size, we should only need to + // draw it once and then we'll let the window manager + // position it appropriately. As such, we no longer needed + // the loaded bitmap. Yay! + // hw-accelerated renderer retains bitmap for faster rotation + unloadWallpaper(false /* forgetSize */); + } + } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } @@ -345,20 +428,28 @@ public class ImageWallpaper extends WallpaperService { * * If {@param needsReset} is set also clears the cache in WallpaperManager first. */ - private void loadWallpaper(boolean needsDraw) { + private void loadWallpaper(boolean needsDraw, boolean needsReset) { mNeedsDrawAfterLoadingWallpaper |= needsDraw; if (mLoader != null) { - if (DEBUG) { - Log.d(TAG, "Skipping loadWallpaper, already in flight "); + if (needsReset) { + mLoader.cancel(false /* interrupt */); + mLoader = null; + } else { + if (DEBUG) { + Log.d(TAG, "Skipping loadWallpaper, already in flight "); + } + return; } - return; } mLoader = new AsyncTask<Void, Void, Bitmap>() { @Override protected Bitmap doInBackground(Void... params) { Throwable exception; try { - return mWallpaperManager.getBitmap(true /* hardware */); + if (needsReset) { + mWallpaperManager.forgetLoadedWallpaper(); + } + return mWallpaperManager.getBitmap(); } catch (RuntimeException | OutOfMemoryError e) { exception = e; } @@ -367,33 +458,48 @@ public class ImageWallpaper extends WallpaperService { return null; } - // Note that if we do fail at this, and the default wallpaper can't - // be loaded, we will go into a cycle. Don't do a build where the - // default wallpaper can't be loaded. - Log.w(TAG, "Unable to load wallpaper!", exception); - try { - mWallpaperManager.clear(); - } catch (IOException ex) { - // now we're really screwed. - Log.w(TAG, "Unable reset to default wallpaper!", ex); - } - - if (isCancelled()) { - return null; - } - - try { - return mWallpaperManager.getBitmap(true /* hardware */); - } catch (RuntimeException | OutOfMemoryError e) { - Log.w(TAG, "Unable to load default wallpaper!", e); + if (exception != null) { + // Note that if we do fail at this, and the default wallpaper can't + // be loaded, we will go into a cycle. Don't do a build where the + // default wallpaper can't be loaded. + Log.w(TAG, "Unable to load wallpaper!", exception); + try { + mWallpaperManager.clear(); + } catch (IOException ex) { + // now we're really screwed. + Log.w(TAG, "Unable reset to default wallpaper!", ex); + } + + if (isCancelled()) { + return null; + } + + try { + return mWallpaperManager.getBitmap(); + } catch (RuntimeException | OutOfMemoryError e) { + Log.w(TAG, "Unable to load default wallpaper!", e); + } } return null; } @Override protected void onPostExecute(Bitmap b) { - updateBitmap(b); + mBackground = null; + mBackgroundWidth = -1; + mBackgroundHeight = -1; + + if (b != null) { + mBackground = b; + mBackgroundWidth = mBackground.getWidth(); + mBackgroundHeight = mBackground.getHeight(); + } + if (DEBUG) { + Log.d(TAG, "Wallpaper loaded: " + mBackground); + } + updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(), + false /* forDraw */); if (mNeedsDrawAfterLoadingWallpaper) { drawFrame(); } @@ -404,24 +510,6 @@ public class ImageWallpaper extends WallpaperService { }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - private void updateBitmap(Bitmap bitmap) { - mBackground = null; - mBackgroundWidth = -1; - mBackgroundHeight = -1; - - if (bitmap != null) { - mBackground = bitmap; - mBackgroundWidth = mBackground.getWidth(); - mBackgroundHeight = mBackground.getHeight(); - } - - if (DEBUG) { - Log.d(TAG, "Wallpaper loaded: " + mBackground); - } - updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(), - false /* forDraw */); - } - private void unloadWallpaper(boolean forgetSize) { if (mLoader != null) { mLoader.cancel(false); @@ -476,7 +564,7 @@ public class ImageWallpaper extends WallpaperService { } private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int left, int top) { - Canvas c = sh.lockHardwareCanvas(); + Canvas c = sh.lockCanvas(); if (c != null) { try { if (DEBUG) { @@ -502,5 +590,278 @@ public class ImageWallpaper extends WallpaperService { } } } + + private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) { + if (!initGL(sh)) return false; + + final float right = left + mBackground.getWidth() * mScale; + final float bottom = top + mBackground.getHeight() * mScale; + + final Rect frame = sh.getSurfaceFrame(); + final Matrix4f ortho = new Matrix4f(); + ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f); + + final FloatBuffer triangleVertices = createMesh(left, top, right, bottom); + + final int texture = loadTexture(mBackground); + final int program = buildProgram(sSimpleVS, sSimpleFS); + + final int attribPosition = glGetAttribLocation(program, "position"); + final int attribTexCoords = glGetAttribLocation(program, "texCoords"); + final int uniformTexture = glGetUniformLocation(program, "texture"); + final int uniformProjection = glGetUniformLocation(program, "projection"); + + checkGlError(); + + glViewport(0, 0, frame.width(), frame.height()); + glBindTexture(GL_TEXTURE_2D, texture); + + glUseProgram(program); + glEnableVertexAttribArray(attribPosition); + glEnableVertexAttribArray(attribTexCoords); + glUniform1i(uniformTexture, 0); + glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0); + + checkGlError(); + + if (w > 0 || h > 0) { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + // drawQuad + triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); + glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + + triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); + glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false, + TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + boolean status = mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + checkEglError(); + + finishGL(texture, program); + + return status; + } + + private FloatBuffer createMesh(int left, int top, float right, float bottom) { + final float[] verticesData = { + // X, Y, Z, U, V + left, bottom, 0.0f, 0.0f, 1.0f, + right, bottom, 0.0f, 1.0f, 1.0f, + left, top, 0.0f, 0.0f, 0.0f, + right, top, 0.0f, 1.0f, 0.0f, + }; + + final int bytes = verticesData.length * FLOAT_SIZE_BYTES; + final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order( + ByteOrder.nativeOrder()).asFloatBuffer(); + triangleVertices.put(verticesData).position(0); + return triangleVertices; + } + + private int loadTexture(Bitmap bitmap) { + int[] textures = new int[1]; + + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, textures, 0); + checkGlError(); + + int texture = textures[0]; + glBindTexture(GL_TEXTURE_2D, texture); + checkGlError(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0); + checkGlError(); + + return texture; + } + + private int buildProgram(String vertex, String fragment) { + int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); + if (vertexShader == 0) return 0; + + int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); + if (fragmentShader == 0) return 0; + + int program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + checkGlError(); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + int[] status = new int[1]; + glGetProgramiv(program, GL_LINK_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetProgramInfoLog(program); + Log.d(GL_LOG_TAG, "Error while linking program:\n" + error); + glDeleteProgram(program); + return 0; + } + + return program; + } + + private int buildShader(String source, int type) { + int shader = glCreateShader(type); + + glShaderSource(shader, source); + checkGlError(); + + glCompileShader(shader); + checkGlError(); + + int[] status = new int[1]; + glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); + if (status[0] != GL_TRUE) { + String error = glGetShaderInfoLog(shader); + Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error); + glDeleteShader(shader); + return 0; + } + + return shader; + } + + private void checkEglError() { + int error = mEgl.eglGetError(); + if (error != EGL_SUCCESS) { + Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error)); + } + } + + private void checkGlError() { + int error = glGetError(); + if (error != GL_NO_ERROR) { + Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable()); + } + } + + private void finishGL(int texture, int program) { + int[] textures = new int[1]; + textures[0] = texture; + glDeleteTextures(1, textures, 0); + glDeleteProgram(program); + mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglTerminate(mEglDisplay); + } + + private boolean initGL(SurfaceHolder surfaceHolder) { + mEgl = (EGL10) EGLContext.getEGL(); + + mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mEglDisplay == 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())); + } + + mEglConfig = chooseEglConfig(); + if (mEglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + + mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); + if (mEglContext == EGL_NO_CONTEXT) { + throw new RuntimeException("createContext failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + int attribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }; + EGLSurface tmpSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); + mEgl.eglMakeCurrent(mEglDisplay, tmpSurface, tmpSurface, mEglContext); + + int[] maxSize = new int[1]; + Rect frame = surfaceHolder.getSurfaceFrame(); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0); + + mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, tmpSurface); + + if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglTerminate(mEglDisplay); + Log.e(GL_LOG_TAG, "requested texture size " + + frame.width() + "x" + frame.height() + " exceeds the support maximum of " + + maxSize[0] + "x" + maxSize[0]); + return false; + } + + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null); + if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { + int error = mEgl.eglGetError(); + if (error == EGL_BAD_NATIVE_WINDOW || error == EGL_BAD_ALLOC) { + Log.e(GL_LOG_TAG, "createWindowSurface returned " + + GLUtils.getEGLErrorString(error) + "."); + return false; + } + throw new RuntimeException("createWindowSurface failed " + + GLUtils.getEGLErrorString(error)); + } + + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + return true; + } + + + EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { + int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list); + } + + private EGLConfig chooseEglConfig() { + int[] configsCount = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + int[] configSpec = getConfig(); + if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { + throw new IllegalArgumentException("eglChooseConfig failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } else if (configsCount[0] > 0) { + return configs[0]; + } + return null; + } + + private int[] getConfig() { + return new int[] { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 0, + EGL_STENCIL_SIZE, 0, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE + }; + } } } |