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
19de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport static android.opengl.GLES20.*;
20de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport static javax.microedition.khronos.egl.EGL10.*;
21de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlock
22407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.app.ActivityManager;
234c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.app.WallpaperManager;
24407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.BroadcastReceiver;
25c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haaseimport android.content.ComponentCallbacks2;
26407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.Context;
27407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.content.Intent;
28407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.graphics.Bitmap;
294c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.graphics.Canvas;
30759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackbornimport android.graphics.Rect;
31e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopianimport android.graphics.Region.Op;
32407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.opengl.GLUtils;
33043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guyimport android.os.SystemProperties;
34407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.renderscript.Matrix4f;
354c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.WallpaperService;
36c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackbornimport android.util.Log;
378df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackbornimport android.view.MotionEvent;
384c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.view.SurfaceHolder;
392f20081f9fd734e466147bf1091d06cc7331458cChet Haaseimport android.view.WindowManager;
40407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
41407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.io.IOException;
42407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.ByteBuffer;
43407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.ByteOrder;
44407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport java.nio.FloatBuffer;
45407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
46de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport javax.microedition.khronos.egl.EGL10;
47de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport javax.microedition.khronos.egl.EGLConfig;
48de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport javax.microedition.khronos.egl.EGLContext;
49de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport javax.microedition.khronos.egl.EGLDisplay;
50de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport javax.microedition.khronos.egl.EGLSurface;
514c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
524c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn/**
534c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Default built-in wallpaper that simply shows a static image.
544c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn */
55407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy@SuppressWarnings({"UnusedDeclaration"})
564c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornpublic class ImageWallpaper extends WallpaperService {
57fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown    private static final String TAG = "ImageWallpaper";
58407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    private static final String GL_LOG_TAG = "ImageWallpaperGL";
59fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown    private static final boolean DEBUG = false;
60043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
61fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
62ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn    static final boolean FIXED_SIZED_SURFACE = true;
63881fb2092b41f4447e708da2f341d2ca5602c0d4Erik Gilling    static final boolean USE_OPENGL = true;
64ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
65ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    WallpaperManager mWallpaperManager;
66407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
67c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    DrawableEngine mEngine;
68c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
69407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    boolean mIsHwAccelerated;
70ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
71ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    @Override
72ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    public void onCreate() {
73ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        super.onCreate();
74ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
75407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
76407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        //noinspection PointlessBooleanExpression,ConstantConditions
77407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        if (FIXED_SIZED_SURFACE && USE_OPENGL) {
78043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy            if (!isEmulator()) {
7998365d7663cbd82979a5700faf0050220b01084dJeff Brown                mIsHwAccelerated = ActivityManager.isHighEndGfx();
80043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy            }
81407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
82ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy    }
83ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
84c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    @Override
85c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    public void onTrimMemory(int level) {
86c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        if (mEngine != null) {
87c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            mEngine.trimMemory(level);
88c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        }
89c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase    }
90c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
91043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    private static boolean isEmulator() {
92043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy        return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
93043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy    }
94043a6b1e5709c46cb8094766c792ec57d3fd97dfRomain Guy
95b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner    @Override
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        // TODO: Not currently used, keeping around until we know we don't need it
106407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        @SuppressWarnings({"UnusedDeclaration"})
107284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        private WallpaperObserver mReceiver;
108407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
109407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        Bitmap mBackground;
1105f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase        int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
1112f20081f9fd734e466147bf1091d06cc7331458cChet Haase        int mLastRotation = -1;
1127341d7a104b47996445d069a695e155a07184606Dianne Hackborn        float mXOffset;
1137341d7a104b47996445d069a695e155a07184606Dianne Hackborn        float mYOffset;
114759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn
115fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mVisible = true;
116fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mRedrawNeeded;
117fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        boolean mOffsetsChanged;
118fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        int mLastXTranslation;
119fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown        int mLastYTranslation;
120fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
121407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGL10 mEgl;
122407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLDisplay mEglDisplay;
123407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLConfig mEglConfig;
124407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLContext mEglContext;
125407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLSurface mEglSurface;
126407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
127407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final String sSimpleVS =
128407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "attribute vec4 position;\n" +
129407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "attribute vec2 texCoords;\n" +
130407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "varying vec2 outTexCoords;\n" +
131407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "uniform mat4 projection;\n" +
132407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "\nvoid main(void) {\n" +
133407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    outTexCoords = texCoords;\n" +
134407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    gl_Position = projection * position;\n" +
135407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "}\n\n";
136407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final String sSimpleFS =
137407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "precision mediump float;\n\n" +
138407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "varying vec2 outTexCoords;\n" +
139407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "uniform sampler2D texture;\n" +
140407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "\nvoid main(void) {\n" +
141407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
142407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                "}\n\n";
143209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
144407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int FLOAT_SIZE_BYTES = 4;
145407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
146407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
147407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
148407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
149284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        class WallpaperObserver extends BroadcastReceiver {
150b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            @Override
151284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            public void onReceive(Context context, Intent intent) {
15230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                if (DEBUG) {
15330bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                    Log.d(TAG, "onReceive");
15430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                }
15530bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
156b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mLastSurfaceWidth = mLastSurfaceHeight = -1;
157b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mBackground = null;
158b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mRedrawNeeded = true;
159b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                drawFrame();
160284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            }
161284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        }
162284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn
16335be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey        public DrawableEngine() {
16435be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey            super();
16535be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey            setFixedSizeAllowed(true);
16635be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey        }
16735be7560300a97fc3675bdd325910f28827d9508Jeff Sharkey
168c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        public void trimMemory(int level) {
169c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
170c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mBackground != null && mIsHwAccelerated) {
1715f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (DEBUG) {
1725f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    Log.d(TAG, "trimMemory");
1735f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
174c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mBackground.recycle();
175c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mBackground = null;
176c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                mWallpaperManager.forgetLoadedWallpaper();
177c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase            }
178c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase        }
179c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase
1804c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        @Override
181759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        public void onCreate(SurfaceHolder surfaceHolder) {
18230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
18330bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onCreate");
18430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
18530bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
186759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn            super.onCreate(surfaceHolder);
187209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
188407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // TODO: Don't need this currently because the wallpaper service
1899ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            // will restart the image wallpaper whenever the image changes.
1909ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
1919ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //mReceiver = new WallpaperObserver();
1929ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            //registerReceiver(mReceiver, filter, null, mHandler);
193fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
194ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            updateSurfaceSize(surfaceHolder);
195a8e5a2bcd6a0d35893187c6df42425c03be005daChet Haase
196a8e5a2bcd6a0d35893187c6df42425c03be005daChet Haase            setOffsetNotificationsEnabled(false);
1974c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
1984c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1994c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        @Override
200284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        public void onDestroy() {
201284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn            super.onDestroy();
2029ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            if (mReceiver != null) {
2039ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn                unregisterReceiver(mReceiver);
2049ea31639738e8d2c90dc3a4fcd535d09a0b7209aDianne Hackborn            }
205284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        }
206284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn
207284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        @Override
208ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
209912d9d13698693709991b76f83a8d64179e97e83Dianne Hackborn            super.onDesiredSizeChanged(desiredWidth, desiredHeight);
210ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            SurfaceHolder surfaceHolder = getSurfaceHolder();
211ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            if (surfaceHolder != null) {
212ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn                updateSurfaceSize(surfaceHolder);
213ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn            }
214ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        }
215ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn
216ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        void updateSurfaceSize(SurfaceHolder surfaceHolder) {
217ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            if (FIXED_SIZED_SURFACE) {
218ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // Used a fixed size surface, because we are special.  We can do
219ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // this because we know the current design of window animations doesn't
220ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                // cause this to break.
221ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                surfaceHolder.setFixedSize(getDesiredMinimumWidth(), getDesiredMinimumHeight());
222ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            } else {
223ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                surfaceHolder.setSizeFromLayout();
224ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            }
225ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        }
226ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn
227ac1471a4fff660710f88afc679c4119fdf8dc417Dianne Hackborn        @Override
228759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        public void onVisibilityChanged(boolean visible) {
22930bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
2302f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
23130bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
23230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
233b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            if (mVisible != visible) {
234b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                if (DEBUG) {
235b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                    Log.d(TAG, "Visibility changed to visible=" + visible);
23630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                }
237b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mVisible = visible;
238b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                drawFrame();
239fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
240759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        }
241fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
242759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        @Override
2438df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        public void onTouchEvent(MotionEvent event) {
2448df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn            super.onTouchEvent(event);
2458df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        }
2468df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn
2478df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn        @Override
24872c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        public void onOffsetsChanged(float xOffset, float yOffset,
249bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen                float xOffsetStep, float yOffsetStep,
25072c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn                int xPixels, int yPixels) {
25130bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
25230bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset
25330bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                        + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep
25430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                        + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
25530bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            }
25630bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown
257b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            if (mXOffset != xOffset || mYOffset != yOffset) {
258b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                if (DEBUG) {
259b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                    Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
260fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                }
261b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mXOffset = xOffset;
262b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mYOffset = yOffset;
263b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner                mOffsetsChanged = true;
264fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
265b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            drawFrame();
26672c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        }
26772c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn
26872c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        @Override
2694c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
27030bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            if (DEBUG) {
27130bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown                Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height);
272fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
2734c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
27430bc34f191ca8a009af313fc751e5b4bff6e39a1Jeff Brown            super.onSurfaceChanged(holder, format, width, height);
2754c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
276b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            drawFrame();
2774c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
278fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown
279fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        @Override
2802f20081f9fd734e466147bf1091d06cc7331458cChet Haase        public void onSurfaceDestroyed(SurfaceHolder holder) {
2812f20081f9fd734e466147bf1091d06cc7331458cChet Haase            super.onSurfaceDestroyed(holder);
2825f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            mLastSurfaceWidth = mLastSurfaceHeight = -1;
2832f20081f9fd734e466147bf1091d06cc7331458cChet Haase        }
2842f20081f9fd734e466147bf1091d06cc7331458cChet Haase
2852f20081f9fd734e466147bf1091d06cc7331458cChet Haase        @Override
2862f20081f9fd734e466147bf1091d06cc7331458cChet Haase        public void onSurfaceCreated(SurfaceHolder holder) {
2872f20081f9fd734e466147bf1091d06cc7331458cChet Haase            super.onSurfaceCreated(holder);
2885f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            mLastSurfaceWidth = mLastSurfaceHeight = -1;
2892f20081f9fd734e466147bf1091d06cc7331458cChet Haase        }
2902f20081f9fd734e466147bf1091d06cc7331458cChet Haase
2912f20081f9fd734e466147bf1091d06cc7331458cChet Haase        @Override
292fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
293fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            if (DEBUG) {
2942f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "onSurfaceRedrawNeeded");
295fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            }
296fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner            super.onSurfaceRedrawNeeded(holder);
297fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner
298b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner            drawFrame();
299fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner        }
300fb729c7b4420eacbc65a958beb53511ff59ba3e6Craig Mautner
301b1ef36965bf17e791afd16a9a34bcbb32f495f68Craig Mautner        void drawFrame() {
3022f20081f9fd734e466147bf1091d06cc7331458cChet Haase            SurfaceHolder sh = getSurfaceHolder();
3032f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final Rect frame = sh.getSurfaceFrame();
3042f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final int dw = frame.width();
3052f20081f9fd734e466147bf1091d06cc7331458cChet Haase            final int dh = frame.height();
3062f20081f9fd734e466147bf1091d06cc7331458cChet Haase            int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
3072f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    getDefaultDisplay().getRotation();
3085f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
3092f20081f9fd734e466147bf1091d06cc7331458cChet Haase
3105f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
3112f20081f9fd734e466147bf1091d06cc7331458cChet Haase            if (!redrawNeeded && !mOffsetsChanged) {
3122f20081f9fd734e466147bf1091d06cc7331458cChet Haase                if (DEBUG) {
3132f20081f9fd734e466147bf1091d06cc7331458cChet Haase                    Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
3142f20081f9fd734e466147bf1091d06cc7331458cChet Haase                            + "and offsets have not changed.");
315fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                }
3162f20081f9fd734e466147bf1091d06cc7331458cChet Haase                return;
317fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
3182f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastRotation = newRotation;
319321357b6066a34cc12a0528b7b835c7664db2e08Michael Jurka
3202f20081f9fd734e466147bf1091d06cc7331458cChet Haase            // Load bitmap if it is not yet loaded or if it was loaded at a different size
3215f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            if (mBackground == null || surfaceDimensionsChanged) {
3222f20081f9fd734e466147bf1091d06cc7331458cChet Haase                if (DEBUG) {
3235f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
3245f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            mBackground + ", " +
3255f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
3265f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
3275f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                            dw + ", " + dh);
3282f20081f9fd734e466147bf1091d06cc7331458cChet Haase                }
329b9fca9997100f209e98f0559c54c875b9e661e9fMichael Wright                mWallpaperManager.forgetLoadedWallpaper();
330ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                updateWallpaperLocked();
3315f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (mBackground == null) {
3325f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    if (DEBUG) {
3335f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        Log.d(TAG, "Unable to load bitmap");
3345f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    }
3355f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    return;
3365f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
3375f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                if (DEBUG) {
3385f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
3395f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
3405f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
3415f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                mBackground.getHeight());
3425f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                    }
3435f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                }
344ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            }
345ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
3465f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final int availw = dw - mBackground.getWidth();
3475f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final int availh = dh - mBackground.getHeight();
348033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
349033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
350033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown
351033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            mOffsetsChanged = false;
3522f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mRedrawNeeded = false;
3535f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            if (surfaceDimensionsChanged) {
3545f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                mLastSurfaceWidth = dw;
3555f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                mLastSurfaceHeight = dh;
3565f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            }
3572f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastXTranslation = xPixels;
3582f20081f9fd734e466147bf1091d06cc7331458cChet Haase            mLastYTranslation = yPixels;
3592f20081f9fd734e466147bf1091d06cc7331458cChet Haase            if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
360033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                if (DEBUG) {
361033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                    Log.d(TAG, "Suppressed drawFrame since the image has not "
362033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                            + "actually moved an integral number of pixels.");
363033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                }
364033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown                return;
365033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown            }
366033f63a1a5e8f768a72a11561fe70957eb44fa3eJeff Brown
367c92f150af0fb93b677a4ec6e2aca1b9a9bdd8760Craig Mautner            if (DEBUG) {
3682f20081f9fd734e466147bf1091d06cc7331458cChet Haase                Log.d(TAG, "Redrawing wallpaper");
369c92f150af0fb93b677a4ec6e2aca1b9a9bdd8760Craig Mautner            }
3709549c067d93bd87aa28d1d6d44fdb8d75b2fd276Wim Vander Schelden
371407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mIsHwAccelerated) {
372f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
373f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                    drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
374f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                }
375407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            } else {
376407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
377c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                if (FIXED_SIZED_SURFACE) {
378c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // If the surface is fixed-size, we should only need to
379c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // draw it once and then we'll let the window manager
380c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // position it appropriately.  As such, we no longer needed
381c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // the loaded bitmap.  Yay!
382c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    // hw-accelerated path retains bitmap for faster rotation
383c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mBackground = null;
384c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                    mWallpaperManager.forgetLoadedWallpaper();
385c61d70ec46bc44344a419a0a15ccbecd1f8f1a2dChet Haase                }
386759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn            }
387ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
388759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn        }
389ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy
3905f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase        private void updateWallpaperLocked() {
391fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            Throwable exception = null;
392fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            try {
393589a6af173c10738d2a83c69a9dda36579cc739dChet Haase                mBackground = null;
394407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                mBackground = mWallpaperManager.getBitmap();
395fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            } catch (RuntimeException e) {
396fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                exception = e;
397fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            } catch (OutOfMemoryError e) {
398fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                exception = e;
399fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            }
400407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
401fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown            if (exception != null) {
402fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                mBackground = null;
403fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // Note that if we do fail at this, and the default wallpaper can't
404fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // be loaded, we will go into a cycle.  Don't do a build where the
405fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                // default wallpaper can't be loaded.
406fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                Log.w(TAG, "Unable to load wallpaper!", exception);
407c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                try {
408fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    mWallpaperManager.clear();
409fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                } catch (IOException ex) {
410fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    // now we're really screwed.
411fa2e504087362989e5dd7fe6e65b6481cef59495Jeff Brown                    Log.w(TAG, "Unable reset to default wallpaper!", ex);
412c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                }
413ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy            }
414407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
415407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
416407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) {
417407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            Canvas c = sh.lockCanvas();
418407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (c != null) {
419407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                try {
420407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (DEBUG) {
421407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        Log.d(TAG, "Redrawing: x=" + x + ", y=" + y);
422407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
423407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
424407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    c.translate(x, y);
425407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (w < 0 || h < 0) {
426407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.save(Canvas.CLIP_SAVE_FLAG);
4275f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                        c.clipRect(0, 0, mBackground.getWidth(), mBackground.getHeight(),
4285f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase                                Op.DIFFERENCE);
429407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.drawColor(0xff000000);
430407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.restore();
431407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
432407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    if (mBackground != null) {
433407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        c.drawBitmap(mBackground, 0, 0, null);
434407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    }
435407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                } finally {
436407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    sh.unlockCanvasAndPost(c);
437407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                }
438407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
439407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
440407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
441f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy        private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
442f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            if (!initGL(sh)) return false;
443407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
4445f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final float right = left + mBackground.getWidth();
4455f0d976b37b919b74509b6f22e4ad3fa56422f6cChet Haase            final float bottom = top + mBackground.getHeight();
446407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
447407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final Rect frame = sh.getSurfaceFrame();
448407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final Matrix4f ortho = new Matrix4f();
449407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
450407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
451407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final FloatBuffer triangleVertices = createMesh(left, top, right, bottom);
452407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
453407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int texture = loadTexture(mBackground);
454407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int program = buildProgram(sSimpleVS, sSimpleFS);
4552f20081f9fd734e466147bf1091d06cc7331458cChet Haase
456407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int attribPosition = glGetAttribLocation(program, "position");
457407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int attribTexCoords = glGetAttribLocation(program, "texCoords");
458407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int uniformTexture = glGetUniformLocation(program, "texture");
459407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int uniformProjection = glGetUniformLocation(program, "projection");
460407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
461407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
462407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
463407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glViewport(0, 0, frame.width(), frame.height());
464407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glBindTexture(GL_TEXTURE_2D, texture);
465407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
466407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUseProgram(program);
467407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glEnableVertexAttribArray(attribPosition);
468407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glEnableVertexAttribArray(attribTexCoords);
469407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUniform1i(uniformTexture, 0);
470407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0);
471407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
472407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
473407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
474407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (w < 0 || h < 0) {
475407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
476407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glClear(GL_COLOR_BUFFER_BIT);
477407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
4782f20081f9fd734e466147bf1091d06cc7331458cChet Haase
479407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // drawQuad
480407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
481407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
482407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
483407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
484407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
485407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
486407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
487407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
488407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4892f20081f9fd734e466147bf1091d06cc7331458cChet Haase
490c8d983f7259b4e328abc10c27c3c2cec61ad0722Romain Guy            boolean status = mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
491407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkEglError();
4922f20081f9fd734e466147bf1091d06cc7331458cChet Haase
493407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            finishGL();
494f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy
495c8d983f7259b4e328abc10c27c3c2cec61ad0722Romain Guy            return status;
496407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
497407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
498407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private FloatBuffer createMesh(int left, int top, float right, float bottom) {
499407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final float[] verticesData = {
500407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    // X, Y, Z, U, V
501407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     left,  bottom, 0.0f, 0.0f, 1.0f,
502407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     right, bottom, 0.0f, 1.0f, 1.0f,
503407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     left,  top,    0.0f, 0.0f, 0.0f,
504407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                     right, top,    0.0f, 1.0f, 0.0f,
505407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            };
506407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
507407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final int bytes = verticesData.length * FLOAT_SIZE_BYTES;
508407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order(
509407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    ByteOrder.nativeOrder()).asFloatBuffer();
510407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            triangleVertices.put(verticesData).position(0);
511407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return triangleVertices;
512407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
513407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
514407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int loadTexture(Bitmap bitmap) {
515407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] textures = new int[1];
516209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
517407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glActiveTexture(GL_TEXTURE0);
518407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGenTextures(1, textures, 0);
519407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
520209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
521407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int texture = textures[0];
522407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glBindTexture(GL_TEXTURE_2D, texture);
523407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
524209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
525407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
526407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
527209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
528407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
529407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
530209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
531407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
532407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
533407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
534407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return texture;
535407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
536209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
537407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int buildProgram(String vertex, String fragment) {
538407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
539407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (vertexShader == 0) return 0;
540209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
541407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
542407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (fragmentShader == 0) return 0;
543209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
544407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int program = glCreateProgram();
545407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glAttachShader(program, vertexShader);
546407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
547209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
548407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glAttachShader(program, fragmentShader);
549407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
550209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
551407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glLinkProgram(program);
552407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
553209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
554407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] status = new int[1];
555407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
556407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (status[0] != GL_TRUE) {
557407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                String error = glGetProgramInfoLog(program);
558407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.d(GL_LOG_TAG, "Error while linking program:\n" + error);
559407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(vertexShader);
560407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(fragmentShader);
561407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteProgram(program);
562407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return 0;
563407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
564209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
565407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return program;
566407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
5673696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy
568407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int buildShader(String source, int type) {
569407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int shader = glCreateShader(type);
570209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
571407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glShaderSource(shader, source);
572407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
573209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
574407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glCompileShader(shader);
575407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            checkGlError();
576209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
577407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] status = new int[1];
578407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
579407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (status[0] != GL_TRUE) {
580407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                String error = glGetShaderInfoLog(shader);
581407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error);
582407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                glDeleteShader(shader);
583407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return 0;
584407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
585209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
586407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return shader;
587407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
5883696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy
589407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void checkEglError() {
590407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int error = mEgl.eglGetError();
591407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (error != EGL_SUCCESS) {
592407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error));
593407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
594407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
5953696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy
596407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void checkGlError() {
597407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int error = glGetError();
598407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (error != GL_NO_ERROR) {
599407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable());
600407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
601407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
6023696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy
603407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private void finishGL() {
604f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
605407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
606f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
6073696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy            mEgl.eglTerminate(mEglDisplay);
608407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
6093696779bca4e5bc1b60c056db6f892e72e51a20fRomain Guy
610f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy        private boolean initGL(SurfaceHolder surfaceHolder) {
611407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEgl = (EGL10) EGLContext.getEGL();
612209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
613407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
614407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglDisplay == EGL_NO_DISPLAY) {
615407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglGetDisplay failed " +
616407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
617407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
618209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
619407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] version = new int[2];
620407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglInitialize(mEglDisplay, version)) {
621407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglInitialize failed " +
622407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
623407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
624209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
625407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglConfig = chooseEglConfig();
626407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglConfig == null) {
627407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglConfig not initialized");
628407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
629209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
630407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
631187e1e2fc7dfb4eabdcb2c8990774bc6020fb16bChet Haase            if (mEglContext == EGL_NO_CONTEXT) {
632187e1e2fc7dfb4eabdcb2c8990774bc6020fb16bChet Haase                throw new RuntimeException("createContext failed " +
633187e1e2fc7dfb4eabdcb2c8990774bc6020fb16bChet Haase                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
6349549c067d93bd87aa28d1d6d44fdb8d75b2fd276Wim Vander Schelden            }
635187e1e2fc7dfb4eabdcb2c8990774bc6020fb16bChet Haase
6362e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            int attribs[] = {
6372e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                EGL_WIDTH, 1,
6382e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                EGL_HEIGHT, 1,
6392e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                EGL_NONE
6402e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            };
6412e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            EGLSurface tmpSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
6422e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            mEgl.eglMakeCurrent(mEglDisplay, tmpSurface, tmpSurface, mEglContext);
6432e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase
6442e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            int[] maxSize = new int[1];
6452e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            Rect frame = surfaceHolder.getSurfaceFrame();
6462e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
6472e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase
6482e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
6492e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            mEgl.eglDestroySurface(mEglDisplay, tmpSurface);
6502e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase
6512e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
6522e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
6532e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                mEgl.eglTerminate(mEglDisplay);
6542e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                Log.e(GL_LOG_TAG, "requested  texture size " +
6552e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                    frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
6562e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                    maxSize[0] + "x" + maxSize[0]);
6572e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase                return false;
6582e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase            }
6592e417be5c4d45ae041c0046570d117d7b0d71940Chet Haase
660407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
661407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
662407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                int error = mEgl.eglGetError();
6639549c067d93bd87aa28d1d6d44fdb8d75b2fd276Wim Vander Schelden                if (error == EGL_BAD_NATIVE_WINDOW || error == EGL_BAD_ALLOC) {
6649549c067d93bd87aa28d1d6d44fdb8d75b2fd276Wim Vander Schelden                    Log.e(GL_LOG_TAG, "createWindowSurface returned " +
6659549c067d93bd87aa28d1d6d44fdb8d75b2fd276Wim Vander Schelden                                         GLUtils.getEGLErrorString(error) + ".");
666f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy                    return false;
667407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                }
668407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("createWindowSurface failed " +
669407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(error));
670407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
671209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
672407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
673407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new RuntimeException("eglMakeCurrent failed " +
674407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
675407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
676f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy
677f929629e74fe84b986f76db448b9c95d72b2903eRomain Guy            return true;
678407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
679209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
680209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
681407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
682407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
683209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list);
684407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
685209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock
686407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private EGLConfig chooseEglConfig() {
687407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] configsCount = new int[1];
688407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            EGLConfig[] configs = new EGLConfig[1];
689407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            int[] configSpec = getConfig();
690407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
691407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                throw new IllegalArgumentException("eglChooseConfig failed " +
692407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
693407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            } else if (configsCount[0] > 0) {
694407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                return configs[0];
695407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            }
696407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return null;
697407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        }
698407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
699407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private int[] getConfig() {
700407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return new int[] {
701407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
702407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_RED_SIZE, 8,
703407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_GREEN_SIZE, 8,
704407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_BLUE_SIZE, 8,
705407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_ALPHA_SIZE, 0,
706407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_DEPTH_SIZE, 0,
707407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_STENCIL_SIZE, 0,
7088efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy                    EGL_CONFIG_CAVEAT, EGL_NONE,
709407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                    EGL_NONE
710407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            };
711ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy        }
7124c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
7134c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn}
714