12d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy/*
22d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Copyright (C) 2010 The Android Open Source Project
32d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy *
42d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
52d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * you may not use this file except in compliance with the License.
62d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * You may obtain a copy of the License at
72d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy *
82d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
92d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy *
102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Unless required by applicable law or agreed to in writing, software
112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * See the License for the specific language governing permissions and
142d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * limitations under the License.
152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */
162d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
182d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guypackage android.view;
192d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
20c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackbornimport android.content.ComponentCallbacks2;
217d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Paint;
227d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Rect;
23aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.graphics.SurfaceTexture;
24bd43152bda835c5a9a619a5869344a6a3af11917Romain Guyimport android.opengl.EGL14;
25407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.opengl.GLUtils;
26717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.opengl.ManagedEGLContext;
27717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.os.Handler;
28717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.os.Looper;
2902ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemClock;
3002ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemProperties;
3177e67cf9055378d00bb57f458129462f33047039Romain Guyimport android.os.Trace;
32e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport android.util.Log;
338ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guyimport com.google.android.gles_jni.EGLImpl;
342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL10;
362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL11;
372d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLConfig;
382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLContext;
392d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLDisplay;
402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLSurface;
41e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport javax.microedition.khronos.opengles.GL;
422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
43a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guyimport java.io.File;
44a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guyimport java.io.PrintWriter;
4577e67cf9055378d00bb57f458129462f33047039Romain Guyimport java.util.concurrent.locks.ReentrantLock;
46a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
47484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guyimport static javax.microedition.khronos.egl.EGL10.*;
48484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy/**
50c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * Interface for rendering a ViewAncestor using hardware acceleration.
512d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy *
522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @hide
532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */
5461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guypublic abstract class HardwareRenderer {
554f6aff386045000c2c03b903c7109cb42092b7eaRomain Guy    static final String LOG_TAG = "HardwareRenderer";
56fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
575233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy    /**
58a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     * Name of the file that holds the shaders cache.
59a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     */
60a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
61a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
62a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    /**
637d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     * Turn on to only refresh the parts of the screen that need updating.
64069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY}
65069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * must also have the value "true".
667d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     */
677d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy    public static final boolean RENDER_DIRTY_REGIONS = true;
687d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
697d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy    /**
70069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * System property used to enable or disable dirty regions invalidation.
71069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
72069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * The default value of this property is assumed to be true.
73069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     *
74069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * Possible values:
75069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * "true", to enable partial invalidates
76069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * "false", to disable partial invalidates
77069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     */
784b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
799ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
809ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy    /**
819ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     * System property used to enable or disable vsync.
829ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     * The default value of this property is assumed to be false.
839ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     *
849ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     * Possible values:
859ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     * "true", to disable vsync
869ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     * "false", to enable vsync
879ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy     */
884b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    static final String DISABLE_VSYNC_PROPERTY = "debug.hwui.disable_vsync";
89069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy
90069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy    /**
91a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * System property used to enable or disable hardware rendering profiling.
92a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * The default value of this property is assumed to be false.
9309280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     *
94a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
95a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * output extra information about the time taken to execute by the last
96a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * frames.
97a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     *
98a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * Possible values:
99a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * "true", to enable profiling
100a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * "false", to disable profiling
1014b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy     *
1024b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy     * @hide
103a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     */
1044b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    public static final String PROFILE_PROPERTY = "debug.hwui.profile";
105a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
106a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    /**
10709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * System property used to specify the number of frames to be used
10809280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * when doing hardware rendering profiling.
10909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * The default value of this property is #PROFILE_MAX_FRAMES.
11009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     *
11109280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
11209280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * output extra information about the time taken to execute by the last
11309280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * frames.
11409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     *
11509280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * Possible values:
11609280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     * "60", to set the limit of frames to 60
11709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase     */
1184b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
11909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase
12009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase    /**
121484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     * System property used to debug EGL configuration choice.
122484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     *
123484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     * Possible values:
124484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     * "choice", print the chosen configuration only
125484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     * "all", print all possible configurations
126484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy     */
1274b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
128484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
129484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy    /**
1307d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     * Turn on to draw dirty regions every other frame.
131b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy     *
132b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy     * Possible values:
133b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy     * "true", to enable dirty regions debugging
134b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy     * "false", to disable dirty regions debugging
1354b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy     *
1364b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy     * @hide
1377d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     */
1384b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy    public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
1394ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy
1404ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy    /**
1414ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     * Turn on to flash hardware layers when they update.
1424ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     *
1434ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     * Possible values:
1444ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     * "true", to enable hardware layers updates debugging
1454ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     * "false", to disable hardware layers updates debugging
1464ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     *
1474ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     * @hide
1484ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy     */
1494ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy    public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
1504ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy            "debug.hwui.show_layers_updates";
1514ff0cf4b83605bff630c4e6f1fabe4f72a3f93a1Romain Guy
1527d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy    /**
1537c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     * Turn on to show overdraw level.
1547c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     *
1557c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     * Possible values:
1567c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     * "true", to enable overdraw debugging
1577c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     * "false", to disable overdraw debugging
1587c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     *
1597c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     * @hide
1607c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy     */
1617c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
1627c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
1637c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy    /**
1645233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     * A process can set this flag to false to prevent the use of hardware
1655233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     * rendering.
1665233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     *
1675233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     * @hide
1685233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     */
1695233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy    public static boolean sRendererDisabled = false;
1705233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy
1715d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn    /**
1725d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn     * Further hardware renderer disabling for the system process.
1735d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn     *
1745d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn     * @hide
1755d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn     */
1765d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn    public static boolean sSystemRendererDisabled = false;
1775d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn
178a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    /**
179a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * Number of frames to profile.
180a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     */
181a21f877434dd25a93869b8641e3c38618bf317a9Romain Guy    private static final int PROFILE_MAX_FRAMES = 128;
182a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
183a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    /**
184a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * Number of floats per profiled frame.
185a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     */
186a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    private static final int PROFILE_FRAME_DATA_COUNT = 3;
187a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
1882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    private boolean mEnabled;
1892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    private boolean mRequested = true;
1902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
1912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
19267f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy     * Invoke this method to disable hardware rendering in the current process.
1935233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     *
1945233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     * @hide
1955233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy     */
1965d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn    public static void disable(boolean system) {
1975233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy        sRendererDisabled = true;
1985d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn        if (system) {
1995d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn            sSystemRendererDisabled = true;
2005d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn        }
2015233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy    }
2025233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy
2035233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy    /**
20461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     * Indicates whether hardware acceleration is available under any form for
20561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     * the view hierarchy.
20661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     *
20761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     * @return True if the view hierarchy can potentially be hardware accelerated,
20861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     *         false otherwise
20961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy     */
21061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    public static boolean isAvailable() {
21161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy        return GLES20Canvas.isAvailable();
21261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    }
21361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy
21461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    /**
2152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Destroys the hardware rendering context.
2164caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy     *
2174caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy     * @param full If true, destroys all associated resources.
2182d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
2194caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy    abstract void destroy(boolean full);
2202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
2212d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
2222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Initializes the hardware renderer for the specified surface.
2232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
224786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     * @param surface The surface to hardware accelerate
2252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
2262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @return True if the initialization was successful, false otherwise.
2272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
228786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy    abstract boolean initialize(Surface surface) throws Surface.OutOfResourcesException;
2292a83f001fdb189f945e82e81e717ba204824b112Romain Guy
2302a83f001fdb189f945e82e81e717ba204824b112Romain Guy    /**
2312a83f001fdb189f945e82e81e717ba204824b112Romain Guy     * Updates the hardware renderer for the specified surface.
232786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     *
233786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     * @param surface The surface to hardware accelerate
2342a83f001fdb189f945e82e81e717ba204824b112Romain Guy     */
235786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy    abstract void updateSurface(Surface surface) throws Surface.OutOfResourcesException;
2362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
2372d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
23831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     * Destroys the layers used by the specified view hierarchy.
2396d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     *
2406d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     * @param view The root of the view hierarchy
2416d7475d666baefaa3ba9f0dcee25238739454241Romain Guy     */
2426d7475d666baefaa3ba9f0dcee25238739454241Romain Guy    abstract void destroyLayers(View view);
2436d7475d666baefaa3ba9f0dcee25238739454241Romain Guy
2446d7475d666baefaa3ba9f0dcee25238739454241Romain Guy    /**
24531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     * Destroys all hardware rendering resources associated with the specified
24631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     * view hierarchy.
24731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     *
24831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     * @param view The root of the view hierarchy
24931f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy     */
25031f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy    abstract void destroyHardwareResources(View view);
25131f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy
25231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy    /**
253039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     * This method should be invoked whenever the current hardware renderer
254cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy     * context should be reset.
255786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     *
256786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     * @param surface The surface to hardware accelerate
2577e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy     */
258786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy    abstract void invalidate(Surface surface);
259039857520b1a03a52051b966d87d587225bdfcc3Romain Guy
260039857520b1a03a52051b966d87d587225bdfcc3Romain Guy    /**
261039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     * This method should be invoked to ensure the hardware renderer is in
262039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     * valid state (for instance, to ensure the correct EGL context is bound
263039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     * to the current thread.)
264039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     *
265039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     * @return true if the renderer is now valid, false otherwise
266039857520b1a03a52051b966d87d587225bdfcc3Romain Guy     */
267039857520b1a03a52051b966d87d587225bdfcc3Romain Guy    abstract boolean validate();
2687e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy
2697e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy    /**
2701ac4765e959c79101f64b1279887ed469334c268Romain Guy     * This method ensures the hardware renderer is in a valid state
2711ac4765e959c79101f64b1279887ed469334c268Romain Guy     * before executing the specified action.
2721ac4765e959c79101f64b1279887ed469334c268Romain Guy     *
2731ac4765e959c79101f64b1279887ed469334c268Romain Guy     * This method will attempt to set a valid state even if the window
2741ac4765e959c79101f64b1279887ed469334c268Romain Guy     * the renderer is attached to was destroyed.
2751ac4765e959c79101f64b1279887ed469334c268Romain Guy     *
2761ac4765e959c79101f64b1279887ed469334c268Romain Guy     * @return true if the action was run
2771ac4765e959c79101f64b1279887ed469334c268Romain Guy     */
2781ac4765e959c79101f64b1279887ed469334c268Romain Guy    abstract boolean safelyRun(Runnable action);
2791ac4765e959c79101f64b1279887ed469334c268Romain Guy
2801ac4765e959c79101f64b1279887ed469334c268Romain Guy    /**
2817e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy     * Setup the hardware renderer for drawing. This is called whenever the
2827e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy     * size of the target surface changes or when the surface is first created.
2832d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
2842d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param width Width of the drawing surface.
2852d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param height Height of the drawing surface.
2862d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
287fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    abstract void setup(int width, int height);
2882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
289069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy    /**
29040e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * Gets the current width of the surface. This is the width that the surface
29140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * was last set to in a call to {@link #setup(int, int)}.
29240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     *
29340e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * @return the current width of the surface
29440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     */
29540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase    abstract int getWidth();
29640e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase
29740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase    /**
29840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * Gets the current height of the surface. This is the height that the surface
29940e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * was last set to in a call to {@link #setup(int, int)}.
30040e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     *
30140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     * @return the current width of the surface
30240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase     */
30340e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase    abstract int getHeight();
30440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase
30540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase    /**
30608837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase     * Gets the current canvas associated with this HardwareRenderer.
30708837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase     *
30808837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase     * @return the current HardwareCanvas
30908837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase     */
31008837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase    abstract HardwareCanvas getCanvas();
31108837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase
31208837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase    /**
313a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * Outputs extra debugging information in the specified file descriptor.
314a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     * @param pw
315a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy     */
316a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    abstract void dumpGfxInfo(PrintWriter pw);
317a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka
318a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka    /**
319a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka     * Outputs the total number of frames rendered (used for fps calculations)
320a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka     *
321a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka     * @return the number of frames rendered
322a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka     */
323a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka    abstract long getFrameCount();
324a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka
325a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy    /**
326a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     * Sets the directory to use as a persistent storage for hardware rendering
327a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     * resources.
328a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     *
329a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     * @param cacheDir A directory the current process can write to
330a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy     */
331a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    public static void setupDiskCache(File cacheDir) {
332a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy        nSetupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
333a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    }
334a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
335a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    private static native void nSetupShadersDiskCache(String cacheFile);
336a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
337a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    /**
338b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis     * Notifies EGL that the frame is about to be rendered.
3397687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy     * @param size
340b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis     */
3417687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    private static void beginFrame(int[] size) {
3427687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        nBeginFrame(size);
343b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis    }
344b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis
3457687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    private static native void nBeginFrame(int[] size);
346b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis
347b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis    /**
348244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * Preserves the back buffer of the current surface after a buffer swap.
349244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current
350244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL
351244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT.
352244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     *
353244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * @return True if the swap behavior was successfully changed,
354244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     *         false otherwise.
355244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     */
356244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    static boolean preserveBackBuffer() {
357244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        return nPreserveBackBuffer();
358244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
359244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
360244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    private static native boolean nPreserveBackBuffer();
361244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
362244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    /**
363244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * Indicates whether the current surface preserves its back buffer
364244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * after a buffer swap.
365244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     *
366244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED,
367244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     *         false otherwise
368244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     */
369244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    static boolean isBackBufferPreserved() {
370244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        return nIsBackBufferPreserved();
371244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
372244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
373244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    private static native boolean nIsBackBufferPreserved();
374244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
375244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    /**
376244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     * Disables v-sync. For performance testing only.
377244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy     */
378244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    static void disableVsync() {
379244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        nDisableVsync();
380244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
381244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
382244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    private static native void nDisableVsync();
383244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
384244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    /**
38511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy     * Indicates that the specified hardware layer needs to be updated
38611cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy     * as soon as possible.
38711cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy     *
38811cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy     * @param layer The hardware layer that needs an update
38911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy     */
39011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    abstract void pushLayerUpdate(HardwareLayer layer);
39111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
39211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy    /**
393069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * Interface used to receive callbacks whenever a view is drawn by
394069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     * a hardware renderer instance.
395069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy     */
3960f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn    interface HardwareDrawCallbacks {
397069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy        /**
398069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         * Invoked before a view is drawn by a hardware renderer.
399069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         *
400069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         * @param canvas The Canvas used to render the view.
401069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         */
4027d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy        void onHardwarePreDraw(HardwareCanvas canvas);
403069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy
404069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy        /**
405069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         * Invoked after a view is drawn by a hardware renderer.
406069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         *
407069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         * @param canvas The Canvas used to render the view.
408069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy         */
4097d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy        void onHardwarePostDraw(HardwareCanvas canvas);
4100f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn    }
4110f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn
4122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
4132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Draws the specified view.
4147d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     *
4152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param view The view to draw.
4162d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param attachInfo AttachInfo tied to the specified view.
4177d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     * @param callbacks Callbacks invoked when drawing happens.
4187d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy     * @param dirty The dirty rectangle to update, can be null.
41950d133e290468fd149b5c03e46549afca2ee05f8Romain Guy     *
42050d133e290468fd149b5c03e46549afca2ee05f8Romain Guy     * @return true if the dirty rect was ignored, false otherwise
4212d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
42250d133e290468fd149b5c03e46549afca2ee05f8Romain Guy    abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
4237d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            Rect dirty);
4242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
4252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
42653ca03d9a3a6a95286302802173c4820b16328ceRomain Guy     * Creates a new display list that can be used to record batches of
42753ca03d9a3a6a95286302802173c4820b16328ceRomain Guy     * drawing operations.
428b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy     *
42913631f3da855f200a151e7837ed9f6b079622b58Romain Guy     * @param name The name of the display list, used for debugging purpose.
43013631f3da855f200a151e7837ed9f6b079622b58Romain Guy     *             May be null
43113631f3da855f200a151e7837ed9f6b079622b58Romain Guy     *
43253ca03d9a3a6a95286302802173c4820b16328ceRomain Guy     * @return A new display list.
433b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy     */
43413631f3da855f200a151e7837ed9f6b079622b58Romain Guy    public abstract DisplayList createDisplayList(String name);
435b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
436b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    /**
437aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * Creates a new hardware layer. A hardware layer built by calling this
438aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * method will be treated as a texture layer, instead of as a render target.
439aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     *
440a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy     * @param isOpaque Whether the layer should be opaque or not
441a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy     *
442aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * @return A hardware layer
4432af3524beb75150d347accc925022daa53b4a789Jamie Gennis     */
444a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy    abstract HardwareLayer createHardwareLayer(boolean isOpaque);
4452af3524beb75150d347accc925022daa53b4a789Jamie Gennis
446aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    /**
4476c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * Creates a new hardware layer.
4486c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     *
4496c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * @param width The minimum width of the layer
4506c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * @param height The minimum height of the layer
4516c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * @param isOpaque Whether the layer should be opaque or not
4526c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     *
4536c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     * @return A hardware layer
4546c319ca1275c8db892c39b48fc54864c949f9171Romain Guy     */
4556c319ca1275c8db892c39b48fc54864c949f9171Romain Guy    abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
456aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
457aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    /**
458aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * Creates a new {@link SurfaceTexture} that can be used to render into the
459aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * specified hardware layer.
460aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     *
461aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     *
462aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
463aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     *
464aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     * @return A {@link SurfaceTexture}
465aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy     */
466e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy    abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
467aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
468aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy    /**
4692af3524beb75150d347accc925022daa53b4a789Jamie Gennis     * Sets the {@link android.graphics.SurfaceTexture} that will be used to
4702af3524beb75150d347accc925022daa53b4a789Jamie Gennis     * render into the specified hardware layer.
4712af3524beb75150d347accc925022daa53b4a789Jamie Gennis     *
4722af3524beb75150d347accc925022daa53b4a789Jamie Gennis     * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
4732af3524beb75150d347accc925022daa53b4a789Jamie Gennis     * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer
4742af3524beb75150d347accc925022daa53b4a789Jamie Gennis     */
4752af3524beb75150d347accc925022daa53b4a789Jamie Gennis    abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
4762af3524beb75150d347accc925022daa53b4a789Jamie Gennis
4772af3524beb75150d347accc925022daa53b4a789Jamie Gennis    /**
478ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * Detaches the specified functor from the current functor execution queue.
479ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     *
480ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @param functor The native functor to remove from the execution queue.
481ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     *
482ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @see HardwareCanvas#callDrawGLFunction(int)
483ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @see #attachFunctor(android.view.View.AttachInfo, int)
484ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     */
485ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    abstract void detachFunctor(int functor);
486ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
487ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    /**
488ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * Schedules the specified functor in the functors execution queue.
489ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     *
490ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @param attachInfo AttachInfo tied to this renderer.
491ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @param functor The native functor to insert in the execution queue.
492ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     *
493ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     * @see HardwareCanvas#callDrawGLFunction(int)
49441ee465734d0006797a8fd36e88976c1e85d161cChris Craik     * @see #detachFunctor(int)
49541ee465734d0006797a8fd36e88976c1e85d161cChris Craik     *
49641ee465734d0006797a8fd36e88976c1e85d161cChris Craik     * @return true if the functor was attached successfully
497ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy     */
49841ee465734d0006797a8fd36e88976c1e85d161cChris Craik    abstract boolean attachFunctor(View.AttachInfo attachInfo, int functor);
499ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
500ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy    /**
5012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Initializes the hardware renderer for the specified surface and setup the
502c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
5032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * potentially lost the hardware renderer. The hardware renderer should be
5042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * reinitialized and setup when the render {@link #isRequested()} and
5052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * {@link #isEnabled()}.
50644d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy     *
5072d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param width The width of the drawing surface.
5082d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param height The height of the drawing surface.
509786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy     * @param surface The surface to hardware accelerate
510dfab363807b3b44be4032e410f016e0a0d018426Romain Guy     *
511dfab363807b3b44be4032e410f016e0a0d018426Romain Guy     * @return true if the surface was initialized, false otherwise. Returning
512dfab363807b3b44be4032e410f016e0a0d018426Romain Guy     *         false might mean that the surface was already initialized.
5132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
514dfab363807b3b44be4032e410f016e0a0d018426Romain Guy    boolean initializeIfNeeded(int width, int height, Surface surface)
51544d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy            throws Surface.OutOfResourcesException {
5162d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        if (isRequested()) {
5172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            // We lost the gl context, so recreate it.
5182d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            if (!isEnabled()) {
519786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy                if (initialize(surface)) {
520fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                    setup(width, height);
521dfab363807b3b44be4032e410f016e0a0d018426Romain Guy                    return true;
5222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy                }
5232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            }
524dfab363807b3b44be4032e410f016e0a0d018426Romain Guy        }
525dfab363807b3b44be4032e410f016e0a0d018426Romain Guy        return false;
5262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
5272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
5282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
5292d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Creates a hardware renderer using OpenGL.
5302d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
5312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.)
532e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy     * @param translucent True if the surface is translucent, false otherwise
5332d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
5342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @return A hardware renderer backed by OpenGL.
5352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
536e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy    static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) {
5372d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        switch (glVersion) {
538e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            case 2:
539163935113919a184122b8b3bd672ef08c8df65dcRomain Guy                return Gl20Renderer.create(translucent);
5402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        }
5412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        throw new IllegalArgumentException("Unknown GL version: " + glVersion);
5422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
5432d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
5442d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
545bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * Invoke this method when the system is running out of memory. This
546bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * method will attempt to recover as much memory as possible, based on
547bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * the specified hint.
548bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     *
549bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     * @param level Hint about the amount of memory that should be trimmed,
550bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     *              see {@link android.content.ComponentCallbacks}
551bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy     */
552bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    static void trimMemory(int level) {
55319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        startTrimMemory(level);
55419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        endTrimMemory();
55519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    }
55619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy
55719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    /**
55819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * Starts the process of trimming memory. Usually this call will setup
55919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * hardware rendering context and reclaim memory.Extra cleanup might
56019f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * be required by calling {@link #endTrimMemory()}.
56119f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     *
56219f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * @param level Hint about the amount of memory that should be trimmed,
56319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     *              see {@link android.content.ComponentCallbacks}
56419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     */
56519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    static void startTrimMemory(int level) {
56619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        Gl20Renderer.startTrimMemory(level);
56719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    }
56819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy
56919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    /**
57019f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * Finishes the process of trimming memory. This method will usually
57119f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     * cleanup special resources used by the memory trimming process.
57219f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy     */
57319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy    static void endTrimMemory() {
57419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        Gl20Renderer.endTrimMemory();
575bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    }
576bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy
577bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy    /**
5782d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Indicates whether hardware acceleration is currently enabled.
5792d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
5802d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @return True if hardware acceleration is in use, false otherwise.
5812d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
5822d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    boolean isEnabled() {
5832d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        return mEnabled;
5842d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
5852d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
5862d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
5872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Indicates whether hardware acceleration is currently enabled.
5882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
5892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @param enabled True if the hardware renderer is in use, false otherwise.
5902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
5912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    void setEnabled(boolean enabled) {
5922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        mEnabled = enabled;
5932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
5942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
5952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
5962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * Indicates whether hardware acceleration is currently request but not
5972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * necessarily enabled yet.
5982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
5992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @return True if requested, false otherwise.
6002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
6012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    boolean isRequested() {
6022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        return mRequested;
6032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
6042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
6052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    /**
6069745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy     * Indicates whether hardware acceleration is currently requested but not
6072d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * necessarily enabled yet.
6082d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     *
6092d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     * @return True to request hardware acceleration, false otherwise.
6102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy     */
6112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    void setRequested(boolean requested) {
6122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        mRequested = requested;
6132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
6142d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
6152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    @SuppressWarnings({"deprecation"})
616e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy    static abstract class GlRenderer extends HardwareRenderer {
61716260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy        static final int SURFACE_STATE_ERROR = 0;
61816260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy        static final int SURFACE_STATE_SUCCESS = 1;
61916260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy        static final int SURFACE_STATE_UPDATED = 2;
6208f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
62165924a3e56c2e7ac863f8e25e9f9a58b9db7d513Chris Craik        static final int FUNCTOR_PROCESS_DELAY = 4;
6228f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
623fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        static EGL10 sEgl;
624fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        static EGLDisplay sEglDisplay;
625fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        static EGLConfig sEglConfig;
626566b3efb25299d2a9c8ae827522802bad965426aRomain Guy        static final Object[] sEglLock = new Object[0];
62740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        int mWidth = -1, mHeight = -1;
628e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
6295d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        static final ThreadLocal<ManagedEGLContext> sEglContextStorage
6305d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy                = new ThreadLocal<ManagedEGLContext>();
631566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
632566b3efb25299d2a9c8ae827522802bad965426aRomain Guy        EGLContext mEglContext;
633566b3efb25299d2a9c8ae827522802bad965426aRomain Guy        Thread mEglThread;
634fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
635fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        EGLSurface mEglSurface;
636fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
637e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        GL mGl;
63867f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy        HardwareCanvas mCanvas;
639a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
640a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka        long mFrameCount;
6417d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy        Paint mDebugPaint;
6427d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
6437e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        static boolean sDirtyRegions;
6447e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        static final boolean sDirtyRegionsRequested;
6457e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        static {
6467e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
6477e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            //noinspection PointlessBooleanExpression,ConstantConditions
6487e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
6497e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            sDirtyRegionsRequested = sDirtyRegions;
6507e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        }
6517e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy
6527e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        boolean mDirtyRegionsEnabled;
6539477c6e6581ce97976250951f33e1297604ac777Romain Guy        boolean mUpdateDirtyRegions;
6549477c6e6581ce97976250951f33e1297604ac777Romain Guy
6559ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        final boolean mVsyncDisabled;
6562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
657a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        final boolean mProfileEnabled;
658a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        final float[] mProfileData;
65977e67cf9055378d00bb57f458129462f33047039Romain Guy        final ReentrantLock mProfileLock;
660a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
661b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy
662b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy        final boolean mDebugDirtyRegions;
6637c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy        final boolean mShowOverdraw;
664a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
665e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        final int mGlVersion;
666e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        final boolean mTranslucent;
6672d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
668fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        private boolean mDestroyed;
669566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
670cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        private final Rect mRedrawClip = new Rect();
6718f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
6727687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        private final int[] mSurfaceSize = new int[2];
6738f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable();
674fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
675e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        GlRenderer(int glVersion, boolean translucent) {
676e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            mGlVersion = glVersion;
677e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            mTranslucent = translucent;
678b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy
679b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            String property;
6809ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
681b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            property = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false");
682b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            mVsyncDisabled = "true".equalsIgnoreCase(property);
6839ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            if (mVsyncDisabled) {
6849ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy                Log.d(LOG_TAG, "Disabling v-sync");
6859ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            }
686a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
68713b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy            property = SystemProperties.get(PROFILE_PROPERTY, "false");
68813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy            mProfileEnabled = "true".equalsIgnoreCase(property);
68913b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy            if (mProfileEnabled) {
69013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy                Log.d(LOG_TAG, "Profiling hardware renderer");
691a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            }
692a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
693a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            if (mProfileEnabled) {
69409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                property = SystemProperties.get(PROFILE_MAXFRAMES_PROPERTY,
69509280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                        Integer.toString(PROFILE_MAX_FRAMES));
69609280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                int maxProfileFrames = Integer.valueOf(property);
69709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
69809280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
69909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
70009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                }
70177e67cf9055378d00bb57f458129462f33047039Romain Guy
70277e67cf9055378d00bb57f458129462f33047039Romain Guy                mProfileLock = new ReentrantLock();
703a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            } else {
704a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                mProfileData = null;
70577e67cf9055378d00bb57f458129462f33047039Romain Guy                mProfileLock = null;
706a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            }
707b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy
708b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            property = SystemProperties.get(DEBUG_DIRTY_REGIONS_PROPERTY, "false");
709b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            mDebugDirtyRegions = "true".equalsIgnoreCase(property);
710b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            if (mDebugDirtyRegions) {
711b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                Log.d(LOG_TAG, "Debugging dirty regions");
712b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy            }
7137c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy
7147c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy            mShowOverdraw = SystemProperties.getBoolean(
7157c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy                    HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false);
716a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        }
717a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
718a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        @Override
719a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy        void dumpGfxInfo(PrintWriter pw) {
720a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            if (mProfileEnabled) {
721a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                pw.printf("\n\tDraw\tProcess\tExecute\n");
72277e67cf9055378d00bb57f458129462f33047039Romain Guy
72377e67cf9055378d00bb57f458129462f33047039Romain Guy                mProfileLock.lock();
72477e67cf9055378d00bb57f458129462f33047039Romain Guy                try {
72577e67cf9055378d00bb57f458129462f33047039Romain Guy                    for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
72677e67cf9055378d00bb57f458129462f33047039Romain Guy                        if (mProfileData[i] < 0) {
72777e67cf9055378d00bb57f458129462f33047039Romain Guy                            break;
72877e67cf9055378d00bb57f458129462f33047039Romain Guy                        }
72977e67cf9055378d00bb57f458129462f33047039Romain Guy                        pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
73077e67cf9055378d00bb57f458129462f33047039Romain Guy                                mProfileData[i + 2]);
73177e67cf9055378d00bb57f458129462f33047039Romain Guy                        mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
73209280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase                    }
73377e67cf9055378d00bb57f458129462f33047039Romain Guy                    mProfileCurrentFrame = mProfileData.length;
73477e67cf9055378d00bb57f458129462f33047039Romain Guy                } finally {
73577e67cf9055378d00bb57f458129462f33047039Romain Guy                    mProfileLock.unlock();
736a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                }
737a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy            }
7382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        }
7392d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
740a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka        @Override
741a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka        long getFrameCount() {
742a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka            return mFrameCount;
743a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka        }
744a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka
745e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        /**
74602ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy         * Indicates whether this renderer instance can track and update dirty regions.
74702ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy         */
74802ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy        boolean hasDirtyRegions() {
7497e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            return mDirtyRegionsEnabled;
75002ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy        }
75102ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy
75202ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy        /**
7534caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy         * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
754e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy         * is invoked and the requested flag is turned off. The error code is
755e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy         * also logged as a warning.
756e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy         */
757b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        void checkEglErrors() {
758e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            if (isEnabled()) {
759740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                checkEglErrorsForced();
760740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy            }
761740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy        }
762740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy
763740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy        private void checkEglErrorsForced() {
764740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy            int error = sEgl.eglGetError();
765740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy            if (error != EGL_SUCCESS) {
766740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                // something bad has happened revert to
767740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                // normal rendering.
768740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
769740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                fallback(error != EGL11.EGL_CONTEXT_LOST);
7702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            }
7712d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        }
77267f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy
7739745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy        private void fallback(boolean fallback) {
7749745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy            destroy(true);
7759745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy            if (fallback) {
7769745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy                // we'll try again if it was context lost
7779745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy                setRequested(false);
7789745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy                Log.w(LOG_TAG, "Mountain View, we've had a problem here. "
7799745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy                        + "Switching back to software rendering.");
7809745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy            }
7819745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy        }
7829745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy
783e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        @Override
784786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy        boolean initialize(Surface surface) throws Surface.OutOfResourcesException {
785e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            if (isRequested() && !isEnabled()) {
786e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                initializeEgl();
787786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy                mGl = createEglSurface(surface);
788fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                mDestroyed = false;
7892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
790e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                if (mGl != null) {
791fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                    int err = sEgl.eglGetError();
792484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    if (err != EGL_SUCCESS) {
7934caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy                        destroy(true);
794e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                        setRequested(false);
795e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                    } else {
7964caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy                        if (mCanvas == null) {
7974caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy                            mCanvas = createCanvas();
798fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                        }
799e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                        if (mCanvas != null) {
800e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                            setEnabled(true);
801e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                        } else {
802e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                            Log.w(LOG_TAG, "Hardware accelerated Canvas could not be created");
803e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                        }
804e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                    }
805e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
806e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                    return mCanvas != null;
807e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                }
808e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            }
809e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            return false;
810e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
8112a83f001fdb189f945e82e81e717ba204824b112Romain Guy
8122a83f001fdb189f945e82e81e717ba204824b112Romain Guy        @Override
813786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy        void updateSurface(Surface surface) throws Surface.OutOfResourcesException {
8142a83f001fdb189f945e82e81e717ba204824b112Romain Guy            if (isRequested() && isEnabled()) {
815786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy                createEglSurface(surface);
8162a83f001fdb189f945e82e81e717ba204824b112Romain Guy            }
8172a83f001fdb189f945e82e81e717ba204824b112Romain Guy        }
818e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
8195d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        abstract HardwareCanvas createCanvas();
8202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
82129d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy        abstract int[] getConfig(boolean dirtyRegions);
82229d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy
823e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        void initializeEgl() {
824566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            synchronized (sEglLock) {
825566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                if (sEgl == null && sEglConfig == null) {
826566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    sEgl = (EGL10) EGLContext.getEGL();
827566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
828566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    // Get to the default display.
829484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
830566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
831484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    if (sEglDisplay == EGL_NO_DISPLAY) {
832566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        throw new RuntimeException("eglGetDisplay failed "
833407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                                + GLUtils.getEGLErrorString(sEgl.eglGetError()));
834566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    }
835566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
836566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    // We can now initialize EGL for that display
837566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    int[] version = new int[2];
838566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    if (!sEgl.eglInitialize(sEglDisplay, version)) {
839566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        throw new RuntimeException("eglInitialize failed " +
840407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                                GLUtils.getEGLErrorString(sEgl.eglGetError()));
841566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                    }
842740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy
843740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy                    checkEglErrorsForced();
844740ee65d460401c266a7108c9aa4c6e7fbe58489Romain Guy
845e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy                    sEglConfig = chooseEglConfig();
846069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy                    if (sEglConfig == null) {
847566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
848566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        if (sDirtyRegions) {
849566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                            sDirtyRegions = false;
850566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                            sEglConfig = chooseEglConfig();
851566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                            if (sEglConfig == null) {
852566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                                throw new RuntimeException("eglConfig not initialized");
853566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                            }
854566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        } else {
855566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                            throw new RuntimeException("eglConfig not initialized");
856566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        }
857069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy                    }
858069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy                }
859069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy            }
860566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
8615d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy            ManagedEGLContext managedContext = sEglContextStorage.get();
862717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            mEglContext = managedContext != null ? managedContext.getContext() : null;
863566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            mEglThread = Thread.currentThread();
864566b3efb25299d2a9c8ae827522802bad965426aRomain Guy
865566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            if (mEglContext == null) {
866566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
8675d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy                sEglContextStorage.set(createManagedContext(mEglContext));
868566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            }
869e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
870e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
8715d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        abstract ManagedEGLContext createManagedContext(EGLContext eglContext);
8725d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy
873e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy        private EGLConfig chooseEglConfig() {
874e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            EGLConfig[] configs = new EGLConfig[1];
875484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            int[] configsCount = new int[1];
8767e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            int[] configSpec = getConfig(sDirtyRegions);
877484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
878484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            // Debug
87929d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy            final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
880484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            if ("all".equalsIgnoreCase(debug)) {
881484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
882484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
883484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
884484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
885484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                        configsCount[0], configsCount);
886484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
887484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                for (EGLConfig config : debugConfigs) {
888484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    printConfig(config);
889484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                }
890484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            }
891484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
892e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
893e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy                throw new IllegalArgumentException("eglChooseConfig failed " +
894407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
895e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            } else if (configsCount[0] > 0) {
896484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                if ("choice".equalsIgnoreCase(debug)) {
897484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    printConfig(configs[0]);
898484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                }
899e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy                return configs[0];
900e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            }
901484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
902e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            return null;
903e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy        }
904e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy
905e979e62ac7313b7cffe9b131bb8a99c356068b45Romain Guy        private static void printConfig(EGLConfig config) {
906484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            int[] value = new int[1];
907484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
908484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "EGL configuration " + config + ":");
909484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
910484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
911484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  RED_SIZE = " + value[0]);
912484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
913484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
914484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  GREEN_SIZE = " + value[0]);
915484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
916484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
917484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  BLUE_SIZE = " + value[0]);
918484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
919484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
920484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  ALPHA_SIZE = " + value[0]);
921484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
922484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
923484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  DEPTH_SIZE = " + value[0]);
924484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
925484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
926484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            Log.d(LOG_TAG, "  STENCIL_SIZE = " + value[0]);
927484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
9288efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value);
9298efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            Log.d(LOG_TAG, "  SAMPLE_BUFFERS = " + value[0]);
9308efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy
9318efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value);
9328efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            Log.d(LOG_TAG, "  SAMPLES = " + value[0]);
9338efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy
934484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
93529d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy            Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
9368efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy
9378efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value);
9388efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy            Log.d(LOG_TAG, "  CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
939484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy        }
940484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy
941786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy        GL createEglSurface(Surface surface) throws Surface.OutOfResourcesException {
942e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            // Check preconditions.
943fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            if (sEgl == null) {
944e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                throw new RuntimeException("egl not initialized");
945e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            }
946fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            if (sEglDisplay == null) {
947e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy                throw new RuntimeException("eglDisplay not initialized");
948e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            }
949fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            if (sEglConfig == null) {
950069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy                throw new RuntimeException("eglConfig not initialized");
951e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            }
952566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            if (Thread.currentThread() != mEglThread) {
953fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                throw new IllegalStateException("HardwareRenderer cannot be used "
954fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                        + "from multiple threads");
955fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            }
956e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
9576d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            // In case we need to destroy an existing surface
9586d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            destroySurface();
959e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
960e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            // Create an EGL surface we can render into.
961786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy            if (!createSurface(surface)) {
9621d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                return null;
963e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            }
964e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
9658ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy            initCaches();
9666f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy
9679477c6e6581ce97976250951f33e1297604ac777Romain Guy            return mEglContext.getGL();
9689477c6e6581ce97976250951f33e1297604ac777Romain Guy        }
9699477c6e6581ce97976250951f33e1297604ac777Romain Guy
9709477c6e6581ce97976250951f33e1297604ac777Romain Guy        private void enableDirtyRegions() {
9716f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy            // If mDirtyRegions is set, this means we have an EGL configuration
9726f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy            // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
9737e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            if (sDirtyRegions) {
974244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy                if (!(mDirtyRegionsEnabled = preserveBackBuffer())) {
9757d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                    Log.w(LOG_TAG, "Backbuffer cannot be preserved");
9767d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                }
9777e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            } else if (sDirtyRegionsRequested) {
9786f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // If mDirtyRegions is not set, our EGL configuration does not
9796f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
9806f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // swap behavior might be EGL_BUFFER_PRESERVED, which means we
9816f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // want to set mDirtyRegions. We try to do this only if dirty
9826f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // regions were initially requested as part of the device
9836f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy                // configuration (see RENDER_DIRTY_REGIONS)
984244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy                mDirtyRegionsEnabled = isBackBufferPreserved();
9857d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy            }
9862d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        }
9872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
9888ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        abstract void initCaches();
9898ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
990e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
991bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy            int[] attribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
992e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
993c002936e4bd042db3024202b3e9696835a730cfaRomain Guy            EGLContext context = egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
994c002936e4bd042db3024202b3e9696835a730cfaRomain Guy                    mGlVersion != 0 ? attribs : null);
995ed1b6f4fc0af836624b2edc2830eb918bf04cf3cRomain Guy            if (context == null || context == EGL_NO_CONTEXT) {
996c002936e4bd042db3024202b3e9696835a730cfaRomain Guy                //noinspection ConstantConditions
997c002936e4bd042db3024202b3e9696835a730cfaRomain Guy                throw new IllegalStateException(
998c002936e4bd042db3024202b3e9696835a730cfaRomain Guy                        "Could not create an EGL context. eglCreateContext failed with error: " +
999c002936e4bd042db3024202b3e9696835a730cfaRomain Guy                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
1000c002936e4bd042db3024202b3e9696835a730cfaRomain Guy            }
1001c002936e4bd042db3024202b3e9696835a730cfaRomain Guy            return context;
1002e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
1003e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
1004e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        @Override
10054caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy        void destroy(boolean full) {
10064caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy            if (full && mCanvas != null) {
10074caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy                mCanvas = null;
10084caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy            }
1009fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
1010357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy            if (!isEnabled() || mDestroyed) {
1011357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy                setEnabled(false);
1012357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy                return;
1013357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy            }
1014e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
10156d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            destroySurface();
1016357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy            setEnabled(false);
10172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
1018357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy            mDestroyed = true;
1019e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            mGl = null;
1020fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        }
1021fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
10226d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        void destroySurface() {
10236d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
10246d7475d666baefaa3ba9f0dcee25238739454241Romain Guy                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
10256d7475d666baefaa3ba9f0dcee25238739454241Romain Guy                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
10266d7475d666baefaa3ba9f0dcee25238739454241Romain Guy                mEglSurface = null;
10276d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            }
10286d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        }
10296d7475d666baefaa3ba9f0dcee25238739454241Romain Guy
10302d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        @Override
1031786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy        void invalidate(Surface surface) {
10327e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            // Cancels any existing buffer to ensure we'll get a buffer
10337e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy            // of the right size before we call eglSwapBuffers
1034cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
10351d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy
1036d3facf341bf106588aade72c0164532cd4bf941fRomain Guy            if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
1037d3facf341bf106588aade72c0164532cd4bf941fRomain Guy                sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
10381d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                mEglSurface = null;
10391d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                setEnabled(false);
1040d3facf341bf106588aade72c0164532cd4bf941fRomain Guy            }
1041cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy
1042786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy            if (surface.isValid()) {
1043786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy                if (!createSurface(surface)) {
10441d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                    return;
1045cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy                }
10469477c6e6581ce97976250951f33e1297604ac777Romain Guy
10479477c6e6581ce97976250951f33e1297604ac777Romain Guy                mUpdateDirtyRegions = true;
10489477c6e6581ce97976250951f33e1297604ac777Romain Guy
104986e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy                if (mCanvas != null) {
105086e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy                    setEnabled(true);
105186e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy                }
10521d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy            }
10531d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy        }
10541d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy
1055786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy        private boolean createSurface(Surface surface) {
1056786fc93d71b833ab6b02b0c7ea5e30f25cceeedfRomain Guy            mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
10571d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy
10581d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
10591d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                int error = sEgl.eglGetError();
10601d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                if (error == EGL_BAD_NATIVE_WINDOW) {
10611d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                    Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
10621d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                    return false;
10631d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                }
10641d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy                throw new RuntimeException("createWindowSurface failed "
1065407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                        + GLUtils.getEGLErrorString(error));
1066cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy            }
1067bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy
1068bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
1069bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy                throw new IllegalStateException("eglMakeCurrent failed " +
1070bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
1071bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy            }
1072bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy
1073bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy            enableDirtyRegions();
1074bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy
10751d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy            return true;
1076039857520b1a03a52051b966d87d587225bdfcc3Romain Guy        }
1077cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy
1078039857520b1a03a52051b966d87d587225bdfcc3Romain Guy        @Override
1079039857520b1a03a52051b966d87d587225bdfcc3Romain Guy        boolean validate() {
1080039857520b1a03a52051b966d87d587225bdfcc3Romain Guy            return checkCurrent() != SURFACE_STATE_ERROR;
10817e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        }
10827e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy
10837e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy        @Override
1084fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        void setup(int width, int height) {
1085eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy            if (validate()) {
1086eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy                mCanvas.setViewport(width, height);
108740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase                mWidth = width;
108840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase                mHeight = height;
1089eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy            }
1090e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
10917d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
109240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        @Override
109340e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        int getWidth() {
109440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase            return mWidth;
109540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        }
109640e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase
109740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        @Override
109840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        int getHeight() {
109940e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase            return mHeight;
110040e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase        }
110140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase
110208837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase        @Override
110308837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase        HardwareCanvas getCanvas() {
110408837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase            return mCanvas;
110508837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase        }
110608837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase
1107e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        boolean canDraw() {
1108e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            return mGl != null && mCanvas != null;
1109e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
1110e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
111144b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase        int onPreDraw(Rect dirty) {
111244b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return DisplayList.STATUS_DONE;
1113e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
1114e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
1115b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        void onPostDraw() {
1116b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        }
11172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy
11188f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        class FunctorsRunnable implements Runnable {
11198f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            View.AttachInfo attachInfo;
11208f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
11218f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            @Override
11228f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            public void run() {
11238f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                final HardwareRenderer renderer = attachInfo.mHardwareRenderer;
11248f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) {
11258f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    return;
11268f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                }
11278f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
11288f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                final int surfaceState = checkCurrent();
11298f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                if (surfaceState != SURFACE_STATE_ERROR) {
11308f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    int status = mCanvas.invokeFunctors(mRedrawClip);
11318f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    handleFunctorStatus(attachInfo, status);
11328f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                }
11338f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            }
11348f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        }
11358f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
11362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        @Override
113750d133e290468fd149b5c03e46549afca2ee05f8Romain Guy        boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
11387d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                Rect dirty) {
1139e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy            if (canDraw()) {
114002ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy                if (!hasDirtyRegions()) {
11417d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                    dirty = null;
11427d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                }
11432d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy                attachInfo.mIgnoreDirtyState = true;
114402ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy                attachInfo.mDrawingTime = SystemClock.uptimeMillis();
114502ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy
11464702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn                view.mPrivateFlags |= View.PFLAG_DRAWN;
1147039857520b1a03a52051b966d87d587225bdfcc3Romain Guy
1148d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                final int surfaceState = checkCurrent();
1149d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                if (surfaceState != SURFACE_STATE_ERROR) {
11507687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                    HardwareCanvas canvas = mCanvas;
11517687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                    attachInfo.mHardwareCanvas = canvas;
115277e67cf9055378d00bb57f458129462f33047039Romain Guy
115377e67cf9055378d00bb57f458129462f33047039Romain Guy                    if (mProfileEnabled) {
115477e67cf9055378d00bb57f458129462f33047039Romain Guy                        mProfileLock.lock();
115577e67cf9055378d00bb57f458129462f33047039Romain Guy                    }
115677e67cf9055378d00bb57f458129462f33047039Romain Guy
1157d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                    // We had to change the current surface and/or context, redraw everything
1158d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                    if (surfaceState == SURFACE_STATE_UPDATED) {
1159d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                        dirty = null;
11607687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                        beginFrame(null);
11617687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                    } else {
11627687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                        int[] size = mSurfaceSize;
11637687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                        beginFrame(size);
11647687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
11657687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                        if (size[1] != mHeight || size[0] != mWidth) {
11667687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                            mWidth = size[0];
11677687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                            mHeight = size[1];
11687687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
11697687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                            canvas.setViewport(mWidth, mHeight);
11707687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
11717687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                            dirty = null;
11727687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy                        }
1173d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                    }
1174d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy
11752b7028eabac80cec170572bc0e945a1d4224e595Romain Guy                    int saveCount = 0;
11762b7028eabac80cec170572bc0e945a1d4224e595Romain Guy                    int status = DisplayList.STATUS_DONE;
1177daf98e941e140e8739458126640183b9f296a2abChet Haase
1178b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                    try {
11794702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn                        view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
11804702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn                                == View.PFLAG_INVALIDATED;
11814702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn                        view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
11827d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy
1183a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                        long getDisplayListStartTime = 0;
1184a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                        if (mProfileEnabled) {
1185a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT;
1186a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            if (mProfileCurrentFrame >= mProfileData.length) {
1187a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                                mProfileCurrentFrame = 0;
1188a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            }
1189a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy
119095db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                            getDisplayListStartTime = System.nanoTime();
119195db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                        }
119295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
119311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                        canvas.clearLayerUpdates();
119477e67cf9055378d00bb57f458129462f33047039Romain Guy
119511cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy                        DisplayList displayList;
119677e67cf9055378d00bb57f458129462f33047039Romain Guy                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
119777e67cf9055378d00bb57f458129462f33047039Romain Guy                        try {
119877e67cf9055378d00bb57f458129462f33047039Romain Guy                            displayList = view.getDisplayList();
119977e67cf9055378d00bb57f458129462f33047039Romain Guy                        } finally {
120077e67cf9055378d00bb57f458129462f33047039Romain Guy                            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
120177e67cf9055378d00bb57f458129462f33047039Romain Guy                        }
120295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
12037c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
12047c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                        try {
12057c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                            status = onPreDraw(dirty);
12067c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                        } finally {
12077c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
12087c25aab491707f7324f9941b8cfa9bd2b4b97e76Romain Guy                        }
12092b7028eabac80cec170572bc0e945a1d4224e595Romain Guy                        saveCount = canvas.save();
12102b7028eabac80cec170572bc0e945a1d4224e595Romain Guy                        callbacks.onHardwarePreDraw(canvas);
12112b7028eabac80cec170572bc0e945a1d4224e595Romain Guy
1212a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                        if (mProfileEnabled) {
121395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                            long now = System.nanoTime();
1214a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            float total = (now - getDisplayListStartTime) * 0.000001f;
1215a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            //noinspection PointlessArithmeticExpression
1216a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            mProfileData[mProfileCurrentFrame] = total;
121795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                        }
121895db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
1219daf98e941e140e8739458126640183b9f296a2abChet Haase                        if (displayList != null) {
1220a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            long drawDisplayListStartTime = 0;
1221a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            if (mProfileEnabled) {
122295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                                drawDisplayListStartTime = System.nanoTime();
122395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                            }
122495db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
122577e67cf9055378d00bb57f458129462f33047039Romain Guy                            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList");
122677e67cf9055378d00bb57f458129462f33047039Romain Guy                            try {
122777e67cf9055378d00bb57f458129462f33047039Romain Guy                                status |= canvas.drawDisplayList(displayList, mRedrawClip,
122877e67cf9055378d00bb57f458129462f33047039Romain Guy                                        DisplayList.FLAG_CLIP_CHILDREN);
122977e67cf9055378d00bb57f458129462f33047039Romain Guy                            } finally {
123077e67cf9055378d00bb57f458129462f33047039Romain Guy                                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
123177e67cf9055378d00bb57f458129462f33047039Romain Guy                            }
123295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
1233a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                            if (mProfileEnabled) {
123495db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                                long now = System.nanoTime();
1235a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                                float total = (now - drawDisplayListStartTime) * 0.000001f;
1236a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy                                mProfileData[mProfileCurrentFrame + 1] = total;
123795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                            }
123895db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
12398f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                            handleFunctorStatus(attachInfo, status);
1240daf98e941e140e8739458126640183b9f296a2abChet Haase                        } else {
1241daf98e941e140e8739458126640183b9f296a2abChet Haase                            // Shouldn't reach here
1242daf98e941e140e8739458126640183b9f296a2abChet Haase                            view.draw(canvas);
1243daf98e941e140e8739458126640183b9f296a2abChet Haase                        }
1244b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                    } finally {
1245b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                        callbacks.onHardwarePostDraw(canvas);
1246b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                        canvas.restoreToCount(saveCount);
1247b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                        view.mRecreateDisplayList = false;
124819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy
1249a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka                        mFrameCount++;
125019f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy
1251b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy                        if (mDebugDirtyRegions) {
12527d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                            if (mDebugPaint == null) {
12537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                                mDebugPaint = new Paint();
12547d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                                mDebugPaint.setColor(0x7fff0000);
12557d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                            }
125619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy
1257a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka                            if (dirty != null && (mFrameCount & 1) == 0) {
12587d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                                canvas.drawRect(dirty, mDebugPaint);
12597d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                            }
12607d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy                        }
1261b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                    }
1262daf98e941e140e8739458126640183b9f296a2abChet Haase
1263b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                    onPostDraw();
1264daf98e941e140e8739458126640183b9f296a2abChet Haase
1265b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                    attachInfo.mIgnoreDirtyState = false;
1266486590963e2207d68eebd6944fec70d50d41116aChet Haase
1267486590963e2207d68eebd6944fec70d50d41116aChet Haase                    if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) {
1268486590963e2207d68eebd6944fec70d50d41116aChet Haase                        long eglSwapBuffersStartTime = 0;
1269486590963e2207d68eebd6944fec70d50d41116aChet Haase                        if (mProfileEnabled) {
1270486590963e2207d68eebd6944fec70d50d41116aChet Haase                            eglSwapBuffersStartTime = System.nanoTime();
1271486590963e2207d68eebd6944fec70d50d41116aChet Haase                        }
1272486590963e2207d68eebd6944fec70d50d41116aChet Haase
1273486590963e2207d68eebd6944fec70d50d41116aChet Haase                        sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
1274486590963e2207d68eebd6944fec70d50d41116aChet Haase
1275486590963e2207d68eebd6944fec70d50d41116aChet Haase                        if (mProfileEnabled) {
1276486590963e2207d68eebd6944fec70d50d41116aChet Haase                            long now = System.nanoTime();
1277486590963e2207d68eebd6944fec70d50d41116aChet Haase                            float total = (now - eglSwapBuffersStartTime) * 0.000001f;
1278486590963e2207d68eebd6944fec70d50d41116aChet Haase                            mProfileData[mProfileCurrentFrame + 2] = total;
1279486590963e2207d68eebd6944fec70d50d41116aChet Haase                        }
1280486590963e2207d68eebd6944fec70d50d41116aChet Haase
1281486590963e2207d68eebd6944fec70d50d41116aChet Haase                        checkEglErrors();
128295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown                    }
128395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown
128477e67cf9055378d00bb57f458129462f33047039Romain Guy                    if (mProfileEnabled) {
128577e67cf9055378d00bb57f458129462f33047039Romain Guy                        mProfileLock.unlock();
128677e67cf9055378d00bb57f458129462f33047039Romain Guy                    }
128777e67cf9055378d00bb57f458129462f33047039Romain Guy
128850d133e290468fd149b5c03e46549afca2ee05f8Romain Guy                    return dirty == null;
12899a40babc62416259d18783ce8c03c00042ec317bRomain Guy                }
12902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            }
129150d133e290468fd149b5c03e46549afca2ee05f8Romain Guy
129250d133e290468fd149b5c03e46549afca2ee05f8Romain Guy            return false;
12932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        }
1294039857520b1a03a52051b966d87d587225bdfcc3Romain Guy
12958f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        private void handleFunctorStatus(View.AttachInfo attachInfo, int status) {
12968f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            // If the draw flag is set, functors will be invoked while executing
12978f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            // the tree of display lists
12988f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            if ((status & DisplayList.STATUS_DRAW) != 0) {
12998f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                if (mRedrawClip.isEmpty()) {
13008f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    attachInfo.mViewRootImpl.invalidate();
13018f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                } else {
13028f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip);
13038f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                    mRedrawClip.setEmpty();
13048f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                }
13058f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            }
13068f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
13078f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            if ((status & DisplayList.STATUS_INVOKE) != 0) {
1308cb82b942c89bf69b6c03e2f4951f519c1be115dcChris Craik                scheduleFunctors(attachInfo, true);
1309ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            }
1310ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        }
1311ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
1312cb82b942c89bf69b6c03e2f4951f519c1be115dcChris Craik        private void scheduleFunctors(View.AttachInfo attachInfo, boolean delayed) {
1313ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            mFunctorsRunnable.attachInfo = attachInfo;
1314ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
13158f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy                // delay the functor callback by a few ms so it isn't polled constantly
1316cb82b942c89bf69b6c03e2f4951f519c1be115dcChris Craik                attachInfo.mHandler.postDelayed(mFunctorsRunnable,
1317cb82b942c89bf69b6c03e2f4951f519c1be115dcChris Craik                                                delayed ? FUNCTOR_PROCESS_DELAY : 0);
13188f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy            }
13198f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy        }
13208f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy
1321ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        @Override
1322ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        void detachFunctor(int functor) {
1323ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            if (mCanvas != null) {
1324ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy                mCanvas.detachFunctor(functor);
1325932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik            }
1326ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        }
1327ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
1328ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        @Override
132941ee465734d0006797a8fd36e88976c1e85d161cChris Craik        boolean attachFunctor(View.AttachInfo attachInfo, int functor) {
1330ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            if (mCanvas != null) {
1331ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy                mCanvas.attachFunctor(functor);
1332cb82b942c89bf69b6c03e2f4951f519c1be115dcChris Craik                scheduleFunctors(attachInfo, false);
133341ee465734d0006797a8fd36e88976c1e85d161cChris Craik                return true;
1334ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy            }
133541ee465734d0006797a8fd36e88976c1e85d161cChris Craik            return false;
1336ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy        }
1337ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy
1338039857520b1a03a52051b966d87d587225bdfcc3Romain Guy        /**
1339566b3efb25299d2a9c8ae827522802bad965426aRomain Guy         * Ensures the current EGL context is the one we expect.
1340039857520b1a03a52051b966d87d587225bdfcc3Romain Guy         *
1341039857520b1a03a52051b966d87d587225bdfcc3Romain Guy         * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
1342039857520b1a03a52051b966d87d587225bdfcc3Romain Guy         *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
1343039857520b1a03a52051b966d87d587225bdfcc3Romain Guy         *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
1344039857520b1a03a52051b966d87d587225bdfcc3Romain Guy         */
1345912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy        int checkCurrent() {
1346566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            if (mEglThread != Thread.currentThread()) {
1347039857520b1a03a52051b966d87d587225bdfcc3Romain Guy                throw new IllegalStateException("Hardware acceleration can only be used with a " +
1348566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                        "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
1349039857520b1a03a52051b966d87d587225bdfcc3Romain Guy                        "Current thread: " + Thread.currentThread());
1350039857520b1a03a52051b966d87d587225bdfcc3Romain Guy            }
1351039857520b1a03a52051b966d87d587225bdfcc3Romain Guy
1352566b3efb25299d2a9c8ae827522802bad965426aRomain Guy            if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
1353484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
1354566b3efb25299d2a9c8ae827522802bad965426aRomain Guy                if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
13559745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy                    Log.e(LOG_TAG, "eglMakeCurrent failed " +
1356407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                            GLUtils.getEGLErrorString(sEgl.eglGetError()));
1357eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy                    fallback(true);
1358d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                    return SURFACE_STATE_ERROR;
1359d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                } else {
13609477c6e6581ce97976250951f33e1297604ac777Romain Guy                    if (mUpdateDirtyRegions) {
13619477c6e6581ce97976250951f33e1297604ac777Romain Guy                        enableDirtyRegions();
13629477c6e6581ce97976250951f33e1297604ac777Romain Guy                        mUpdateDirtyRegions = false;
13639477c6e6581ce97976250951f33e1297604ac777Romain Guy                    }
1364d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy                    return SURFACE_STATE_UPDATED;
1365fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy                }
1366fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy            }
1367d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy            return SURFACE_STATE_SUCCESS;
1368fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        }
1369e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy    }
1370fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
1371e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy    /**
1372e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy     * Hardware renderer using OpenGL ES 2.0.
1373e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy     */
1374e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy    static class Gl20Renderer extends GlRenderer {
1375e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        private GLES20Canvas mGlCanvas;
1376e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1377912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy        private static EGLSurface sPbuffer;
1378912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy        private static final Object[] sPbufferLock = new Object[0];
1379912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy
138031f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy        static class Gl20RendererEglContext extends ManagedEGLContext {
1381717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            final Handler mHandler = new Handler();
1382717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
138331f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy            public Gl20RendererEglContext(EGLContext context) {
1384717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                super(context);
1385717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            }
1386717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1387717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            @Override
1388717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            public void onTerminate(final EGLContext eglContext) {
1389717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                // Make sure we do this on the correct thread.
1390717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                if (mHandler.getLooper() != Looper.myLooper()) {
1391717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    mHandler.post(new Runnable() {
13925d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy                        @Override
13935d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy                        public void run() {
1394717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                            onTerminate(eglContext);
1395717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        }
1396717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    });
1397717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    return;
1398717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                }
1399717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1400717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                synchronized (sEglLock) {
1401717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    if (sEgl == null) return;
1402717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1403717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    if (EGLImpl.getInitCount(sEglDisplay) == 1) {
1404717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        usePbufferSurface(eglContext);
1405717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        GLES20Canvas.terminateCaches();
1406717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1407717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEgl.eglDestroyContext(sEglDisplay, eglContext);
1408a998dff5d49a423aaf7097aa8f96bf5bdc681d25Romain Guy                        sEglContextStorage.set(null);
1409717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEglContextStorage.remove();
1410717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1411717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
141231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                        sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
141331f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                                EGL_NO_SURFACE, EGL_NO_CONTEXT);
1414717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1415717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEgl.eglReleaseThread();
1416717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEgl.eglTerminate(sEglDisplay);
1417717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1418717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEgl = null;
1419717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEglDisplay = null;
1420717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sEglConfig = null;
1421717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                        sPbuffer = null;
1422717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                    }
1423717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                }
1424717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            }
1425717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn        }
1426717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn
1427e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        Gl20Renderer(boolean translucent) {
1428e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            super(2, translucent);
1429e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
1430e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
14312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy        @Override
14325d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        HardwareCanvas createCanvas() {
14336b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy            return mGlCanvas = new GLES20Canvas(mTranslucent);
1434e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        }
1435e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy
1436e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy        @Override
14375d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        ManagedEGLContext createManagedContext(EGLContext eglContext) {
14385d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy            return new Gl20Renderer.Gl20RendererEglContext(mEglContext);
14395d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        }
14405d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy
14415d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy        @Override
1442e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy        int[] getConfig(boolean dirtyRegions) {
1443e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            return new int[] {
1444bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy                    EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
1445484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_RED_SIZE, 8,
1446484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_GREEN_SIZE, 8,
1447484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_BLUE_SIZE, 8,
1448484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_ALPHA_SIZE, 8,
1449484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_DEPTH_SIZE, 0,
14508efca54693b1fa956eede0367fffe8bb0d3531f0Romain Guy                    EGL_CONFIG_CAVEAT, EGL_NONE,
14517c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy                    // TODO: Find a better way to choose the stencil size
14527c450aaa3caac2a05fcb20a177483d0e92378426Romain Guy                    EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0,
1453484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
1454bd43152bda835c5a9a619a5869344a6a3af11917Romain Guy                            (dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
1455484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy                    EGL_NONE
1456e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy            };
1457e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy        }
14588ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
14598ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        @Override
14608ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        void initCaches() {
14618ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy            GLES20Canvas.initCaches();
14628ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        }
1463e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy
1464b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy        @Override
1465b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy        boolean canDraw() {
1466b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy            return super.canDraw() && mGlCanvas != null;
1467b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy        }
1468e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1469e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        @Override
147044b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase        int onPreDraw(Rect dirty) {
147144b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase            return mGlCanvas.onPreDraw(dirty);
1472e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy        }
1473e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy
1474b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        @Override
1475b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        void onPostDraw() {
1476b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy            mGlCanvas.onPostDraw();
1477b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy        }
1478b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy
1479b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        @Override
148067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy        void destroy(boolean full) {
1481b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy            try {
1482b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                super.destroy(full);
1483b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy            } finally {
1484b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                if (full && mGlCanvas != null) {
1485b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                    mGlCanvas = null;
1486b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy                }
148767f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy            }
148867f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy        }
148967f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy
149067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy        @Override
14919ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        void setup(int width, int height) {
14929ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            super.setup(width, height);
14939ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            if (mVsyncDisabled) {
1494244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy                disableVsync();
14959ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy            }
14969ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        }
14979ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy
14989ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy        @Override
149911cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        void pushLayerUpdate(HardwareLayer layer) {
150011cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy            mGlCanvas.pushLayerUpdate(layer);
150111cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        }
150211cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy
150311cb642756093a4af901b1525375b1eb2b5c3e2bRomain Guy        @Override
150413631f3da855f200a151e7837ed9f6b079622b58Romain Guy        public DisplayList createDisplayList(String name) {
150513631f3da855f200a151e7837ed9f6b079622b58Romain Guy            return new GLES20DisplayList(name);
1506b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        }
1507aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
1508aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        @Override
1509a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy        HardwareLayer createHardwareLayer(boolean isOpaque) {
1510a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy            return new GLES20TextureLayer(isOpaque);
1511aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        }
1512aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
15136c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        @Override
15146c319ca1275c8db892c39b48fc54864c949f9171Romain Guy        HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
1515aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy            return new GLES20RenderLayer(width, height, isOpaque);
1516aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        }
1517aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
1518aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        @Override
1519e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy        SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
1520aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy            return ((GLES20TextureLayer) layer).getSurfaceTexture();
1521aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy        }
1522aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy
15236d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        @Override
15242af3524beb75150d347accc925022daa53b4a789Jamie Gennis        void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
15252af3524beb75150d347accc925022daa53b4a789Jamie Gennis            ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
15262af3524beb75150d347accc925022daa53b4a789Jamie Gennis        }
15272af3524beb75150d347accc925022daa53b4a789Jamie Gennis
15282af3524beb75150d347accc925022daa53b4a789Jamie Gennis        @Override
15291ac4765e959c79101f64b1279887ed469334c268Romain Guy        boolean safelyRun(Runnable action) {
15301ac4765e959c79101f64b1279887ed469334c268Romain Guy            boolean needsContext = true;
15311ac4765e959c79101f64b1279887ed469334c268Romain Guy            if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
15321ac4765e959c79101f64b1279887ed469334c268Romain Guy
15331ac4765e959c79101f64b1279887ed469334c268Romain Guy            if (needsContext) {
15341ac4765e959c79101f64b1279887ed469334c268Romain Guy                Gl20RendererEglContext managedContext =
15351ac4765e959c79101f64b1279887ed469334c268Romain Guy                        (Gl20RendererEglContext) sEglContextStorage.get();
15361ac4765e959c79101f64b1279887ed469334c268Romain Guy                if (managedContext == null) return false;
15371ac4765e959c79101f64b1279887ed469334c268Romain Guy                usePbufferSurface(managedContext.getContext());
15381ac4765e959c79101f64b1279887ed469334c268Romain Guy            }
15390872b370422eb1f9007b4717b8796543873e6390Jesse Hall
15401ac4765e959c79101f64b1279887ed469334c268Romain Guy            try {
15411ac4765e959c79101f64b1279887ed469334c268Romain Guy                action.run();
15421ac4765e959c79101f64b1279887ed469334c268Romain Guy            } finally {
15430872b370422eb1f9007b4717b8796543873e6390Jesse Hall                if (needsContext) {
15440872b370422eb1f9007b4717b8796543873e6390Jesse Hall                    sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
15450872b370422eb1f9007b4717b8796543873e6390Jesse Hall                            EGL_NO_SURFACE, EGL_NO_CONTEXT);
15460872b370422eb1f9007b4717b8796543873e6390Jesse Hall                }
154731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy            }
15481ac4765e959c79101f64b1279887ed469334c268Romain Guy
15491ac4765e959c79101f64b1279887ed469334c268Romain Guy            return true;
15501ac4765e959c79101f64b1279887ed469334c268Romain Guy        }
15511ac4765e959c79101f64b1279887ed469334c268Romain Guy
15521ac4765e959c79101f64b1279887ed469334c268Romain Guy        @Override
1553bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy        void destroyLayers(final View view) {
1554bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy            if (view != null) {
1555bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                safelyRun(new Runnable() {
1556bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                    @Override
1557bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                    public void run() {
1558bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                        if (mCanvas != null) {
1559bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                            mCanvas.clearLayerUpdates();
1560bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                        }
1561bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                        destroyHardwareLayer(view);
1562bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                        GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
1563bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                    }
1564bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                });
1565bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy            }
1566bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy        }
1567bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy
1568bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy        private static void destroyHardwareLayer(View view) {
1569bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy            view.destroyLayer(true);
1570bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy
1571bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy            if (view instanceof ViewGroup) {
1572bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                ViewGroup group = (ViewGroup) view;
1573bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy
1574bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                int count = group.getChildCount();
1575bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                for (int i = 0; i < count; i++) {
1576bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                    destroyHardwareLayer(group.getChildAt(i));
1577bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy                }
1578bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy            }
1579bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy        }
1580bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy
1581bd17bd34311ba5af4b6ac9ddc4b8c71888f2e6f1Romain Guy        @Override
15821ac4765e959c79101f64b1279887ed469334c268Romain Guy        void destroyHardwareResources(final View view) {
15831ac4765e959c79101f64b1279887ed469334c268Romain Guy            if (view != null) {
15841ac4765e959c79101f64b1279887ed469334c268Romain Guy                safelyRun(new Runnable() {
15851ac4765e959c79101f64b1279887ed469334c268Romain Guy                    @Override
15861ac4765e959c79101f64b1279887ed469334c268Romain Guy                    public void run() {
15876a2d17f71342f981c9df1dc5beff33e30eb3ae2bChet Haase                        if (mCanvas != null) {
15886a2d17f71342f981c9df1dc5beff33e30eb3ae2bChet Haase                            mCanvas.clearLayerUpdates();
15896a2d17f71342f981c9df1dc5beff33e30eb3ae2bChet Haase                        }
15901ac4765e959c79101f64b1279887ed469334c268Romain Guy                        destroyResources(view);
15911ac4765e959c79101f64b1279887ed469334c268Romain Guy                        GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
15921ac4765e959c79101f64b1279887ed469334c268Romain Guy                    }
15931ac4765e959c79101f64b1279887ed469334c268Romain Guy                });
15941ac4765e959c79101f64b1279887ed469334c268Romain Guy            }
159531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy        }
1596244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
159731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy        private static void destroyResources(View view) {
159831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy            view.destroyHardwareResources();
159931f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy
160031f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy            if (view instanceof ViewGroup) {
160131f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                ViewGroup group = (ViewGroup) view;
160231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy
160331f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                int count = group.getChildCount();
160431f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                for (int i = 0; i < count; i++) {
160531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                    destroyResources(group.getChildAt(i));
160631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy                }
160731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy            }
160831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy        }
16096d7475d666baefaa3ba9f0dcee25238739454241Romain Guy
16106d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        static HardwareRenderer create(boolean translucent) {
16116d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            if (GLES20Canvas.isAvailable()) {
16126d7475d666baefaa3ba9f0dcee25238739454241Romain Guy                return new Gl20Renderer(translucent);
16136d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            }
16146d7475d666baefaa3ba9f0dcee25238739454241Romain Guy            return null;
16156d7475d666baefaa3ba9f0dcee25238739454241Romain Guy        }
16166d7475d666baefaa3ba9f0dcee25238739454241Romain Guy
161719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        static void startTrimMemory(int level) {
1618912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy            if (sEgl == null || sEglConfig == null) return;
1619912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy
16205d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy            Gl20RendererEglContext managedContext =
16215d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy                    (Gl20RendererEglContext) sEglContextStorage.get();
1622912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy            // We do not have OpenGL objects
1623717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn            if (managedContext == null) {
1624912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy                return;
1625912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy            } else {
1626717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn                usePbufferSurface(managedContext.getContext());
16272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy            }
1628912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy
162927ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
163027ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
163127ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn            } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
163227ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
1633bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy            }
163419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        }
16350872b370422eb1f9007b4717b8796543873e6390Jesse Hall
163619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy        static void endTrimMemory() {
163719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy            if (sEgl != null && sEglDisplay != null) {
163819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
163919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy            }
1640bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy        }
16418ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy
16428ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        private static void usePbufferSurface(EGLContext eglContext) {
16438ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy            synchronized (sPbufferLock) {
16448ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                // Create a temporary 1x1 pbuffer so we have a context
16458ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                // to clear our OpenGL objects
16468ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                if (sPbuffer == null) {
16478ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                    sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
16488ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                            EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
16498ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                    });
16508ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy                }
16518ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy            }
16528ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy            sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
16538ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy        }
16542d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy    }
16552d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy}
1656