diff options
author | Romain Guy <romainguy@google.com> | 2011-08-24 17:09:30 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-08-24 17:09:30 -0700 |
commit | c39e8e89eb370ed66f552da3be258e57f1aabeb9 (patch) | |
tree | 345c03fe7b130d2dbc8277998c603ca8079bb94b | |
parent | 19bc995e9ae4ec9ea48c183758759e2b68ec964b (diff) | |
parent | 407ec78b828173257b0c5dae221649a4ccd8b058 (diff) | |
download | frameworks_base-c39e8e89eb370ed66f552da3be258e57f1aabeb9.zip frameworks_base-c39e8e89eb370ed66f552da3be258e57f1aabeb9.tar.gz frameworks_base-c39e8e89eb370ed66f552da3be258e57f1aabeb9.tar.bz2 |
Merge "Add OpenGL backend to ImageWallpaper Bug #5204874"
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/WallpaperManager.java | 66 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 60 | ||||
-rw-r--r-- | opengl/java/android/opengl/GLUtils.java | 49 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/ImageWallpaper.java | 393 | ||||
-rw-r--r-- | services/java/com/android/server/WallpaperManagerService.java | 2 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java | 52 |
7 files changed, 454 insertions, 169 deletions
diff --git a/api/current.txt b/api/current.txt index aea2ff3..250f09f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13974,6 +13974,7 @@ package android.opengl { } public final class GLUtils { + method public static java.lang.String getEGLErrorString(int); method public static int getInternalFormat(android.graphics.Bitmap); method public static int getType(android.graphics.Bitmap); method public static void texImage2D(int, int, int, android.graphics.Bitmap, int); diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index ff04757..f81ea81 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -107,19 +107,22 @@ public class WallpaperManager { private final int mHeight; private int mDrawLeft; private int mDrawTop; + private final Paint mPaint; private FastBitmapDrawable(Bitmap bitmap) { mBitmap = bitmap; mWidth = bitmap.getWidth(); mHeight = bitmap.getHeight(); + setBounds(0, 0, mWidth, mHeight); + + mPaint = new Paint(); + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); } @Override public void draw(Canvas canvas) { - Paint paint = new Paint(); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); - canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, paint); + canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, mPaint); } @Override @@ -134,33 +137,23 @@ public class WallpaperManager { } @Override - public void setBounds(Rect bounds) { - // TODO Auto-generated method stub - super.setBounds(bounds); - } - - @Override public void setAlpha(int alpha) { - throw new UnsupportedOperationException( - "Not supported with this drawable"); + throw new UnsupportedOperationException("Not supported with this drawable"); } @Override public void setColorFilter(ColorFilter cf) { - throw new UnsupportedOperationException( - "Not supported with this drawable"); + throw new UnsupportedOperationException("Not supported with this drawable"); } @Override public void setDither(boolean dither) { - throw new UnsupportedOperationException( - "Not supported with this drawable"); + throw new UnsupportedOperationException("Not supported with this drawable"); } @Override public void setFilterBitmap(boolean filter) { - throw new UnsupportedOperationException( - "Not supported with this drawable"); + throw new UnsupportedOperationException("Not supported with this drawable"); } @Override @@ -230,7 +223,7 @@ public class WallpaperManager { } mWallpaper = null; try { - mWallpaper = getCurrentWallpaperLocked(context); + mWallpaper = getCurrentWallpaperLocked(); } catch (OutOfMemoryError e) { Log.w(TAG, "No memory load current wallpaper", e); } @@ -253,7 +246,7 @@ public class WallpaperManager { } } - private Bitmap getCurrentWallpaperLocked(Context context) { + private Bitmap getCurrentWallpaperLocked() { try { Bundle params = new Bundle(); ParcelFileDescriptor fd = mService.getWallpaper(this, params); @@ -265,17 +258,19 @@ public class WallpaperManager { BitmapFactory.Options options = new BitmapFactory.Options(); Bitmap bm = BitmapFactory.decodeFileDescriptor( fd.getFileDescriptor(), null, options); - return generateBitmap(context, bm, width, height); + return generateBitmap(bm, width, height); } catch (OutOfMemoryError e) { Log.w(TAG, "Can't decode file", e); } finally { try { fd.close(); } catch (IOException e) { + // Ignore } } } } catch (RemoteException e) { + // Ignore } return null; } @@ -291,27 +286,29 @@ public class WallpaperManager { try { BitmapFactory.Options options = new BitmapFactory.Options(); Bitmap bm = BitmapFactory.decodeStream(is, null, options); - return generateBitmap(context, bm, width, height); + return generateBitmap(bm, width, height); } catch (OutOfMemoryError e) { Log.w(TAG, "Can't decode stream", e); } finally { try { is.close(); } catch (IOException e) { + // Ignore } } } } catch (RemoteException e) { + // Ignore } return null; } } - private static Object mSync = new Object(); + private static final Object sSync = new Object[0]; private static Globals sGlobals; static void initGlobals(Looper looper) { - synchronized (mSync) { + synchronized (sSync) { if (sGlobals == null) { sGlobals = new Globals(looper); } @@ -390,8 +387,7 @@ public class WallpaperManager { public Drawable getFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true); if (bm != null) { - Drawable dr = new FastBitmapDrawable(bm); - return dr; + return new FastBitmapDrawable(bm); } return null; } @@ -406,13 +402,21 @@ public class WallpaperManager { public Drawable peekFastDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false); if (bm != null) { - Drawable dr = new FastBitmapDrawable(bm); - return dr; + return new FastBitmapDrawable(bm); } return null; } /** + * Like {@link #getDrawable()} but returns a Bitmap. + * + * @hide + */ + public Bitmap getBitmap() { + return sGlobals.peekWallpaperBitmap(mContext, true); + } + + /** * Remove all internal references to the last loaded wallpaper. Useful * for apps that want to reduce memory usage when they only temporarily * need to have the wallpaper. After calling, the next request for the @@ -464,6 +468,7 @@ public class WallpaperManager { } } } catch (RemoteException e) { + // Ignore } } @@ -493,6 +498,7 @@ public class WallpaperManager { } } } catch (RemoteException e) { + // Ignore } } @@ -524,6 +530,7 @@ public class WallpaperManager { } } } catch (RemoteException e) { + // Ignore } } @@ -594,6 +601,7 @@ public class WallpaperManager { try { sGlobals.mService.setDimensionHints(minimumWidth, minimumHeight); } catch (RemoteException e) { + // Ignore } } @@ -690,7 +698,7 @@ public class WallpaperManager { setResource(com.android.internal.R.drawable.default_wallpaper); } - static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) { + static Bitmap generateBitmap(Bitmap bm, int width, int height) { if (bm == null) { return null; } @@ -717,7 +725,7 @@ public class WallpaperManager { if (deltaw > 0 || deltah > 0) { // We need to scale up so it covers the entire area. - float scale = 1.0f; + float scale; if (deltaw > deltah) { scale = width / (float)targetRect.right; } else { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index a05637d..926d424 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -21,6 +21,7 @@ import android.content.ComponentCallbacks2; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; +import android.opengl.GLUtils; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; @@ -402,51 +403,6 @@ public abstract class HardwareRenderer { } /** - * Return a string for the EGL error code, or the hex representation - * if the error is unknown. - * - * @param error The EGL error to convert into a String. - * - * @return An error string correponding to the EGL error code. - */ - static String getEGLErrorString(int error) { - switch (error) { - case EGL_SUCCESS: - return "EGL_SUCCESS"; - case EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED"; - case EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS"; - case EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC"; - case EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE"; - case EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG"; - case EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT"; - case EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE"; - case EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY"; - case EGL_BAD_MATCH: - return "EGL_BAD_MATCH"; - case EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP"; - case EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW"; - case EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER"; - case EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE"; - case EGL11.EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST"; - default: - return "0x" + Integer.toHexString(error); - } - } - - /** * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)} * is invoked and the requested flag is turned off. The error code is * also logged as a warning. @@ -458,7 +414,7 @@ public abstract class HardwareRenderer { // something bad has happened revert to // normal rendering. fallback(error != EGL11.EGL_CONTEXT_LOST); - Log.w(LOG_TAG, "EGL error: " + getEGLErrorString(error)); + Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error)); } } } @@ -523,14 +479,14 @@ public abstract class HardwareRenderer { if (sEglDisplay == EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed " - + getEGLErrorString(sEgl.eglGetError())); + + GLUtils.getEGLErrorString(sEgl.eglGetError())); } // We can now initialize EGL for that display int[] version = new int[2]; if (!sEgl.eglInitialize(sEglDisplay, version)) { throw new RuntimeException("eglInitialize failed " + - getEGLErrorString(sEgl.eglGetError())); + GLUtils.getEGLErrorString(sEgl.eglGetError())); } sEglConfig = chooseEglConfig(); @@ -579,7 +535,7 @@ public abstract class HardwareRenderer { if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) { throw new IllegalArgumentException("eglChooseConfig failed " + - getEGLErrorString(sEgl.eglGetError())); + GLUtils.getEGLErrorString(sEgl.eglGetError())); } else if (configsCount[0] > 0) { if ("choice".equalsIgnoreCase(debug)) { printConfig(configs[0]); @@ -647,7 +603,7 @@ public abstract class HardwareRenderer { */ if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { throw new Surface.OutOfResourcesException("eglMakeCurrent failed " - + getEGLErrorString(sEgl.eglGetError())); + + GLUtils.getEGLErrorString(sEgl.eglGetError())); } // If mDirtyRegions is set, this means we have an EGL configuration @@ -734,7 +690,7 @@ public abstract class HardwareRenderer { return false; } throw new RuntimeException("createWindowSurface failed " - + getEGLErrorString(error)); + + GLUtils.getEGLErrorString(error)); } return true; } @@ -856,7 +812,7 @@ public abstract class HardwareRenderer { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { fallback(true); Log.e(LOG_TAG, "eglMakeCurrent failed " + - getEGLErrorString(sEgl.eglGetError())); + GLUtils.getEGLErrorString(sEgl.eglGetError())); return SURFACE_STATE_ERROR; } else { return SURFACE_STATE_UPDATED; diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java index f30a4cd..125c56e 100644 --- a/opengl/java/android/opengl/GLUtils.java +++ b/opengl/java/android/opengl/GLUtils.java @@ -16,9 +16,11 @@ package android.opengl; -import javax.microedition.khronos.opengles.GL10; import android.graphics.Bitmap; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; + /** * * Utility class to help bridging OpenGL ES and Android APIs. @@ -222,6 +224,51 @@ public final class GLUtils { } } + /** + * Return a string for the EGL error code, or the hex representation + * if the error is unknown. + * + * @param error The EGL error to convert into a String. + * + * @return An error string corresponding to the EGL error code. + */ + public static String getEGLErrorString(int error) { + switch (error) { + case EGL10.EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL10.EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL10.EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL10.EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL10.EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL10.EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL10.EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL10.EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL10.EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL10.EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL10.EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL10.EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL10.EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL10.EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL11.EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + default: + return "0x" + Integer.toHexString(error); + } + } + native private static void nativeClassInit(); native private static int native_getInternalFormat(Bitmap bitmap); diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index e1231a5..5a3850d 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -16,41 +16,65 @@ package com.android.systemui; -import java.io.IOException; - +import android.app.ActivityManager; import android.app.WallpaperManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.Region.Op; -import android.graphics.drawable.Drawable; -import android.os.Handler; +import android.opengl.GLUtils; +import android.renderscript.Matrix4f; import android.service.wallpaper.WallpaperService; import android.util.Log; -import android.util.Slog; +import android.view.Display; import android.view.MotionEvent; import android.view.SurfaceHolder; -import android.content.Context; -import android.content.IntentFilter; -import android.content.Intent; -import android.content.BroadcastReceiver; +import android.view.WindowManager; + +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 java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import static android.opengl.GLES20.*; +import static javax.microedition.khronos.egl.EGL10.*; /** * Default built-in wallpaper that simply shows a static image. */ +@SuppressWarnings({"UnusedDeclaration"}) public class ImageWallpaper extends WallpaperService { private static final String TAG = "ImageWallpaper"; + private static final String GL_LOG_TAG = "ImageWallpaperGL"; private static final boolean DEBUG = false; static final boolean FIXED_SIZED_SURFACE = true; + static final boolean USE_OPENGL = false; WallpaperManager mWallpaperManager; - private Handler mHandler; + + boolean mIsHwAccelerated; @Override public void onCreate() { super.onCreate(); mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE); - mHandler = new Handler(); + + //noinspection PointlessBooleanExpression,ConstantConditions + if (FIXED_SIZED_SURFACE && USE_OPENGL) { + WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + mIsHwAccelerated = ActivityManager.isHighEndGfx(display); + } } public Engine onCreateEngine() { @@ -58,9 +82,16 @@ public class ImageWallpaper extends WallpaperService { } class DrawableEngine extends Engine { - private final Object mLock = new Object(); + static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + static final int EGL_OPENGL_ES2_BIT = 4; + + private final Object mLock = new Object[0]; + + // TODO: Not currently used, keeping around until we know we don't need it + @SuppressWarnings({"UnusedDeclaration"}) private WallpaperObserver mReceiver; - Drawable mBackground; + + Bitmap mBackground; int mBackgroundWidth = -1, mBackgroundHeight = -1; float mXOffset; float mYOffset; @@ -71,6 +102,35 @@ 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 GL mGL; + + 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; + class WallpaperObserver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { if (DEBUG) { @@ -94,7 +154,7 @@ public class ImageWallpaper extends WallpaperService { super.onCreate(surfaceHolder); - // Don't need this currently because the wallpaper service + // TODO: Don't need this currently because the wallpaper service // will restart the image wallpaper whenever the image changes. //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); //mReceiver = new WallpaperObserver(); @@ -221,8 +281,7 @@ public class ImageWallpaper extends WallpaperService { int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2); mOffsetsChanged = false; - if (!mRedrawNeeded - && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { + if (!mRedrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { if (DEBUG) { Log.d(TAG, "Suppressed drawFrame since the image has not " + "actually moved an integral number of pixels."); @@ -240,27 +299,10 @@ public class ImageWallpaper extends WallpaperService { updateWallpaperLocked(); } - //Slog.i(TAG, "************** DRAWING WALLAPER ******************"); - Canvas c = sh.lockCanvas(); - if (c != null) { - try { - if (DEBUG) { - Log.d(TAG, "Redrawing: xPixels=" + xPixels + ", yPixels=" + yPixels); - } - - c.translate(xPixels, yPixels); - if (availw < 0 || availh < 0) { - c.save(Canvas.CLIP_SAVE_FLAG); - c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE); - c.drawColor(0xff000000); - c.restore(); - } - if (mBackground != null) { - mBackground.draw(c); - } - } finally { - sh.unlockCanvasAndPost(c); - } + if (mIsHwAccelerated) { + drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels); + } else { + drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); } if (FIXED_SIZED_SURFACE) { @@ -274,15 +316,15 @@ public class ImageWallpaper extends WallpaperService { } void updateWallpaperLocked() { - //Slog.i(TAG, "************** LOADING WALLAPER ******************"); Throwable exception = null; try { - mBackground = mWallpaperManager.getFastDrawable(); + mBackground = mWallpaperManager.getBitmap(); } catch (RuntimeException e) { exception = e; } catch (OutOfMemoryError e) { exception = e; } + if (exception != null) { mBackground = null; // Note that if we do fail at this, and the default wallpaper can't @@ -296,8 +338,277 @@ public class ImageWallpaper extends WallpaperService { Log.w(TAG, "Unable reset to default wallpaper!", ex); } } - mBackgroundWidth = mBackground != null ? mBackground.getIntrinsicWidth() : 0; - mBackgroundHeight = mBackground != null ? mBackground.getIntrinsicHeight() : 0; + + mBackgroundWidth = mBackground != null ? mBackground.getWidth() : 0; + mBackgroundHeight = mBackground != null ? mBackground.getHeight() : 0; + } + + private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) { + Canvas c = sh.lockCanvas(); + if (c != null) { + try { + if (DEBUG) { + Log.d(TAG, "Redrawing: x=" + x + ", y=" + y); + } + + c.translate(x, y); + if (w < 0 || h < 0) { + c.save(Canvas.CLIP_SAVE_FLAG); + c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE); + c.drawColor(0xff000000); + c.restore(); + } + if (mBackground != null) { + c.drawBitmap(mBackground, 0, 0, null); + } + } finally { + sh.unlockCanvasAndPost(c); + } + } + } + + private void drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) { + initGL(sh); + + final float right = left + mBackgroundWidth; + final float bottom = top + mBackgroundHeight; + + 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); + + if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { + throw new RuntimeException("Cannot swap buffers"); + } + checkEglError(); + + finishGL(); + } + + 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(); + + bitmap.recycle(); + + 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); + checkGlError(); + + glAttachShader(program, fragmentShader); + checkGlError(); + + glLinkProgram(program); + checkGlError(); + + 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); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + 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() { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + } + + private void 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); + + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null); + + if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { + int error = mEgl.eglGetError(); + if (error == EGL_BAD_NATIVE_WINDOW) { + Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); + return; + } + throw new RuntimeException("createWindowSurface failed " + + GLUtils.getEGLErrorString(error)); + } + + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + + mGL = mEglContext.getGL(); + } + + + 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_NONE + }; } } } diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 9765f2a..565063a 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -75,7 +75,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { static final String TAG = "WallpaperService"; static final boolean DEBUG = false; - Object mLock = new Object(); + final Object mLock = new Object[0]; /** * Minimum time between crashes of a wallpaper service for us to consider diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java index e77178d..3232eed 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java @@ -33,7 +33,6 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; @@ -207,7 +206,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa glEnableVertexAttribArray(attribTexCoords); checkGlError(); - glUniform1i(texture, 0); + glUniform1i(uniformTexture, texture); checkGlError(); while (!mFinished) { @@ -350,7 +349,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { throw new RuntimeException("eglMakeCurrent failed " - + getEGLErrorString(mEgl.eglGetError())); + + GLUtils.getEGLErrorString(mEgl.eglGetError())); } } } @@ -361,13 +360,13 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed " - + getEGLErrorString(mEgl.eglGetError())); + + GLUtils.getEGLErrorString(mEgl.eglGetError())); } int[] version = new int[2]; if (!mEgl.eglInitialize(mEglDisplay, version)) { throw new RuntimeException("eglInitialize failed " + - getEGLErrorString(mEgl.eglGetError())); + GLUtils.getEGLErrorString(mEgl.eglGetError())); } mEglConfig = chooseEglConfig(); @@ -386,12 +385,12 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa return; } throw new RuntimeException("createWindowSurface failed " - + getEGLErrorString(error)); + + GLUtils.getEGLErrorString(error)); } if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { throw new RuntimeException("eglMakeCurrent failed " - + getEGLErrorString(mEgl.eglGetError())); + + GLUtils.getEGLErrorString(mEgl.eglGetError())); } mGL = mEglContext.getGL(); @@ -409,7 +408,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa int[] configSpec = getConfig(); if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { throw new IllegalArgumentException("eglChooseConfig failed " + - getEGLErrorString(mEgl.eglGetError())); + GLUtils.getEGLErrorString(mEgl.eglGetError())); } else if (configsCount[0] > 0) { return configs[0]; } @@ -429,43 +428,6 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa }; } - static String getEGLErrorString(int error) { - switch (error) { - case EGL10.EGL_SUCCESS: - return "EGL_SUCCESS"; - case EGL10.EGL_NOT_INITIALIZED: - return "EGL_NOT_INITIALIZED"; - case EGL10.EGL_BAD_ACCESS: - return "EGL_BAD_ACCESS"; - case EGL10.EGL_BAD_ALLOC: - return "EGL_BAD_ALLOC"; - case EGL10.EGL_BAD_ATTRIBUTE: - return "EGL_BAD_ATTRIBUTE"; - case EGL10.EGL_BAD_CONFIG: - return "EGL_BAD_CONFIG"; - case EGL10.EGL_BAD_CONTEXT: - return "EGL_BAD_CONTEXT"; - case EGL10.EGL_BAD_CURRENT_SURFACE: - return "EGL_BAD_CURRENT_SURFACE"; - case EGL10.EGL_BAD_DISPLAY: - return "EGL_BAD_DISPLAY"; - case EGL10.EGL_BAD_MATCH: - return "EGL_BAD_MATCH"; - case EGL10.EGL_BAD_NATIVE_PIXMAP: - return "EGL_BAD_NATIVE_PIXMAP"; - case EGL10.EGL_BAD_NATIVE_WINDOW: - return "EGL_BAD_NATIVE_WINDOW"; - case EGL10.EGL_BAD_PARAMETER: - return "EGL_BAD_PARAMETER"; - case EGL10.EGL_BAD_SURFACE: - return "EGL_BAD_SURFACE"; - case EGL11.EGL_CONTEXT_LOST: - return "EGL_CONTEXT_LOST"; - default: - return "0x" + Integer.toHexString(error); - } - } - void finish() { mFinished = true; } |