ImageWallpaper.java revision a8e5a2bcd6a0d35893187c6df42425c03be005da
1bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker/* 256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * Copyright (C) 2009 The Android Open Source Project 356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * 456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * Licensed under the Apache License, Version 2.0 (the "License"); 556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * you may not use this file except in compliance with the License. 656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * You may obtain a copy of the License at 756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * 856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * http://www.apache.org/licenses/LICENSE-2.0 956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * 1056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * Unless required by applicable law or agreed to in writing, software 1156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * distributed under the License is distributed on an "AS IS" BASIS, 1256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * See the License for the specific language governing permissions and 1456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * limitations under the License. 1556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker */ 1656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 1756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerpackage com.android.systemui; 1856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 1956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.app.ActivityManager; 2056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.app.WallpaperManager; 2156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.content.BroadcastReceiver; 2256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.content.Context; 2356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.content.Intent; 2456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.graphics.Bitmap; 257eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinkerimport android.graphics.Canvas; 2656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.graphics.Rect; 2756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.graphics.Region.Op; 2856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.opengl.GLUtils; 2956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.os.SystemProperties; 3056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.renderscript.Matrix4f; 3156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.service.wallpaper.WallpaperService; 3256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.util.Log; 3356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.view.Display; 3456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.view.MotionEvent; 3556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.view.SurfaceHolder; 3656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport android.view.WindowManager; 3756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 387eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinkerimport javax.microedition.khronos.egl.EGL10; 397eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinkerimport javax.microedition.khronos.egl.EGLConfig; 4056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport javax.microedition.khronos.egl.EGLContext; 4156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport javax.microedition.khronos.egl.EGLDisplay; 4256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport javax.microedition.khronos.egl.EGLSurface; 4356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport javax.microedition.khronos.opengles.GL; 4456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport java.io.IOException; 4556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport java.nio.ByteBuffer; 4656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport java.nio.ByteOrder; 4756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport java.nio.FloatBuffer; 4856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 4956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport static android.opengl.GLES20.*; 5056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerimport static javax.microedition.khronos.egl.EGL10.*; 5156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 5256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker/** 5356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker * Default built-in wallpaper that simply shows a static image. 5456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker */ 5556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker@SuppressWarnings({"UnusedDeclaration"}) 5656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinkerpublic class ImageWallpaper extends WallpaperService { 5756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final String TAG = "ImageWallpaper"; 5856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final String GL_LOG_TAG = "ImageWallpaperGL"; 5956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final boolean DEBUG = false; 6056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu"; 6156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 6256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker static final boolean FIXED_SIZED_SURFACE = true; 63611d3d481605049c8ca77f27131282993f448664Jeff Tinker static final boolean USE_OPENGL = true; 64611d3d481605049c8ca77f27131282993f448664Jeff Tinker 65611d3d481605049c8ca77f27131282993f448664Jeff Tinker WallpaperManager mWallpaperManager; 66611d3d481605049c8ca77f27131282993f448664Jeff Tinker 67611d3d481605049c8ca77f27131282993f448664Jeff Tinker boolean mIsHwAccelerated; 6856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 6956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 7056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker public void onCreate() { 7156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker super.onCreate(); 7256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE); 7356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 7456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker //noinspection PointlessBooleanExpression,ConstantConditions 7556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (FIXED_SIZED_SURFACE && USE_OPENGL) { 7656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (!isEmulator()) { 7756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker WindowManager windowManager = 7856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker (WindowManager) getSystemService(Context.WINDOW_SERVICE); 7956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Display display = windowManager.getDefaultDisplay(); 807eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker mIsHwAccelerated = ActivityManager.isHighEndGfx(display); 81bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 82bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 8346722ff44a979c4674c5668189f631d8f77929fdRonghua Wu } 849a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 859a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private static boolean isEmulator() { 869a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0")); 8756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 8856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 89bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker public Engine onCreateEngine() { 90bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker return new DrawableEngine(); 91b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 92b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 93bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker class DrawableEngine extends Engine { 94bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 95b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker static final int EGL_OPENGL_ES2_BIT = 4; 96b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 9756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private final Object mLock = new Object[0]; 9856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 9906a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker // TODO: Not currently used, keeping around until we know we don't need it 10006a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker @SuppressWarnings({"UnusedDeclaration"}) 10106a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker private WallpaperObserver mReceiver; 10206a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker 10306a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker Bitmap mBackground; 10406a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker int mBackgroundWidth = -1, mBackgroundHeight = -1; 10506a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker float mXOffset; 10606a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker float mYOffset; 10706a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker 1089a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker boolean mVisible = true; 1099a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker boolean mRedrawNeeded; 1109a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker boolean mOffsetsChanged; 1119a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker int mLastXTranslation; 1129a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker int mLastYTranslation; 1139a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 1149a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private EGL10 mEgl; 1159a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private EGLDisplay mEglDisplay; 1169a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private EGLConfig mEglConfig; 1179a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private EGLContext mEglContext; 1189a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private EGLSurface mEglSurface; 1199a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private GL mGL; 1209a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 1219a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private static final String sSimpleVS = 1229a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker "attribute vec4 position;\n" + 1239a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker "attribute vec2 texCoords;\n" + 1249a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker "varying vec2 outTexCoords;\n" + 1259a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker "uniform mat4 projection;\n" + 12656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "\nvoid main(void) {\n" + 12756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker " outTexCoords = texCoords;\n" + 12856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker " gl_Position = projection * position;\n" + 12956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "}\n\n"; 13056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final String sSimpleFS = 13156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "precision mediump float;\n\n" + 13256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "varying vec2 outTexCoords;\n" + 13356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "uniform sampler2D texture;\n" + 13456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker "\nvoid main(void) {\n" + 13556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker " gl_FragColor = texture2D(texture, outTexCoords);\n" + 136bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker "}\n\n"; 137bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 138bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker private static final int FLOAT_SIZE_BYTES = 4; 13956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 14056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 141b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 142b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 143b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker class WallpaperObserver extends BroadcastReceiver { 144b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker public void onReceive(Context context, Intent intent) { 145b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker if (DEBUG) { 146b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker Log.d(TAG, "onReceive"); 147b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 148bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 14956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker synchronized (mLock) { 150bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mBackgroundWidth = mBackgroundHeight = -1; 15156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mBackground = null; 152b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker mRedrawNeeded = true; 153b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker drawFrameLocked(); 154b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 155b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 15656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 157b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 15856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 159bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker public void onCreate(SurfaceHolder surfaceHolder) { 160bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (DEBUG) { 16156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "onCreate"); 162bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 16356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 164b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker super.onCreate(surfaceHolder); 165bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 166bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // TODO: Don't need this currently because the wallpaper service 167bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // will restart the image wallpaper whenever the image changes. 16806a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); 16906a8cd6d19a20843d137f7e65f4c81da685c291eJeff Tinker //mReceiver = new WallpaperObserver(); 17056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker //registerReceiver(mReceiver, filter, null, mHandler); 171b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 172bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker updateSurfaceSize(surfaceHolder); 173b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 174b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker setOffsetNotificationsEnabled(false); 175b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 176b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 177b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker @Override 178b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker public void onDestroy() { 179b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker super.onDestroy(); 180b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker if (mReceiver != null) { 181b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker unregisterReceiver(mReceiver); 182b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 183b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker } 184b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker 185b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker @Override 186bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) { 187bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker super.onDesiredSizeChanged(desiredWidth, desiredHeight); 18856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker SurfaceHolder surfaceHolder = getSurfaceHolder(); 189b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker if (surfaceHolder != null) { 190b84d1cad1d481f75aa03d55ac07e4ff58dbfb84aJeff Tinker updateSurfaceSize(surfaceHolder); 191bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 192bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 193bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 194bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker void updateSurfaceSize(SurfaceHolder surfaceHolder) { 195bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (FIXED_SIZED_SURFACE) { 19656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker // Used a fixed size surface, because we are special. We can do 19756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker // this because we know the current design of window animations doesn't 19856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker // cause this to break. 19956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker surfaceHolder.setFixedSize(getDesiredMinimumWidth(), getDesiredMinimumHeight()); 20056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } else { 20156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker surfaceHolder.setSizeFromLayout(); 20256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 203bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 204bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 20556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 20656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker public void onVisibilityChanged(boolean visible) { 20756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 208bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker Log.d(TAG, "onVisibilityChanged: visible=" + visible); 20956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 21056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 21156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker synchronized (mLock) { 212c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker if (mVisible != visible) { 213c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker if (DEBUG) { 214c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker Log.d(TAG, "Visibility changed to visible=" + visible); 21556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 21656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mVisible = visible; 21756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker drawFrameLocked(); 21856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 219c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker } 220c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker } 221c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker 22256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 223bc6b9e7f8a6b991263906c1b0bd1db0e45b59282Jeff Tinker public void onTouchEvent(MotionEvent event) { 224bc6b9e7f8a6b991263906c1b0bd1db0e45b59282Jeff Tinker super.onTouchEvent(event); 225bc6b9e7f8a6b991263906c1b0bd1db0e45b59282Jeff Tinker } 22656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 22756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 22856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker public void onOffsetsChanged(float xOffset, float yOffset, 22956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker float xOffsetStep, float yOffsetStep, 23056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker int xPixels, int yPixels) { 23156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 23256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset 23356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep 23456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker + ", xPixels=" + xPixels + ", yPixels=" + yPixels); 23556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 23656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 23756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker synchronized (mLock) { 23856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (mXOffset != xOffset || mYOffset != yOffset) { 23956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 24056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ")."); 24156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 24256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mXOffset = xOffset; 24357481590b98518865e266004e7ca4737abd5508dJeff Tinker mYOffset = yOffset; 24456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mOffsetsChanged = true; 24557481590b98518865e266004e7ca4737abd5508dJeff Tinker } 24656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker drawFrameLocked(); 24756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 24856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 24956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 25056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker @Override 25156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 25256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 25356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height); 25456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 25556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 25656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker super.onSurfaceChanged(holder, format, width, height); 25756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 25856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker synchronized (mLock) { 25956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker mRedrawNeeded = true; 26056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker drawFrameLocked(); 26156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 26256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 26356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 26456c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker void drawFrameLocked() { 26556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (!mVisible) { 26656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 26756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible."); 26856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 26956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker return; 27056c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 27156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (!mRedrawNeeded && !mOffsetsChanged) { 27256c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (DEBUG) { 27356c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker Log.d(TAG, "Suppressed drawFrame since redraw is not needed " 274bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker + "and offsets have not changed."); 275bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 276bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker return; 277bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 278bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 279bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (mBackgroundWidth < 0 || mBackgroundHeight < 0) { 280bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // If we don't yet know the size of the wallpaper bitmap, 281bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // we need to get it now. 282bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker updateWallpaperLocked(); 283bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 284bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 285bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker SurfaceHolder sh = getSurfaceHolder(); 286bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker final Rect frame = sh.getSurfaceFrame(); 287bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker final int dw = frame.width(); 288bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker final int dh = frame.height(); 289bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker final int availw = dw - mBackgroundWidth; 290bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker final int availh = dh - mBackgroundHeight; 291bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2); 292bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2); 293bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 294bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mOffsetsChanged = false; 295bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (!mRedrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { 296bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (DEBUG) { 297bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker Log.d(TAG, "Suppressed drawFrame since the image has not " 298bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker + "actually moved an integral number of pixels."); 299bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 300bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker return; 301bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 302bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mRedrawNeeded = false; 303bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mLastXTranslation = xPixels; 304bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mLastYTranslation = yPixels; 305bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 306bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (mBackground == null) { 307bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // If we somehow got to this point after we have last flushed 308bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // the wallpaper, well we really need it to draw again. So 309bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // seems like we need to reload it. Ouch. 310bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker updateWallpaperLocked(); 311bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 312bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 313bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (mIsHwAccelerated) { 314bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) { 315bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); 316bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 317bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } else { 318bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); 319bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 320bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 321bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker if (FIXED_SIZED_SURFACE) { 322bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // If the surface is fixed-size, we should only need to 323bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // draw it once and then we'll let the window manager 324bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // position it appropriately. As such, we no longer needed 325bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker // the loaded bitmap. Yay! 326bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mBackground = null; 327bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker mWallpaperManager.forgetLoadedWallpaper(); 328bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 329bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 330bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker 331bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker void updateWallpaperLocked() { 332bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker Throwable exception = null; 333c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker try { 334c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker mBackground = mWallpaperManager.getBitmap(); 335c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker } catch (RuntimeException e) { 336c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker exception = e; 337c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker } catch (OutOfMemoryError e) { 338c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker exception = e; 339c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker } 340c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker 341c2f10f20ec9be98f363d6739ba1552955efe6532Jeff Tinker if (exception != null) { 3427eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker mBackground = null; 3437eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker // Note that if we do fail at this, and the default wallpaper can't 3447eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker // be loaded, we will go into a cycle. Don't do a build where the 3457eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker // default wallpaper can't be loaded. 3467eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker Log.w(TAG, "Unable to load wallpaper!", exception); 3477eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker try { 3487eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker mWallpaperManager.clear(); 3499a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } catch (IOException ex) { 3507eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker // now we're really screwed. 3517eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker Log.w(TAG, "Unable reset to default wallpaper!", ex); 3527eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker } 353bcbd78bd246f1e68e44b4a6d6257dbfcec8e65b3Jeff Tinker } 3549a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 3559a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker mBackgroundWidth = mBackground != null ? mBackground.getWidth() : 0; 3569a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker mBackgroundHeight = mBackground != null ? mBackground.getHeight() : 0; 3579a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } 3589a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 3599a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) { 3609a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker Canvas c = sh.lockCanvas(); 36156c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (c != null) { 3627eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker try { 3637eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker if (DEBUG) { 3647eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker Log.d(TAG, "Redrawing: x=" + x + ", y=" + y); 36556c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker } 36656c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker 36756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker c.translate(x, y); 3687eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker if (w < 0 || h < 0) { 3697eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker c.save(Canvas.CLIP_SAVE_FLAG); 3707eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE); 3717eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker c.drawColor(0xff000000); 3729a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker c.restore(); 3737eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker } 3749a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker if (mBackground != null) { 3759a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker c.drawBitmap(mBackground, 0, 0, null); 3769a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } 3779a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } finally { 3789a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker sh.unlockCanvasAndPost(c); 3799a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } 3809a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker } 3817eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker } 3827eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker 3837eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) { 3847eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker if (!initGL(sh)) return false; 3857eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker 3867eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker final float right = left + mBackgroundWidth; 3877eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker final float bottom = top + mBackgroundHeight; 3887eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker 3897eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker final Rect frame = sh.getSurfaceFrame(); 3907eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker 3917eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker final Matrix4f ortho = new Matrix4f(); 3927eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f); 3937eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker 3947eafcae5ffb7f6f12ee573dea685dc6989a0ee91Jeff Tinker final FloatBuffer triangleVertices = createMesh(left, top, right, bottom); 3959a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 3969a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int texture = loadTexture(mBackground); 3979a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int program = buildProgram(sSimpleVS, sSimpleFS); 3989a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 3999a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int attribPosition = glGetAttribLocation(program, "position"); 4009a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int attribTexCoords = glGetAttribLocation(program, "texCoords"); 4019a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int uniformTexture = glGetUniformLocation(program, "texture"); 4029a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker final int uniformProjection = glGetUniformLocation(program, "projection"); 4039a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 4049a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker checkGlError(); 4059a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 4069a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glViewport(0, 0, frame.width(), frame.height()); 4079a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glBindTexture(GL_TEXTURE_2D, texture); 4089a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 4099a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glUseProgram(program); 4109a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glEnableVertexAttribArray(attribPosition); 4119a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glEnableVertexAttribArray(attribTexCoords); 4129a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glUniform1i(uniformTexture, 0); 4139a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0); 4149a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 4159a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker checkGlError(); 4169a498ef11566a5ae82c24b0651c58280309dfd04Jeff Tinker 41756c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker if (w < 0 || h < 0) { 41856c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 41956c78c47d8c22621a8a23375d8a6c63d99a9335dJeff Tinker glClear(GL_COLOR_BUFFER_BIT); 420 } 421 422 // drawQuad 423 triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 424 glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false, 425 TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); 426 427 triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 428 glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false, 429 TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices); 430 431 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 432 433 if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 434 throw new RuntimeException("Cannot swap buffers"); 435 } 436 checkEglError(); 437 438 finishGL(); 439 440 return true; 441 } 442 443 private FloatBuffer createMesh(int left, int top, float right, float bottom) { 444 final float[] verticesData = { 445 // X, Y, Z, U, V 446 left, bottom, 0.0f, 0.0f, 1.0f, 447 right, bottom, 0.0f, 1.0f, 1.0f, 448 left, top, 0.0f, 0.0f, 0.0f, 449 right, top, 0.0f, 1.0f, 0.0f, 450 }; 451 452 final int bytes = verticesData.length * FLOAT_SIZE_BYTES; 453 final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order( 454 ByteOrder.nativeOrder()).asFloatBuffer(); 455 triangleVertices.put(verticesData).position(0); 456 return triangleVertices; 457 } 458 459 private int loadTexture(Bitmap bitmap) { 460 int[] textures = new int[1]; 461 462 glActiveTexture(GL_TEXTURE0); 463 glGenTextures(1, textures, 0); 464 checkGlError(); 465 466 int texture = textures[0]; 467 glBindTexture(GL_TEXTURE_2D, texture); 468 checkGlError(); 469 470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 472 473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 475 476 GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0); 477 checkGlError(); 478 479 bitmap.recycle(); 480 481 return texture; 482 } 483 484 private int buildProgram(String vertex, String fragment) { 485 int vertexShader = buildShader(vertex, GL_VERTEX_SHADER); 486 if (vertexShader == 0) return 0; 487 488 int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER); 489 if (fragmentShader == 0) return 0; 490 491 int program = glCreateProgram(); 492 glAttachShader(program, vertexShader); 493 checkGlError(); 494 495 glAttachShader(program, fragmentShader); 496 checkGlError(); 497 498 glLinkProgram(program); 499 checkGlError(); 500 501 int[] status = new int[1]; 502 glGetProgramiv(program, GL_LINK_STATUS, status, 0); 503 if (status[0] != GL_TRUE) { 504 String error = glGetProgramInfoLog(program); 505 Log.d(GL_LOG_TAG, "Error while linking program:\n" + error); 506 glDeleteShader(vertexShader); 507 glDeleteShader(fragmentShader); 508 glDeleteProgram(program); 509 return 0; 510 } 511 512 return program; 513 } 514 515 private int buildShader(String source, int type) { 516 int shader = glCreateShader(type); 517 518 glShaderSource(shader, source); 519 checkGlError(); 520 521 glCompileShader(shader); 522 checkGlError(); 523 524 int[] status = new int[1]; 525 glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0); 526 if (status[0] != GL_TRUE) { 527 String error = glGetShaderInfoLog(shader); 528 Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error); 529 glDeleteShader(shader); 530 return 0; 531 } 532 533 return shader; 534 } 535 536 private void checkEglError() { 537 int error = mEgl.eglGetError(); 538 if (error != EGL_SUCCESS) { 539 Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error)); 540 } 541 } 542 543 private void checkGlError() { 544 int error = glGetError(); 545 if (error != GL_NO_ERROR) { 546 Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable()); 547 } 548 } 549 550 private void finishGL() { 551 mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 552 mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 553 mEgl.eglDestroyContext(mEglDisplay, mEglContext); 554 } 555 556 private boolean initGL(SurfaceHolder surfaceHolder) { 557 mEgl = (EGL10) EGLContext.getEGL(); 558 559 mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 560 if (mEglDisplay == EGL_NO_DISPLAY) { 561 throw new RuntimeException("eglGetDisplay failed " + 562 GLUtils.getEGLErrorString(mEgl.eglGetError())); 563 } 564 565 int[] version = new int[2]; 566 if (!mEgl.eglInitialize(mEglDisplay, version)) { 567 throw new RuntimeException("eglInitialize failed " + 568 GLUtils.getEGLErrorString(mEgl.eglGetError())); 569 } 570 571 mEglConfig = chooseEglConfig(); 572 if (mEglConfig == null) { 573 throw new RuntimeException("eglConfig not initialized"); 574 } 575 576 mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); 577 578 mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null); 579 580 if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { 581 int error = mEgl.eglGetError(); 582 if (error == EGL_BAD_NATIVE_WINDOW) { 583 Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 584 return false; 585 } 586 throw new RuntimeException("createWindowSurface failed " + 587 GLUtils.getEGLErrorString(error)); 588 } 589 590 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 591 throw new RuntimeException("eglMakeCurrent failed " + 592 GLUtils.getEGLErrorString(mEgl.eglGetError())); 593 } 594 595 mGL = mEglContext.getGL(); 596 597 return true; 598 } 599 600 601 EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 602 int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 603 return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list); 604 } 605 606 private EGLConfig chooseEglConfig() { 607 int[] configsCount = new int[1]; 608 EGLConfig[] configs = new EGLConfig[1]; 609 int[] configSpec = getConfig(); 610 if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { 611 throw new IllegalArgumentException("eglChooseConfig failed " + 612 GLUtils.getEGLErrorString(mEgl.eglGetError())); 613 } else if (configsCount[0] > 0) { 614 return configs[0]; 615 } 616 return null; 617 } 618 619 private int[] getConfig() { 620 return new int[] { 621 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 622 EGL_RED_SIZE, 8, 623 EGL_GREEN_SIZE, 8, 624 EGL_BLUE_SIZE, 8, 625 EGL_ALPHA_SIZE, 0, 626 EGL_DEPTH_SIZE, 0, 627 EGL_STENCIL_SIZE, 0, 628 EGL_NONE 629 }; 630 } 631 } 632} 633