14c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn/*
24c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Copyright (C) 2009 The Android Open Source Project
34c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
44c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
54c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * you may not use this file except in compliance with the License.
64c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * You may obtain a copy of the License at
74c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
84c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
94c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
104c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
114c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
124c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * See the License for the specific language governing permissions and
144c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * limitations under the License.
154c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn */
164c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
17ba39839444532af0ed3766f736582413f6d7a40bDianne Hackbornpackage com.android.systemui;
184c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
19407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.app.ActivityManager;
204c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.app.WallpaperManager;
21407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.BroadcastReceiver;
22c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haaseimport android.content.ComponentCallbacks2;
23407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.Context;
24407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.Intent;
25407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.graphics.Bitmap;
264c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.graphics.Canvas;
27759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackbornimport android.graphics.Rect;
28e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopianimport android.graphics.Region.Op;
29407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.opengl.GLUtils;
30043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guyimport android.os.SystemProperties;
31407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.renderscript.Matrix4f;
324c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.WallpaperService;
33c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackbornimport android.util.Log;
342f20081f9fd734e466147bf1091d06cc7331458cChet Haaseimport android.view.Display;
358df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackbornimport android.view.MotionEvent;
364c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.view.SurfaceHolder;
372f20081f9fd734e466147bf1091d06cc7331458cChet Haaseimport android.view.WindowManager;
38407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
39407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.egl.EGL10;
40407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.egl.EGLConfig;
41407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.egl.EGLContext;
42407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.egl.EGLDisplay;
43407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.egl.EGLSurface;
44407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport javax.microedition.khronos.opengles.GL;
45407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.io.IOException;
46407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.ByteBuffer;
47407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.ByteOrder;
48407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.FloatBuffer;
49407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
50407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport static android.opengl.GLES20.*;
51407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport static javax.microedition.khronos.egl.EGL10.*;
524c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
534c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn/**
544c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Default built-in wallpaper that simply shows a static image.
554c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn */
56407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy@SuppressWarnings({"UnusedDeclaration"})
574c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornpublic class ImageWallpaper extends WallpaperService {
58fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown    private static final String TAG = "ImageWallpaper";
59407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    private static final String GL_LOG_TAG = "ImageWallpaperGL";
60fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown    private static final boolean DEBUG = false;
61043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
62fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
63ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn    static final boolean FIXED_SIZED_SURFACE = true;
64881fb2092b41f4447e708da2f341d2ca5602c0d4Erik Gilling    static final boolean USE_OPENGL = true;
65ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
66ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    WallpaperManager mWallpaperManager;
67407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
68c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    DrawableEngine mEngine;
69c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
70407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    boolean mIsHwAccelerated;
71ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
72ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    @Override
73ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    public void onCreate() {
74ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        super.onCreate();
75ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
76407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
77407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        //noinspection PointlessBooleanExpression,ConstantConditions
78407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        if (FIXED_SIZED_SURFACE && USE_OPENGL) {
79043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy            if (!isEmulator()) {
8098365d7663cbd82979a5700faf0050220b01084dJeff Brown                mIsHwAccelerated = ActivityManager.isHighEndGfx();
81043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy            }
82407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
83ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    }
84ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
85c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    @Override
86c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    public void onTrimMemory(int level) {
87c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        if (mEngine != null) {
88c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            mEngine.trimMemory(level);
89c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        }
90c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    }
91c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
92043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    private static boolean isEmulator() {
93043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy        return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
94043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    }
95043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy
96ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    public Engine onCreateEngine() {
97c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        mEngine = new DrawableEngine();
98c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        return mEngine;
99ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    }
100ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
101ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    class DrawableEngine extends Engine {
102407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
103407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        static final int EGL_OPENGL_ES2_BIT = 4;
104407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
105407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private final Object mLock = new Object[0];
106407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
107407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        // TODO: Not currently used, keeping around until we know we don't need it
108407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        @SuppressWarnings({"UnusedDeclaration"})
109284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        private WallpaperObserver mReceiver;
110407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
111407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        Bitmap mBackground;
1125f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase        int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
1132f20081f9fd734e466147bf1091d06cc7331458cChet Haase        int mLastRotation = -1;
1147341d7a104b47996445d069a695e155a07184606Dianne Hackborn        float mXOffset;
1157341d7a104b47996445d069a695e155a07184606Dianne Hackborn        float mYOffset;
116759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn
117fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mVisible = true;
118fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mRedrawNeeded;
119fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mOffsetsChanged;
120fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        int mLastXTranslation;
121fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        int mLastYTranslation;
122fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
123407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGL10 mEgl;
124407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLDisplay mEglDisplay;
125407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLConfig mEglConfig;
126407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLContext mEglContext;
127407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLSurface mEglSurface;
128407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private GL mGL;
129407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
130407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final String sSimpleVS =
131407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "attribute vec4 position;\n" +
132407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "attribute vec2 texCoords;\n" +
133407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "varying vec2 outTexCoords;\n" +
134407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "uniform mat4 projection;\n" +
135407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "\nvoid main(void) {\n" +
136407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    outTexCoords = texCoords;\n" +
137407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    gl_Position = projection * position;\n" +
138407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "}\n\n";
139407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final String sSimpleFS =
140407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "precision mediump float;\n\n" +
141407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "varying vec2 outTexCoords;\n" +
142407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "uniform sampler2D texture;\n" +
143407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "\nvoid main(void) {\n" +
144407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
145407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "}\n\n";
146407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
147407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int FLOAT_SIZE_BYTES = 4;
148407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
149407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
150407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
151407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
152284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        class WallpaperObserver extends BroadcastReceiver {
153284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            public void onReceive(Context context, Intent intent) {
15430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                if (DEBUG) {
15530bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    Log.d(TAG, "onReceive");
15630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                }
15730bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
158fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                synchronized (mLock) {
1595f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    mLastSurfaceWidth = mLastSurfaceHeight = -1;
160ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                    mBackground = null;
161ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                    mRedrawNeeded = true;
1622f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    drawFrameLocked();
163fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                }
164284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            }
165284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        }
166284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn
16735be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey        public DrawableEngine() {
16835be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey            super();
16935be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey            setFixedSizeAllowed(true);
17035be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey        }
17135be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey
172c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        public void trimMemory(int level) {
173c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
174c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mBackground != null && mIsHwAccelerated) {
1755f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (DEBUG) {
1765f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    Log.d(TAG, "trimMemory");
1775f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
178c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mBackground.recycle();
179c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mBackground = null;
180c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mWallpaperManager.forgetLoadedWallpaper();
181c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            }
182c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        }
183c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
1844c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        @Override
185759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        public void onCreate(SurfaceHolder surfaceHolder) {
18630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
18730bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onCreate");
18830bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
18930bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
190759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn            super.onCreate(surfaceHolder);
1919ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn
192407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // TODO: Don't need this currently because the wallpaper service
1939ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            // will restart the image wallpaper whenever the image changes.
1949ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
1959ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //mReceiver = new WallpaperObserver();
1969ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //registerReceiver(mReceiver, filter, null, mHandler);
197fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
198ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            updateSurfaceSize(surfaceHolder);
199a8e5a2bcd6a0d35893187c6df42425c03be005daChet Haase
200a8e5a2bcd6a0d35893187c6df42425c03be005daChet Haase            setOffsetNotificationsEnabled(false);
2014c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
2024c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
2034c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        @Override
204284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        public void onDestroy() {
205284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            super.onDestroy();
2069ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            if (mReceiver != null) {
2079ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn                unregisterReceiver(mReceiver);
2089ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            }
209284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        }
210284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn
211284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        @Override
212ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
213912d9d13698693709991b76f83a8d64179e97e83Dianne Hackborn            super.onDesiredSizeChanged(desiredWidth, desiredHeight);
214ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            SurfaceHolder surfaceHolder = getSurfaceHolder();
215ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            if (surfaceHolder != null) {
216ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn                updateSurfaceSize(surfaceHolder);
217ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            }
218ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        }
219ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn
220ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        void updateSurfaceSize(SurfaceHolder surfaceHolder) {
221ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            if (FIXED_SIZED_SURFACE) {
222ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // Used a fixed size surface, because we are special.  We can do
223ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // this because we know the current design of window animations doesn't
224ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // cause this to break.
225ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                surfaceHolder.setFixedSize(getDesiredMinimumWidth(), getDesiredMinimumHeight());
226ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            } else {
227ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                surfaceHolder.setSizeFromLayout();
228ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            }
229ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        }
230ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn
231ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        @Override
232759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        public void onVisibilityChanged(boolean visible) {
23330bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
2342f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
23530bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
23630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
237fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            synchronized (mLock) {
23830bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                if (mVisible != visible) {
23930bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    if (DEBUG) {
24030bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                        Log.d(TAG, "Visibility changed to visible=" + visible);
24130bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    }
24230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    mVisible = visible;
2432f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    drawFrameLocked();
24430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                }
245fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
246759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        }
247fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
248759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        @Override
2498df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        public void onTouchEvent(MotionEvent event) {
2508df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn            super.onTouchEvent(event);
2518df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        }
2528df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn
2538df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        @Override
25472c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        public void onOffsetsChanged(float xOffset, float yOffset,
255bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen                float xOffsetStep, float yOffsetStep,
25672c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn                int xPixels, int yPixels) {
25730bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
25830bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset
25930bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                        + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep
26030bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                        + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
26130bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
26230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
263fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            synchronized (mLock) {
264fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                if (mXOffset != xOffset || mYOffset != yOffset) {
265fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    if (DEBUG) {
266fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                        Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
267fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    }
268fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    mXOffset = xOffset;
269fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    mYOffset = yOffset;
27030bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    mOffsetsChanged = true;
271fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                }
2722f20081f9fd734e466147bf1091d06cc7331458cChet Haase                drawFrameLocked();
273fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
27472c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        }
27572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn
27672c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        @Override
2774c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
27830bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
27930bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height);
280fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
2814c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
28230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            super.onSurfaceChanged(holder, format, width, height);
2834c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
28430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            synchronized (mLock) {
2852f20081f9fd734e466147bf1091d06cc7331458cChet Haase                drawFrameLocked();
28630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
2874c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
288fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
289fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        @Override
2902f20081f9fd734e466147bf1091d06cc7331458cChet Haase        public void onSurfaceDestroyed(SurfaceHolder holder) {
2912f20081f9fd734e466147bf1091d06cc7331458cChet Haase            super.onSurfaceDestroyed(holder);
2925f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            mLastSurfaceWidth = mLastSurfaceHeight = -1;
2932f20081f9fd734e466147bf1091d06cc7331458cChet Haase        }
2942f20081f9fd734e466147bf1091d06cc7331458cChet Haase
2952f20081f9fd734e466147bf1091d06cc7331458cChet Haase        @Override
2962f20081f9fd734e466147bf1091d06cc7331458cChet Haase        public void onSurfaceCreated(SurfaceHolder holder) {
2972f20081f9fd734e466147bf1091d06cc7331458cChet Haase            super.onSurfaceCreated(holder);
2985f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            mLastSurfaceWidth = mLastSurfaceHeight = -1;
2992f20081f9fd734e466147bf1091d06cc7331458cChet Haase        }
3002f20081f9fd734e466147bf1091d06cc7331458cChet Haase
3012f20081f9fd734e466147bf1091d06cc7331458cChet Haase        @Override
302fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
303fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            if (DEBUG) {
3042f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "onSurfaceRedrawNeeded");
305fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            }
306fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            super.onSurfaceRedrawNeeded(holder);
307fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner
308fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            synchronized (mLock) {
3092f20081f9fd734e466147bf1091d06cc7331458cChet Haase                drawFrameLocked();
310fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            }
311fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        }
312fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner
3132f20081f9fd734e466147bf1091d06cc7331458cChet Haase        void drawFrameLocked() {
3142f20081f9fd734e466147bf1091d06cc7331458cChet Haase            SurfaceHolder sh = getSurfaceHolder();
3152f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final Rect frame = sh.getSurfaceFrame();
3162f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final int dw = frame.width();
3172f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final int dh = frame.height();
3182f20081f9fd734e466147bf1091d06cc7331458cChet Haase            int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
3192f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    getDefaultDisplay().getRotation();
3205f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
3212f20081f9fd734e466147bf1091d06cc7331458cChet Haase
3225f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
3232f20081f9fd734e466147bf1091d06cc7331458cChet Haase            if (!redrawNeeded && !mOffsetsChanged) {
3242f20081f9fd734e466147bf1091d06cc7331458cChet Haase                if (DEBUG) {
3252f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
3262f20081f9fd734e466147bf1091d06cc7331458cChet Haase                            + "and offsets have not changed.");
327fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                }
3282f20081f9fd734e466147bf1091d06cc7331458cChet Haase                return;
329fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
3302f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastRotation = newRotation;
331321357b6066a34cc12a0528b7b835c7664db2e08Michael Jurka
3322f20081f9fd734e466147bf1091d06cc7331458cChet Haase            // Load bitmap if it is not yet loaded or if it was loaded at a different size
3335f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            if (mBackground == null || surfaceDimensionsChanged) {
3342f20081f9fd734e466147bf1091d06cc7331458cChet Haase                if (DEBUG) {
3355f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
3365f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            mBackground + ", " +
3375f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
3385f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
3395f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            dw + ", " + dh);
3402f20081f9fd734e466147bf1091d06cc7331458cChet Haase                }
341ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                updateWallpaperLocked();
3425f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (mBackground == null) {
3435f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    if (DEBUG) {
3445f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        Log.d(TAG, "Unable to load bitmap");
3455f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    }
3465f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    return;
3475f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
3485f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (DEBUG) {
3495f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
3505f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
3515f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
3525f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                mBackground.getHeight());
3535f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    }
3545f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
355ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            }
356ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
3575f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final int availw = dw - mBackground.getWidth();
3585f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final int availh = dh - mBackground.getHeight();
359033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
360033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
361033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown
362033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            mOffsetsChanged = false;
3632f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mRedrawNeeded = false;
3645f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            if (surfaceDimensionsChanged) {
3655f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                mLastSurfaceWidth = dw;
3665f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                mLastSurfaceHeight = dh;
3675f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            }
3682f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastXTranslation = xPixels;
3692f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastYTranslation = yPixels;
3702f20081f9fd734e466147bf1091d06cc7331458cChet Haase            if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
371033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                if (DEBUG) {
372033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                    Log.d(TAG, "Suppressed drawFrame since the image has not "
373033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                            + "actually moved an integral number of pixels.");
374033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                }
375033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                return;
376033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            }
377033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown
378c92f150af0fb93b677a4ec6e2aca1b9a9bdd8760Craig Mautner            if (DEBUG) {
3792f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "Redrawing wallpaper");
380c92f150af0fb93b677a4ec6e2aca1b9a9bdd8760Craig Mautner            }
381407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mIsHwAccelerated) {
382f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
383f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                    drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
384f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                }
385407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            } else {
386407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
387c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                if (FIXED_SIZED_SURFACE) {
388c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // If the surface is fixed-size, we should only need to
389c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // draw it once and then we'll let the window manager
390c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // position it appropriately.  As such, we no longer needed
391c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // the loaded bitmap.  Yay!
392c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // hw-accelerated path retains bitmap for faster rotation
393c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mBackground = null;
394c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mWallpaperManager.forgetLoadedWallpaper();
395c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                }
396759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn            }
397ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
398759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        }
399ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
4005f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase        private void updateWallpaperLocked() {
401fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            Throwable exception = null;
402fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            try {
4035f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                mWallpaperManager.forgetLoadedWallpaper(); // force reload
404589a6af173c10738d2a83c69a9dda36579cc739dChet Haase                mBackground = null;
405407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                mBackground = mWallpaperManager.getBitmap();
406fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            } catch (RuntimeException e) {
407fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                exception = e;
408fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            } catch (OutOfMemoryError e) {
409fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                exception = e;
410fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
411407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
412fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            if (exception != null) {
413fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                mBackground = null;
414fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // Note that if we do fail at this, and the default wallpaper can't
415fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // be loaded, we will go into a cycle.  Don't do a build where the
416fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // default wallpaper can't be loaded.
417fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                Log.w(TAG, "Unable to load wallpaper!", exception);
418c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                try {
419fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    mWallpaperManager.clear();
420fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                } catch (IOException ex) {
421fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    // now we're really screwed.
422fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    Log.w(TAG, "Unable reset to default wallpaper!", ex);
423c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                }
424ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy            }
425407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
426407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
427407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) {
428407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            Canvas c = sh.lockCanvas();
429407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (c != null) {
430407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                try {
431407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (DEBUG) {
432407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        Log.d(TAG, "Redrawing: x=" + x + ", y=" + y);
433407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
434407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
435407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    c.translate(x, y);
436407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (w < 0 || h < 0) {
437407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.save(Canvas.CLIP_SAVE_FLAG);
4385f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        c.clipRect(0, 0, mBackground.getWidth(), mBackground.getHeight(),
4395f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                Op.DIFFERENCE);
440407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.drawColor(0xff000000);
441407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.restore();
442407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
443407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (mBackground != null) {
444407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.drawBitmap(mBackground, 0, 0, null);
445407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
446407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                } finally {
447407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    sh.unlockCanvasAndPost(c);
448407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                }
449407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
450407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
451407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
452f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy        private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
453f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            if (!initGL(sh)) return false;
454407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
4555f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final float right = left + mBackground.getWidth();
4565f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final float bottom = top + mBackground.getHeight();
457407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
458407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final Rect frame = sh.getSurfaceFrame();
459407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final Matrix4f ortho = new Matrix4f();
460407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
461407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
462407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final FloatBuffer triangleVertices = createMesh(left, top, right, bottom);
463407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
464407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int texture = loadTexture(mBackground);
465407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int program = buildProgram(sSimpleVS, sSimpleFS);
4662f20081f9fd734e466147bf1091d06cc7331458cChet Haase
467407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int attribPosition = glGetAttribLocation(program, "position");
468407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int attribTexCoords = glGetAttribLocation(program, "texCoords");
469407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int uniformTexture = glGetUniformLocation(program, "texture");
470407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int uniformProjection = glGetUniformLocation(program, "projection");
471407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
472407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
473407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
474407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glViewport(0, 0, frame.width(), frame.height());
475407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glBindTexture(GL_TEXTURE_2D, texture);
476407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
477407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUseProgram(program);
478407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glEnableVertexAttribArray(attribPosition);
479407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glEnableVertexAttribArray(attribTexCoords);
480407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUniform1i(uniformTexture, 0);
481407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0);
482407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
483407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
484407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
485407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (w < 0 || h < 0) {
486407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
487407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glClear(GL_COLOR_BUFFER_BIT);
488407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
4892f20081f9fd734e466147bf1091d06cc7331458cChet Haase
490407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // drawQuad
491407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
492407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
493407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
494407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
495407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
496407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
497407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
498407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
499407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5002f20081f9fd734e466147bf1091d06cc7331458cChet Haase
501407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
502407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("Cannot swap buffers");
503407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
504407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkEglError();
5052f20081f9fd734e466147bf1091d06cc7331458cChet Haase
506407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            finishGL();
507f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy
508f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            return true;
509407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
510407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
511407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private FloatBuffer createMesh(int left, int top, float right, float bottom) {
512407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final float[] verticesData = {
513407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    // X, Y, Z, U, V
514407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     left,  bottom, 0.0f, 0.0f, 1.0f,
515407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     right, bottom, 0.0f, 1.0f, 1.0f,
516407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     left,  top,    0.0f, 0.0f, 0.0f,
517407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     right, top,    0.0f, 1.0f, 0.0f,
518407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            };
519407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
520407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int bytes = verticesData.length * FLOAT_SIZE_BYTES;
521407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order(
522407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    ByteOrder.nativeOrder()).asFloatBuffer();
523407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.put(verticesData).position(0);
524407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return triangleVertices;
525407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
526407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
527407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int loadTexture(Bitmap bitmap) {
528407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] textures = new int[1];
529407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
530407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glActiveTexture(GL_TEXTURE0);
531407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGenTextures(1, textures, 0);
532407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
533407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
534407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int texture = textures[0];
535407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glBindTexture(GL_TEXTURE_2D, texture);
536407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
537407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
538407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
539407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
540407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
541407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
542407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
543407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
544407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
545407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
546407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
547407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return texture;
548407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
549407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
550407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int buildProgram(String vertex, String fragment) {
551407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
552407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (vertexShader == 0) return 0;
553407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
554407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
555407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (fragmentShader == 0) return 0;
556407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
557407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int program = glCreateProgram();
558407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glAttachShader(program, vertexShader);
559407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
560407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
561407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glAttachShader(program, fragmentShader);
562407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
563407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
564407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glLinkProgram(program);
565407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
566407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
567407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] status = new int[1];
568407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
569407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (status[0] != GL_TRUE) {
570407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                String error = glGetProgramInfoLog(program);
571407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.d(GL_LOG_TAG, "Error while linking program:\n" + error);
572407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(vertexShader);
573407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(fragmentShader);
574407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteProgram(program);
575407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return 0;
576407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
577407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
578407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return program;
579407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
580407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
581407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int buildShader(String source, int type) {
582407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int shader = glCreateShader(type);
583407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
584407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glShaderSource(shader, source);
585407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
586407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
587407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glCompileShader(shader);
588407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
589407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
590407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] status = new int[1];
591407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
592407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (status[0] != GL_TRUE) {
593407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                String error = glGetShaderInfoLog(shader);
594407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error);
595407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(shader);
596407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return 0;
597407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
598407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
599407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return shader;
600407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
601407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
602407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void checkEglError() {
603407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int error = mEgl.eglGetError();
604407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (error != EGL_SUCCESS) {
605407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error));
606407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
607407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
608407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
609407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void checkGlError() {
610407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int error = glGetError();
611407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (error != GL_NO_ERROR) {
612407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable());
613407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
614407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
615407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
616407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void finishGL() {
617f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
618407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
619f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
620407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
621407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
622f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy        private boolean initGL(SurfaceHolder surfaceHolder) {
623407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEgl = (EGL10) EGLContext.getEGL();
624407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
625407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
626407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglDisplay == EGL_NO_DISPLAY) {
627407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglGetDisplay failed " +
628407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
629407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
630407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
631407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] version = new int[2];
632407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglInitialize(mEglDisplay, version)) {
633407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglInitialize failed " +
634407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
635407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
636407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
637407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglConfig = chooseEglConfig();
638407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglConfig == null) {
639407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglConfig not initialized");
640407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
641407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
642407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
643407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
644407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
645407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
646407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
647407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                int error = mEgl.eglGetError();
648407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                if (error == EGL_BAD_NATIVE_WINDOW) {
649407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
650f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                    return false;
651407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                }
652407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("createWindowSurface failed " +
653407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(error));
654407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
655407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
656407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
657407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglMakeCurrent failed " +
658407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
659407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
660407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
661407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mGL = mEglContext.getGL();
662f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy
663f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            return true;
664407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
665407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
666407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
667407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
668407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
669407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list);
670407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
671407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
672407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLConfig chooseEglConfig() {
673407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] configsCount = new int[1];
674407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            EGLConfig[] configs = new EGLConfig[1];
675407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] configSpec = getConfig();
676407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
677407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new IllegalArgumentException("eglChooseConfig failed " +
678407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
679407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            } else if (configsCount[0] > 0) {
680407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return configs[0];
681407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
682407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return null;
683407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
684407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
685407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int[] getConfig() {
686407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return new int[] {
687407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
688407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_RED_SIZE, 8,
689407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_GREEN_SIZE, 8,
690407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_BLUE_SIZE, 8,
691407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_ALPHA_SIZE, 0,
692407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_DEPTH_SIZE, 0,
693407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_STENCIL_SIZE, 0,
6948efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy                    EGL_CONFIG_CAVEAT, EGL_NONE,
695407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_NONE
696407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            };
697ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        }
6984c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
6994c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn}
700