HardwareRenderer.java revision 44b2fe3fc114ee5f7273c6b0fee2cc999bf244a2
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; 24407ec78b828173257b0c5dae221649a4ccd8b058Romain Guyimport android.opengl.GLUtils; 25717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.opengl.ManagedEGLContext; 26717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.os.Handler; 27717a25dc2a411edb548859cd6870363346c71b01Dianne Hackbornimport android.os.Looper; 2802ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemClock; 2902ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemProperties; 30e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport android.util.Log; 318ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guyimport com.google.android.gles_jni.EGLImpl; 322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 332d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL10; 342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL11; 352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLConfig; 362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLContext; 372d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLDisplay; 382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLSurface; 39e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport javax.microedition.khronos.opengles.GL; 402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 41a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guyimport java.io.File; 42a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guyimport java.io.PrintWriter; 43a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy 44484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guyimport static javax.microedition.khronos.egl.EGL10.*; 45484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 462d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy/** 47c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * Interface for rendering a ViewAncestor using hardware acceleration. 482d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @hide 502d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 5161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guypublic abstract class HardwareRenderer { 524f6aff386045000c2c03b903c7109cb42092b7eaRomain Guy static final String LOG_TAG = "HardwareRenderer"; 53fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 545233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 55a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * Name of the file that holds the shaders cache. 56a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy */ 57a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; 58a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy 59a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy /** 607d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to only refresh the parts of the screen that need updating. 61069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY} 62069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * must also have the value "true". 637d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 647d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy public static final boolean RENDER_DIRTY_REGIONS = true; 657d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 667d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 67069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * System property used to enable or disable dirty regions invalidation. 68069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true. 69069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * The default value of this property is assumed to be true. 70069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 71069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Possible values: 72069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * "true", to enable partial invalidates 73069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * "false", to disable partial invalidates 74069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 754b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions"; 769ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 779ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy /** 789ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * System property used to enable or disable vsync. 799ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * The default value of this property is assumed to be false. 809ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * 819ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * Possible values: 829ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * "true", to disable vsync 839ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * "false", to enable vsync 849ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy */ 854b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy static final String DISABLE_VSYNC_PROPERTY = "debug.hwui.disable_vsync"; 86069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy 87069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 88a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * System property used to enable or disable hardware rendering profiling. 89a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * The default value of this property is assumed to be false. 9009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * 91a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * When profiling is enabled, the adb shell dumpsys gfxinfo command will 92a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * output extra information about the time taken to execute by the last 93a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * frames. 94a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * 95a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * Possible values: 96a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * "true", to enable profiling 97a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * "false", to disable profiling 984b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy * 994b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy * @hide 100a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy */ 1014b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy public static final String PROFILE_PROPERTY = "debug.hwui.profile"; 102a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 103a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy /** 10409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * System property used to specify the number of frames to be used 10509280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * when doing hardware rendering profiling. 10609280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * The default value of this property is #PROFILE_MAX_FRAMES. 10709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * 10809280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * When profiling is enabled, the adb shell dumpsys gfxinfo command will 10909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * output extra information about the time taken to execute by the last 11009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * frames. 11109280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * 11209280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * Possible values: 11309280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase * "60", to set the limit of frames to 60 11409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase */ 1154b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes"; 11609280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase 11709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase /** 118484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * System property used to debug EGL configuration choice. 119484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * 120484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * Possible values: 121484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * "choice", print the chosen configuration only 122484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * "all", print all possible configurations 123484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy */ 1244b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config"; 125484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 126484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy /** 1277d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to draw dirty regions every other frame. 128b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy * 129b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy * Possible values: 130b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy * "true", to enable dirty regions debugging 131b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy * "false", to disable dirty regions debugging 1324b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy * 1334b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy * @hide 1347d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 1354b8c4f886b3d57e6ffe1a4650487c67334674a40Romain Guy public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions"; 1367d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 1377d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 1385233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * A process can set this flag to false to prevent the use of hardware 1395233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * rendering. 1405233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 1415233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 1425233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 1435233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy public static boolean sRendererDisabled = false; 1445233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 1455d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn /** 1465d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn * Further hardware renderer disabling for the system process. 1475d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn * 1485d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn * @hide 1495d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn */ 1505d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn public static boolean sSystemRendererDisabled = false; 1515d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn 152a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy /** 153a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * Number of frames to profile. 154a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy */ 155a21f877434dd25a93869b8641e3c38618bf317a9Romain Guy private static final int PROFILE_MAX_FRAMES = 128; 156a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 157a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy /** 158a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * Number of floats per profiled frame. 159a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy */ 160a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy private static final int PROFILE_FRAME_DATA_COUNT = 3; 161a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 1622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mEnabled; 1632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mRequested = true; 1642d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1652d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 16667f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy * Invoke this method to disable hardware rendering in the current process. 1675233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 1685233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 1695233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 1705d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn public static void disable(boolean system) { 1715233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy sRendererDisabled = true; 1725d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn if (system) { 1735d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn sSystemRendererDisabled = true; 1745d927c2d8e832fcfcb0154c8741f896001141ef4Dianne Hackborn } 1755233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy } 1765233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 1775233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 17861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * Indicates whether hardware acceleration is available under any form for 17961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * the view hierarchy. 18061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * 18161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * @return True if the view hierarchy can potentially be hardware accelerated, 18261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * false otherwise 18361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy */ 18461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy public static boolean isAvailable() { 18561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy return GLES20Canvas.isAvailable(); 18661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } 18761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy 18861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy /** 1892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Destroys the hardware rendering context. 1904caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * 1914caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * @param full If true, destroys all associated resources. 1922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1934caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy abstract void destroy(boolean full); 1942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface. 1972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param holder The holder for the surface to hardware accelerate. 1992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if the initialization was successful, false otherwise. 2012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 202648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn abstract boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException; 2032a83f001fdb189f945e82e81e717ba204824b112Romain Guy 2042a83f001fdb189f945e82e81e717ba204824b112Romain Guy /** 2052a83f001fdb189f945e82e81e717ba204824b112Romain Guy * Updates the hardware renderer for the specified surface. 2062a83f001fdb189f945e82e81e717ba204824b112Romain Guy * 207cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy * @param holder The holder for the surface to hardware accelerate 2082a83f001fdb189f945e82e81e717ba204824b112Romain Guy */ 209648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException; 2102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 21231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy * Destroys the layers used by the specified view hierarchy. 2136d7475d666baefaa3ba9f0dcee25238739454241Romain Guy * 2146d7475d666baefaa3ba9f0dcee25238739454241Romain Guy * @param view The root of the view hierarchy 2156d7475d666baefaa3ba9f0dcee25238739454241Romain Guy */ 2166d7475d666baefaa3ba9f0dcee25238739454241Romain Guy abstract void destroyLayers(View view); 2176d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 2186d7475d666baefaa3ba9f0dcee25238739454241Romain Guy /** 21931f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy * Destroys all hardware rendering resources associated with the specified 22031f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy * view hierarchy. 22131f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy * 22231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy * @param view The root of the view hierarchy 22331f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy */ 22431f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy abstract void destroyHardwareResources(View view); 22531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy 22631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy /** 227039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * This method should be invoked whenever the current hardware renderer 228cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy * context should be reset. 229cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy * 230cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy * @param holder The holder for the surface to hardware accelerate 2317e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy */ 232cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy abstract void invalidate(SurfaceHolder holder); 233039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 234039857520b1a03a52051b966d87d587225bdfcc3Romain Guy /** 235039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * This method should be invoked to ensure the hardware renderer is in 236039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * valid state (for instance, to ensure the correct EGL context is bound 237039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * to the current thread.) 238039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * 239039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * @return true if the renderer is now valid, false otherwise 240039857520b1a03a52051b966d87d587225bdfcc3Romain Guy */ 241039857520b1a03a52051b966d87d587225bdfcc3Romain Guy abstract boolean validate(); 2427e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 2437e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy /** 2441ac4765e959c79101f64b1279887ed469334c268Romain Guy * This method ensures the hardware renderer is in a valid state 2451ac4765e959c79101f64b1279887ed469334c268Romain Guy * before executing the specified action. 2461ac4765e959c79101f64b1279887ed469334c268Romain Guy * 2471ac4765e959c79101f64b1279887ed469334c268Romain Guy * This method will attempt to set a valid state even if the window 2481ac4765e959c79101f64b1279887ed469334c268Romain Guy * the renderer is attached to was destroyed. 2491ac4765e959c79101f64b1279887ed469334c268Romain Guy * 2501ac4765e959c79101f64b1279887ed469334c268Romain Guy * @return true if the action was run 2511ac4765e959c79101f64b1279887ed469334c268Romain Guy */ 2521ac4765e959c79101f64b1279887ed469334c268Romain Guy abstract boolean safelyRun(Runnable action); 2531ac4765e959c79101f64b1279887ed469334c268Romain Guy 2541ac4765e959c79101f64b1279887ed469334c268Romain Guy /** 2557e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy * Setup the hardware renderer for drawing. This is called whenever the 2567e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy * size of the target surface changes or when the surface is first created. 2572d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2582d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width Width of the drawing surface. 2592d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height Height of the drawing surface. 2602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 261fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy abstract void setup(int width, int height); 2622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 263069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 26440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * Gets the current width of the surface. This is the width that the surface 26540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * was last set to in a call to {@link #setup(int, int)}. 26640e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * 26740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * @return the current width of the surface 26840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase */ 26940e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase abstract int getWidth(); 27040e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase 27140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase /** 27240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * Gets the current height of the surface. This is the height that the surface 27340e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * was last set to in a call to {@link #setup(int, int)}. 27440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * 27540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase * @return the current width of the surface 27640e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase */ 27740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase abstract int getHeight(); 27840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase 27940e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase /** 28008837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase * Gets the current canvas associated with this HardwareRenderer. 28108837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase * 28208837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase * @return the current HardwareCanvas 28308837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase */ 28408837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase abstract HardwareCanvas getCanvas(); 28508837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase 28608837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase /** 287a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * Outputs extra debugging information in the specified file descriptor. 288a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy * @param pw 289a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy */ 290a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy abstract void dumpGfxInfo(PrintWriter pw); 291a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka 292a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka /** 293a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka * Outputs the total number of frames rendered (used for fps calculations) 294a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka * 295a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka * @return the number of frames rendered 296a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka */ 297a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka abstract long getFrameCount(); 298a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka 299a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy /** 300a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * Sets the directory to use as a persistent storage for hardware rendering 301a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * resources. 302a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * 303a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * @param cacheDir A directory the current process can write to 304a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy */ 305a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy public static void setupDiskCache(File cacheDir) { 306a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy nSetupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath()); 307a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy } 308a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy 309a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy private static native void nSetupShadersDiskCache(String cacheFile); 310a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy 311a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy /** 312b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis * Notifies EGL that the frame is about to be rendered. 3137687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy * @param size 314b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis */ 3157687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy private static void beginFrame(int[] size) { 3167687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy nBeginFrame(size); 317b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis } 318b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis 3197687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy private static native void nBeginFrame(int[] size); 320b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis 321b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis /** 322244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * Preserves the back buffer of the current surface after a buffer swap. 323244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current 324244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL 325244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. 326244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * 327244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * @return True if the swap behavior was successfully changed, 328244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * false otherwise. 329244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy */ 330244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy static boolean preserveBackBuffer() { 331244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy return nPreserveBackBuffer(); 332244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy } 333244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 334244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy private static native boolean nPreserveBackBuffer(); 335244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 336244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy /** 337244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * Indicates whether the current surface preserves its back buffer 338244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * after a buffer swap. 339244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * 340244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, 341244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * false otherwise 342244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy */ 343244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy static boolean isBackBufferPreserved() { 344244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy return nIsBackBufferPreserved(); 345244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy } 346244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 347244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy private static native boolean nIsBackBufferPreserved(); 348244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 349244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy /** 350244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * Disables v-sync. For performance testing only. 351244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy */ 352244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy static void disableVsync() { 353244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy nDisableVsync(); 354244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy } 355244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 356244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy private static native void nDisableVsync(); 357244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 358244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy /** 359069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Interface used to receive callbacks whenever a view is drawn by 360069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * a hardware renderer instance. 361069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 3620f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn interface HardwareDrawCallbacks { 363069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 364069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Invoked before a view is drawn by a hardware renderer. 365069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 366069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * @param canvas The Canvas used to render the view. 367069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 3687d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy void onHardwarePreDraw(HardwareCanvas canvas); 369069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy 370069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 371069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Invoked after a view is drawn by a hardware renderer. 372069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 373069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * @param canvas The Canvas used to render the view. 374069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 3757d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy void onHardwarePostDraw(HardwareCanvas canvas); 3760f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn } 3770f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn 3782d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 3792d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Draws the specified view. 3807d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * 3812d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param view The view to draw. 3822d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param attachInfo AttachInfo tied to the specified view. 3837d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param callbacks Callbacks invoked when drawing happens. 3847d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param dirty The dirty rectangle to update, can be null. 38550d133e290468fd149b5c03e46549afca2ee05f8Romain Guy * 38650d133e290468fd149b5c03e46549afca2ee05f8Romain Guy * @return true if the dirty rect was ignored, false otherwise 3872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 38850d133e290468fd149b5c03e46549afca2ee05f8Romain Guy abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 3897d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty); 3902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 3912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 39253ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * Creates a new display list that can be used to record batches of 39353ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * drawing operations. 394b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy * 39513631f3da855f200a151e7837ed9f6b079622b58Romain Guy * @param name The name of the display list, used for debugging purpose. 39613631f3da855f200a151e7837ed9f6b079622b58Romain Guy * May be null 39713631f3da855f200a151e7837ed9f6b079622b58Romain Guy * 39853ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * @return A new display list. 399b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy */ 40013631f3da855f200a151e7837ed9f6b079622b58Romain Guy public abstract DisplayList createDisplayList(String name); 401b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy 402b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy /** 403aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Creates a new hardware layer. A hardware layer built by calling this 404aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * method will be treated as a texture layer, instead of as a render target. 405aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 406a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy * @param isOpaque Whether the layer should be opaque or not 407a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy * 408aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @return A hardware layer 4092af3524beb75150d347accc925022daa53b4a789Jamie Gennis */ 410a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy abstract HardwareLayer createHardwareLayer(boolean isOpaque); 4112af3524beb75150d347accc925022daa53b4a789Jamie Gennis 412aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 4136c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * Creates a new hardware layer. 4146c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 4156c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param width The minimum width of the layer 4166c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param height The minimum height of the layer 4176c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param isOpaque Whether the layer should be opaque or not 4186c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 4196c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @return A hardware layer 4206c319ca1275c8db892c39b48fc54864c949f9171Romain Guy */ 4216c319ca1275c8db892c39b48fc54864c949f9171Romain Guy abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque); 422aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 423aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 424aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Creates a new {@link SurfaceTexture} that can be used to render into the 425aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * specified hardware layer. 426aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 427aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 428aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} 429aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 430aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @return A {@link SurfaceTexture} 431aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy */ 432e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer); 433aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 434aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 4352af3524beb75150d347accc925022daa53b4a789Jamie Gennis * Sets the {@link android.graphics.SurfaceTexture} that will be used to 4362af3524beb75150d347accc925022daa53b4a789Jamie Gennis * render into the specified hardware layer. 4372af3524beb75150d347accc925022daa53b4a789Jamie Gennis * 4382af3524beb75150d347accc925022daa53b4a789Jamie Gennis * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} 4392af3524beb75150d347accc925022daa53b4a789Jamie Gennis * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer 4402af3524beb75150d347accc925022daa53b4a789Jamie Gennis */ 4412af3524beb75150d347accc925022daa53b4a789Jamie Gennis abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture); 4422af3524beb75150d347accc925022daa53b4a789Jamie Gennis 4432af3524beb75150d347accc925022daa53b4a789Jamie Gennis /** 444ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * Detaches the specified functor from the current functor execution queue. 445ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * 446ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @param functor The native functor to remove from the execution queue. 447ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * 448ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @see HardwareCanvas#callDrawGLFunction(int) 449ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @see #attachFunctor(android.view.View.AttachInfo, int) 450ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy */ 451ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy abstract void detachFunctor(int functor); 452ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 453ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy /** 454ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * Schedules the specified functor in the functors execution queue. 455ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * 456ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @param attachInfo AttachInfo tied to this renderer. 457ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @param functor The native functor to insert in the execution queue. 458ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * 459ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy * @see HardwareCanvas#callDrawGLFunction(int) 46041ee465734d0006797a8fd36e88976c1e85d161cChris Craik * @see #detachFunctor(int) 46141ee465734d0006797a8fd36e88976c1e85d161cChris Craik * 46241ee465734d0006797a8fd36e88976c1e85d161cChris Craik * @return true if the functor was attached successfully 463ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy */ 46441ee465734d0006797a8fd36e88976c1e85d161cChris Craik abstract boolean attachFunctor(View.AttachInfo attachInfo, int functor); 465ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 466ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy /** 4672d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface and setup the 468c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * renderer for drawing, if needed. This is invoked when the ViewAncestor has 4692d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * potentially lost the hardware renderer. The hardware renderer should be 4702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * reinitialized and setup when the render {@link #isRequested()} and 4712d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * {@link #isEnabled()}. 47244d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy * 4732d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width The width of the drawing surface. 4742d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height The height of the drawing surface. 47544d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy * @param holder The target surface 4762d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 47744d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy void initializeIfNeeded(int width, int height, SurfaceHolder holder) 47844d79747b5e434e8f43928b5548442c65e40e5c3Romain Guy throws Surface.OutOfResourcesException { 4792d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (isRequested()) { 4802d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy // We lost the gl context, so recreate it. 4812d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (!isEnabled()) { 4822d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (initialize(holder)) { 483fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setup(width, height); 4842d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4852d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4862d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 4892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 4902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Creates a hardware renderer using OpenGL. 4912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 4922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.) 493e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * @param translucent True if the surface is translucent, false otherwise 4942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 4952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return A hardware renderer backed by OpenGL. 4962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 497e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) { 4982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy switch (glVersion) { 499e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy case 2: 500163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return Gl20Renderer.create(translucent); 5012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy throw new IllegalArgumentException("Unknown GL version: " + glVersion); 5032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 506bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * Invoke this method when the system is running out of memory. This 507bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * method will attempt to recover as much memory as possible, based on 508bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * the specified hint. 509bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * 510bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * @param level Hint about the amount of memory that should be trimmed, 511bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * see {@link android.content.ComponentCallbacks} 512bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy */ 513bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy static void trimMemory(int level) { 51419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy startTrimMemory(level); 51519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy endTrimMemory(); 51619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy } 51719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy 51819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy /** 51919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * Starts the process of trimming memory. Usually this call will setup 52019f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * hardware rendering context and reclaim memory.Extra cleanup might 52119f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * be required by calling {@link #endTrimMemory()}. 52219f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * 52319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * @param level Hint about the amount of memory that should be trimmed, 52419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * see {@link android.content.ComponentCallbacks} 52519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy */ 52619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy static void startTrimMemory(int level) { 52719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy Gl20Renderer.startTrimMemory(level); 52819f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy } 52919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy 53019f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy /** 53119f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * Finishes the process of trimming memory. This method will usually 53219f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy * cleanup special resources used by the memory trimming process. 53319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy */ 53419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy static void endTrimMemory() { 53519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy Gl20Renderer.endTrimMemory(); 536bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 537bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy 538bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy /** 5392d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 5402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 5412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if hardware acceleration is in use, false otherwise. 5422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 5432d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isEnabled() { 5442d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mEnabled; 5452d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5462d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5472d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 5482d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 5492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 5502d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param enabled True if the hardware renderer is in use, false otherwise. 5512d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 5522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setEnabled(boolean enabled) { 5532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mEnabled = enabled; 5542d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5552d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 5572d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently request but not 5582d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 5592d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 5602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if requested, false otherwise. 5612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 5622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isRequested() { 5632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mRequested; 5642d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5652d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5662d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 5679745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy * Indicates whether hardware acceleration is currently requested but not 5682d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 5692d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 5702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True to request hardware acceleration, false otherwise. 5712d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 5722d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setRequested(boolean requested) { 5732d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mRequested = requested; 5742d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5752d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5762d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @SuppressWarnings({"deprecation"}) 577e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static abstract class GlRenderer extends HardwareRenderer { 578aaceeb0c5be11121a81e44b9633c06fc5c0fcd4dRomain Guy // These values are not exposed in our EGL APIs 579e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 580e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy static final int EGL_OPENGL_ES2_BIT = 4; 5817e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final int EGL_SURFACE_TYPE = 0x3033; 5827e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400; 583e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 58416260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy static final int SURFACE_STATE_ERROR = 0; 58516260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy static final int SURFACE_STATE_SUCCESS = 1; 58616260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy static final int SURFACE_STATE_UPDATED = 2; 5878f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 58865924a3e56c2e7ac863f8e25e9f9a58b9db7d513Chris Craik static final int FUNCTOR_PROCESS_DELAY = 4; 5898f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 590fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGL10 sEgl; 591fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLDisplay sEglDisplay; 592fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLConfig sEglConfig; 593566b3efb25299d2a9c8ae827522802bad965426aRomain Guy static final Object[] sEglLock = new Object[0]; 59440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase int mWidth = -1, mHeight = -1; 595e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 5965d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy static final ThreadLocal<ManagedEGLContext> sEglContextStorage 5975d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy = new ThreadLocal<ManagedEGLContext>(); 598566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 599566b3efb25299d2a9c8ae827522802bad965426aRomain Guy EGLContext mEglContext; 600566b3efb25299d2a9c8ae827522802bad965426aRomain Guy Thread mEglThread; 601fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 602fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy EGLSurface mEglSurface; 603fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 604e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy GL mGl; 60567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy HardwareCanvas mCanvas; 606a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 607a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka long mFrameCount; 6087d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Paint mDebugPaint; 6097d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 6107e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static boolean sDirtyRegions; 6117e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final boolean sDirtyRegionsRequested; 6127e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static { 6137e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true"); 6147e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy //noinspection PointlessBooleanExpression,ConstantConditions 6157e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); 6167e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy sDirtyRegionsRequested = sDirtyRegions; 6177e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } 6187e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 6197e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy boolean mDirtyRegionsEnabled; 6209477c6e6581ce97976250951f33e1297604ac777Romain Guy boolean mUpdateDirtyRegions; 6219477c6e6581ce97976250951f33e1297604ac777Romain Guy 6229ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy final boolean mVsyncDisabled; 6232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 624a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy final boolean mProfileEnabled; 625a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy final float[] mProfileData; 626a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT; 627b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy 628b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy final boolean mDebugDirtyRegions; 629a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 630e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final int mGlVersion; 631e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final boolean mTranslucent; 6322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 633fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy private boolean mDestroyed; 634566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 635cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy private final Rect mRedrawClip = new Rect(); 6368f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 6377687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy private final int[] mSurfaceSize = new int[2]; 6388f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy private final FunctorsRunnable mFunctorsRunnable = new FunctorsRunnable(); 639fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 640e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy GlRenderer(int glVersion, boolean translucent) { 641e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGlVersion = glVersion; 642e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy mTranslucent = translucent; 643b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy 644b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy String property; 6459ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 646b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy property = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false"); 647b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy mVsyncDisabled = "true".equalsIgnoreCase(property); 6489ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (mVsyncDisabled) { 6499ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy Log.d(LOG_TAG, "Disabling v-sync"); 6509ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 651a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 65213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy property = SystemProperties.get(PROFILE_PROPERTY, "false"); 65313b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy mProfileEnabled = "true".equalsIgnoreCase(property); 65413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy if (mProfileEnabled) { 65513b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy Log.d(LOG_TAG, "Profiling hardware renderer"); 656a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 657a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 658a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 65909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase property = SystemProperties.get(PROFILE_MAXFRAMES_PROPERTY, 66009280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase Integer.toString(PROFILE_MAX_FRAMES)); 66109280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase int maxProfileFrames = Integer.valueOf(property); 66209280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT]; 66309280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) { 66409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1; 66509280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase } 666a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } else { 667a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileData = null; 668a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 669b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy 670b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy property = SystemProperties.get(DEBUG_DIRTY_REGIONS_PROPERTY, "false"); 671b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy mDebugDirtyRegions = "true".equalsIgnoreCase(property); 672b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy if (mDebugDirtyRegions) { 673b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy Log.d(LOG_TAG, "Debugging dirty regions"); 674b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy } 675a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 676a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 677a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy @Override 678a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy void dumpGfxInfo(PrintWriter pw) { 679a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 680a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy pw.printf("\n\tDraw\tProcess\tExecute\n"); 681a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) { 68209280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase if (mProfileData[i] < 0) { 68309280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase break; 68409280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase } 685a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1], 686a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileData[i + 2]); 68709280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1; 688a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 68909280606dc5dc1b8f12f9317cf6922772b7d10a7Chet Haase mProfileCurrentFrame = mProfileData.length; 690a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 6912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 6922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 693a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka @Override 694a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka long getFrameCount() { 695a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka return mFrameCount; 696a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka } 697a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka 698e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 69902ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy * Indicates whether this renderer instance can track and update dirty regions. 70002ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy */ 70102ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy boolean hasDirtyRegions() { 7027e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy return mDirtyRegionsEnabled; 70302ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy } 70402ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy 70502ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy /** 7064caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)} 707e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * is invoked and the requested flag is turned off. The error code is 708e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * also logged as a warning. 709e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 710b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void checkEglErrors() { 711e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isEnabled()) { 712fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int error = sEgl.eglGetError(); 713484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (error != EGL_SUCCESS) { 714e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // something bad has happened revert to 715e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // normal rendering. 716407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error)); 717eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy fallback(error != EGL11.EGL_CONTEXT_LOST); 718e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 7192d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 7202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 72167f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 7229745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy private void fallback(boolean fallback) { 7239745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy destroy(true); 7249745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy if (fallback) { 7259745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy // we'll try again if it was context lost 7269745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy setRequested(false); 7279745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.w(LOG_TAG, "Mountain View, we've had a problem here. " 7289745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy + "Switching back to software rendering."); 7299745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 7309745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 7319745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy 732e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 733648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException { 734e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isRequested() && !isEnabled()) { 735e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy initializeEgl(); 736e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = createEglSurface(holder); 737fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mDestroyed = false; 7382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 739e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mGl != null) { 740fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int err = sEgl.eglGetError(); 741484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (err != EGL_SUCCESS) { 7424caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy destroy(true); 743e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setRequested(false); 744e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 7454caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (mCanvas == null) { 7464caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = createCanvas(); 747fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 748e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mCanvas != null) { 749e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setEnabled(true); 750e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 751e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy Log.w(LOG_TAG, "Hardware accelerated Canvas could not be created"); 752e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 753e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 754e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 755e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mCanvas != null; 756e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 757e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 758e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return false; 759e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 7602a83f001fdb189f945e82e81e717ba204824b112Romain Guy 7612a83f001fdb189f945e82e81e717ba204824b112Romain Guy @Override 762648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException { 7632a83f001fdb189f945e82e81e717ba204824b112Romain Guy if (isRequested() && isEnabled()) { 7642a83f001fdb189f945e82e81e717ba204824b112Romain Guy createEglSurface(holder); 7652a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 7662a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 767e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 7685d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy abstract HardwareCanvas createCanvas(); 7692d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 77029d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy abstract int[] getConfig(boolean dirtyRegions); 77129d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy 772e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy void initializeEgl() { 773566b3efb25299d2a9c8ae827522802bad965426aRomain Guy synchronized (sEglLock) { 774566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sEgl == null && sEglConfig == null) { 775566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sEgl = (EGL10) EGLContext.getEGL(); 776566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 777566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // Get to the default display. 778484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 779566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 780484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (sEglDisplay == EGL_NO_DISPLAY) { 781566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglGetDisplay failed " 782407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy + GLUtils.getEGLErrorString(sEgl.eglGetError())); 783566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 784566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 785566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // We can now initialize EGL for that display 786566b3efb25299d2a9c8ae827522802bad965426aRomain Guy int[] version = new int[2]; 787566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglInitialize(sEglDisplay, version)) { 788566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglInitialize failed " + 789407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy GLUtils.getEGLErrorString(sEgl.eglGetError())); 790566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 791566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 792e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy sEglConfig = chooseEglConfig(); 793069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy if (sEglConfig == null) { 794566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without 795566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sDirtyRegions) { 796566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sDirtyRegions = false; 797566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sEglConfig = chooseEglConfig(); 798566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sEglConfig == null) { 799566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglConfig not initialized"); 800566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 801566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } else { 802566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglConfig not initialized"); 803566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 804069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 805069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 806069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 807566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 8085d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy ManagedEGLContext managedContext = sEglContextStorage.get(); 809717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn mEglContext = managedContext != null ? managedContext.getContext() : null; 810566b3efb25299d2a9c8ae827522802bad965426aRomain Guy mEglThread = Thread.currentThread(); 811566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 812566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (mEglContext == null) { 813566b3efb25299d2a9c8ae827522802bad965426aRomain Guy mEglContext = createContext(sEgl, sEglDisplay, sEglConfig); 8145d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy sEglContextStorage.set(createManagedContext(mEglContext)); 815566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 816e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 817e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 8185d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy abstract ManagedEGLContext createManagedContext(EGLContext eglContext); 8195d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy 820e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy private EGLConfig chooseEglConfig() { 821e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy EGLConfig[] configs = new EGLConfig[1]; 822484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy int[] configsCount = new int[1]; 8237e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy int[] configSpec = getConfig(sDirtyRegions); 824484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 825484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy // Debug 82629d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, ""); 827484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if ("all".equalsIgnoreCase(debug)) { 828484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount); 829484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 830484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]]; 831484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs, 832484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy configsCount[0], configsCount); 833484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 834484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy for (EGLConfig config : debugConfigs) { 835484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy printConfig(config); 836484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 837484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 838484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 839e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) { 840e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy throw new IllegalArgumentException("eglChooseConfig failed " + 841407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy GLUtils.getEGLErrorString(sEgl.eglGetError())); 842e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } else if (configsCount[0] > 0) { 843484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if ("choice".equalsIgnoreCase(debug)) { 844484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy printConfig(configs[0]); 845484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 846e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return configs[0]; 847e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 848484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 849e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return null; 850e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 851e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 852e979e62ac7313b7cffe9b131bb8a99c356068b45Romain Guy private static void printConfig(EGLConfig config) { 853484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy int[] value = new int[1]; 854484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 855484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, "EGL configuration " + config + ":"); 856484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 857484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value); 858484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " RED_SIZE = " + value[0]); 859484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 860484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value); 861484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " GREEN_SIZE = " + value[0]); 862484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 863484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value); 864484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " BLUE_SIZE = " + value[0]); 865484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 866484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value); 867484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " ALPHA_SIZE = " + value[0]); 868484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 869484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value); 870484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " DEPTH_SIZE = " + value[0]); 871484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 872484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value); 873484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]); 874484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 875484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value); 87629d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0])); 877484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 878484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 879648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException { 880e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Check preconditions. 881fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEgl == null) { 882e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("egl not initialized"); 883e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 884fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglDisplay == null) { 885e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("eglDisplay not initialized"); 886e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 887fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglConfig == null) { 888069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy throw new RuntimeException("eglConfig not initialized"); 889e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 890566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (Thread.currentThread() != mEglThread) { 891fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy throw new IllegalStateException("HardwareRenderer cannot be used " 892fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy + "from multiple threads"); 893fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 894e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 8956d7475d666baefaa3ba9f0dcee25238739454241Romain Guy // In case we need to destroy an existing surface 8966d7475d666baefaa3ba9f0dcee25238739454241Romain Guy destroySurface(); 897e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 898e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Create an EGL surface we can render into. 8991d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy if (!createSurface(holder)) { 9001d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy return null; 901e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 902e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 9032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 9042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Before we can issue GL commands, we need to make sure 9052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * the context is current and bound to a surface. 9062d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 907566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 908648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn throw new Surface.OutOfResourcesException("eglMakeCurrent failed " 909407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy + GLUtils.getEGLErrorString(sEgl.eglGetError())); 910e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 9118ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy 9128ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy initCaches(); 9136f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy 9149477c6e6581ce97976250951f33e1297604ac777Romain Guy enableDirtyRegions(); 9159477c6e6581ce97976250951f33e1297604ac777Romain Guy 9169477c6e6581ce97976250951f33e1297604ac777Romain Guy return mEglContext.getGL(); 9179477c6e6581ce97976250951f33e1297604ac777Romain Guy } 9189477c6e6581ce97976250951f33e1297604ac777Romain Guy 9199477c6e6581ce97976250951f33e1297604ac777Romain Guy private void enableDirtyRegions() { 9206f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // If mDirtyRegions is set, this means we have an EGL configuration 9216f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set 9227e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy if (sDirtyRegions) { 923244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy if (!(mDirtyRegionsEnabled = preserveBackBuffer())) { 9247d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Log.w(LOG_TAG, "Backbuffer cannot be preserved"); 9257d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 9267e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } else if (sDirtyRegionsRequested) { 9276f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // If mDirtyRegions is not set, our EGL configuration does not 9286f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default 9296f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // swap behavior might be EGL_BUFFER_PRESERVED, which means we 9306f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // want to set mDirtyRegions. We try to do this only if dirty 9316f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // regions were initially requested as part of the device 9326f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // configuration (see RENDER_DIRTY_REGIONS) 933244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy mDirtyRegionsEnabled = isBackBufferPreserved(); 9347d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 9352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 9362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 9378ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy abstract void initCaches(); 9388ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy 939e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 940912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE }; 941e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 942484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, 943912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy mGlVersion != 0 ? attribs : null); 944e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 945e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 946e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 9474caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy void destroy(boolean full) { 9484caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (full && mCanvas != null) { 9494caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = null; 9504caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy } 951fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 952357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy if (!isEnabled() || mDestroyed) { 953357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy setEnabled(false); 954357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy return; 955357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy } 956e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 9576d7475d666baefaa3ba9f0dcee25238739454241Romain Guy destroySurface(); 958357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy setEnabled(false); 9592d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 960357c942462e4eb1d0b2e91b3fe8ec9ac7524bbedRomain Guy mDestroyed = true; 961e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = null; 962fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 963fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 9646d7475d666baefaa3ba9f0dcee25238739454241Romain Guy void destroySurface() { 9656d7475d666baefaa3ba9f0dcee25238739454241Romain Guy if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) { 9666d7475d666baefaa3ba9f0dcee25238739454241Romain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 9676d7475d666baefaa3ba9f0dcee25238739454241Romain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 9686d7475d666baefaa3ba9f0dcee25238739454241Romain Guy mEglSurface = null; 9696d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 9706d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 9716d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 9722d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 973cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy void invalidate(SurfaceHolder holder) { 9747e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy // Cancels any existing buffer to ensure we'll get a buffer 9757e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy // of the right size before we call eglSwapBuffers 976cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 9771d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy 978d3facf341bf106588aade72c0164532cd4bf941fRomain Guy if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) { 979d3facf341bf106588aade72c0164532cd4bf941fRomain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 9801d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy mEglSurface = null; 9811d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy setEnabled(false); 982d3facf341bf106588aade72c0164532cd4bf941fRomain Guy } 983cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy 984d3facf341bf106588aade72c0164532cd4bf941fRomain Guy if (holder.getSurface().isValid()) { 9851d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy if (!createSurface(holder)) { 9861d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy return; 987cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy } 9889477c6e6581ce97976250951f33e1297604ac777Romain Guy 9899477c6e6581ce97976250951f33e1297604ac777Romain Guy mUpdateDirtyRegions = true; 9909477c6e6581ce97976250951f33e1297604ac777Romain Guy 99186e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy if (mCanvas != null) { 99286e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy setEnabled(true); 99386e3e22ba81fb75a5c7e5e007ca1c0cacfda3afbRomain Guy } 9941d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy } 9951d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy } 9961d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy 9971d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy private boolean createSurface(SurfaceHolder holder) { 9981d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); 9991d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy 10001d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { 10011d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy int error = sEgl.eglGetError(); 10021d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy if (error == EGL_BAD_NATIVE_WINDOW) { 10031d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 10041d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy return false; 10051d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy } 10061d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy throw new RuntimeException("createWindowSurface failed " 1007407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy + GLUtils.getEGLErrorString(error)); 1008cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy } 10091d0c708961f824ac5171238c205a7bf328d5d8a5Romain Guy return true; 1010039857520b1a03a52051b966d87d587225bdfcc3Romain Guy } 1011cf15efba0792b052dca5baa350d9fb00e6a60667Romain Guy 1012039857520b1a03a52051b966d87d587225bdfcc3Romain Guy @Override 1013039857520b1a03a52051b966d87d587225bdfcc3Romain Guy boolean validate() { 1014039857520b1a03a52051b966d87d587225bdfcc3Romain Guy return checkCurrent() != SURFACE_STATE_ERROR; 10157e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } 10167e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 10177e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy @Override 1018fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy void setup(int width, int height) { 1019eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy if (validate()) { 1020eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy mCanvas.setViewport(width, height); 102140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase mWidth = width; 102240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase mHeight = height; 1023eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy } 1024e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 10257d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 102640e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase @Override 102740e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase int getWidth() { 102840e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase return mWidth; 102940e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase } 103040e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase 103140e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase @Override 103240e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase int getHeight() { 103340e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase return mHeight; 103440e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase } 103540e0383dce630ed9b2b1aa0e497709b89dfab6efChet Haase 103608837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase @Override 103708837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase HardwareCanvas getCanvas() { 103808837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase return mCanvas; 103908837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase } 104008837c246c9c27902c59b41c8661c2f27a4aa2bcChet Haase 1041e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy boolean canDraw() { 1042e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mGl != null && mCanvas != null; 1043e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 1044e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 104544b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase int onPreDraw(Rect dirty) { 104644b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase return DisplayList.STATUS_DONE; 1047e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 1048e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 1049b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 1050b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 10512d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 10528f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy class FunctorsRunnable implements Runnable { 10538f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy View.AttachInfo attachInfo; 10548f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 10558f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy @Override 10568f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy public void run() { 10578f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy final HardwareRenderer renderer = attachInfo.mHardwareRenderer; 10588f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if (renderer == null || !renderer.isEnabled() || renderer != GlRenderer.this) { 10598f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy return; 10608f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 10618f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 10628f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy final int surfaceState = checkCurrent(); 10638f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if (surfaceState != SURFACE_STATE_ERROR) { 10648f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy int status = mCanvas.invokeFunctors(mRedrawClip); 10658f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy handleFunctorStatus(attachInfo, status); 10668f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 10678f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 10688f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 10698f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 10702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 107150d133e290468fd149b5c03e46549afca2ee05f8Romain Guy boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 10727d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty) { 1073e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (canDraw()) { 107402ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy if (!hasDirtyRegions()) { 10757d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy dirty = null; 10767d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 10772d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy attachInfo.mIgnoreDirtyState = true; 107802ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy attachInfo.mDrawingTime = SystemClock.uptimeMillis(); 107902ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy 10802d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy view.mPrivateFlags |= View.DRAWN; 1081039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 1082d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy final int surfaceState = checkCurrent(); 1083d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState != SURFACE_STATE_ERROR) { 10847687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy HardwareCanvas canvas = mCanvas; 10857687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy attachInfo.mHardwareCanvas = canvas; 10867687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy 1087d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy // We had to change the current surface and/or context, redraw everything 1088d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState == SURFACE_STATE_UPDATED) { 1089d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy dirty = null; 10907687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy beginFrame(null); 10917687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy } else { 10927687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy int[] size = mSurfaceSize; 10937687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy beginFrame(size); 10947687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy 10957687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy if (size[1] != mHeight || size[0] != mWidth) { 10967687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy mWidth = size[0]; 10977687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy mHeight = size[1]; 10987687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy 10997687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy canvas.setViewport(mWidth, mHeight); 11007687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy 11017687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy dirty = null; 11027687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy } 1103d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } 1104d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 110544b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase int status = onPreDraw(dirty); 1106b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy int saveCount = canvas.save(); 1107b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy callbacks.onHardwarePreDraw(canvas); 1108daf98e941e140e8739458126640183b9f296a2abChet Haase 1109b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 1110daf98e941e140e8739458126640183b9f296a2abChet Haase view.mRecreateDisplayList = 1111daf98e941e140e8739458126640183b9f296a2abChet Haase (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED; 1112daf98e941e140e8739458126640183b9f296a2abChet Haase view.mPrivateFlags &= ~View.INVALIDATED; 11137d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 1114a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy long getDisplayListStartTime = 0; 1115a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 1116a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT; 1117a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileCurrentFrame >= mProfileData.length) { 1118a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileCurrentFrame = 0; 1119a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy } 1120a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy 112195db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown getDisplayListStartTime = System.nanoTime(); 112295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown } 112395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 1124daf98e941e140e8739458126640183b9f296a2abChet Haase DisplayList displayList = view.getDisplayList(); 112595db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 1126a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 112795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown long now = System.nanoTime(); 1128a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy float total = (now - getDisplayListStartTime) * 0.000001f; 1129a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy //noinspection PointlessArithmeticExpression 1130a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileData[mProfileCurrentFrame] = total; 113195db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown } 113295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 1133daf98e941e140e8739458126640183b9f296a2abChet Haase if (displayList != null) { 1134a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy long drawDisplayListStartTime = 0; 1135a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 113695db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown drawDisplayListStartTime = System.nanoTime(); 113795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown } 113895db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 113944b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase status |= canvas.drawDisplayList(displayList, mRedrawClip, 114033f6beb10f98e8ba96250e284876d607055d278dRomain Guy DisplayList.FLAG_CLIP_CHILDREN); 114195db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 1142a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy if (mProfileEnabled) { 114395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown long now = System.nanoTime(); 1144a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy float total = (now - drawDisplayListStartTime) * 0.000001f; 1145a676ad7e34c9afbaafaeca8c3fe96e95c518828eRomain Guy mProfileData[mProfileCurrentFrame + 1] = total; 114695db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown } 114795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 11488f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy handleFunctorStatus(attachInfo, status); 1149daf98e941e140e8739458126640183b9f296a2abChet Haase } else { 1150daf98e941e140e8739458126640183b9f296a2abChet Haase // Shouldn't reach here 1151daf98e941e140e8739458126640183b9f296a2abChet Haase view.draw(canvas); 1152daf98e941e140e8739458126640183b9f296a2abChet Haase } 1153b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy } finally { 1154b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy callbacks.onHardwarePostDraw(canvas); 1155b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy canvas.restoreToCount(saveCount); 1156b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy view.mRecreateDisplayList = false; 115719f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy 1158a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka mFrameCount++; 115919f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy 1160b04f7e9438e8f73081f9be3fda166098042263a5Romain Guy if (mDebugDirtyRegions) { 11617d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (mDebugPaint == null) { 11627d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint = new Paint(); 11637d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint.setColor(0x7fff0000); 11647d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 116519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy 1166a3fabff98590d26f0c362cb09dc378fece66215cMichael Jurka if (dirty != null && (mFrameCount & 1) == 0) { 11677d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy canvas.drawRect(dirty, mDebugPaint); 11687d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 11697d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 1170b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 1171daf98e941e140e8739458126640183b9f296a2abChet Haase 1172b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy onPostDraw(); 1173daf98e941e140e8739458126640183b9f296a2abChet Haase 1174b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy attachInfo.mIgnoreDirtyState = false; 1175486590963e2207d68eebd6944fec70d50d41116aChet Haase 1176486590963e2207d68eebd6944fec70d50d41116aChet Haase if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) { 11774e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown 1178486590963e2207d68eebd6944fec70d50d41116aChet Haase long eglSwapBuffersStartTime = 0; 1179486590963e2207d68eebd6944fec70d50d41116aChet Haase if (mProfileEnabled) { 1180486590963e2207d68eebd6944fec70d50d41116aChet Haase eglSwapBuffersStartTime = System.nanoTime(); 1181486590963e2207d68eebd6944fec70d50d41116aChet Haase } 1182486590963e2207d68eebd6944fec70d50d41116aChet Haase 1183486590963e2207d68eebd6944fec70d50d41116aChet Haase sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); 1184486590963e2207d68eebd6944fec70d50d41116aChet Haase 1185486590963e2207d68eebd6944fec70d50d41116aChet Haase if (mProfileEnabled) { 1186486590963e2207d68eebd6944fec70d50d41116aChet Haase long now = System.nanoTime(); 1187486590963e2207d68eebd6944fec70d50d41116aChet Haase float total = (now - eglSwapBuffersStartTime) * 0.000001f; 1188486590963e2207d68eebd6944fec70d50d41116aChet Haase mProfileData[mProfileCurrentFrame + 2] = total; 1189486590963e2207d68eebd6944fec70d50d41116aChet Haase } 1190486590963e2207d68eebd6944fec70d50d41116aChet Haase 1191486590963e2207d68eebd6944fec70d50d41116aChet Haase checkEglErrors(); 119295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown } 119395db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 119450d133e290468fd149b5c03e46549afca2ee05f8Romain Guy return dirty == null; 11959a40babc62416259d18783ce8c03c00042ec317bRomain Guy } 11962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 119750d133e290468fd149b5c03e46549afca2ee05f8Romain Guy 119850d133e290468fd149b5c03e46549afca2ee05f8Romain Guy return false; 11992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1200039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 12018f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { 12028f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy // If the draw flag is set, functors will be invoked while executing 12038f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy // the tree of display lists 12048f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if ((status & DisplayList.STATUS_DRAW) != 0) { 12058f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if (mRedrawClip.isEmpty()) { 12068f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy attachInfo.mViewRootImpl.invalidate(); 12078f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } else { 12088f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip); 12098f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy mRedrawClip.setEmpty(); 12108f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 12118f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 12128f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 12138f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy if ((status & DisplayList.STATUS_INVOKE) != 0) { 1214ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy scheduleFunctors(attachInfo); 1215ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy } 1216ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy } 1217ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 1218ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy private void scheduleFunctors(View.AttachInfo attachInfo) { 1219ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mFunctorsRunnable.attachInfo = attachInfo; 1220ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) { 12218f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy // delay the functor callback by a few ms so it isn't polled constantly 12228f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY); 12238f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 12248f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy } 12258f3b8e32993d190a26c70c839a63d8ce4c3b16d9Romain Guy 1226ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy @Override 1227ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy void detachFunctor(int functor) { 1228ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy if (mCanvas != null) { 1229ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mCanvas.detachFunctor(functor); 1230932b7f6765968bd526c03512f3805fbc3924dc29Chris Craik } 1231ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy } 1232ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 1233ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy @Override 123441ee465734d0006797a8fd36e88976c1e85d161cChris Craik boolean attachFunctor(View.AttachInfo attachInfo, int functor) { 1235ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy if (mCanvas != null) { 1236ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy mCanvas.attachFunctor(functor); 1237ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy scheduleFunctors(attachInfo); 123841ee465734d0006797a8fd36e88976c1e85d161cChris Craik return true; 1239ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy } 124041ee465734d0006797a8fd36e88976c1e85d161cChris Craik return false; 1241ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy } 1242ba6be8a62dcdb3ffd210cd36b9af4e3a658eac47Romain Guy 1243039857520b1a03a52051b966d87d587225bdfcc3Romain Guy /** 1244566b3efb25299d2a9c8ae827522802bad965426aRomain Guy * Ensures the current EGL context is the one we expect. 1245039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * 1246039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current, 1247039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or 1248039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one 1249039857520b1a03a52051b966d87d587225bdfcc3Romain Guy */ 1250912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy int checkCurrent() { 1251566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (mEglThread != Thread.currentThread()) { 1252039857520b1a03a52051b966d87d587225bdfcc3Romain Guy throw new IllegalStateException("Hardware acceleration can only be used with a " + 1253566b3efb25299d2a9c8ae827522802bad965426aRomain Guy "single UI thread.\nOriginal thread: " + mEglThread + "\n" + 1254039857520b1a03a52051b966d87d587225bdfcc3Romain Guy "Current thread: " + Thread.currentThread()); 1255039857520b1a03a52051b966d87d587225bdfcc3Romain Guy } 1256039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 1257566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!mEglContext.equals(sEgl.eglGetCurrentContext()) || 1258484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) { 1259566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 12609745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.e(LOG_TAG, "eglMakeCurrent failed " + 1261407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy GLUtils.getEGLErrorString(sEgl.eglGetError())); 1262eca9b1f53c2c291cbfb89b5f3cc45db7bdca6c7dRomain Guy fallback(true); 1263d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_ERROR; 1264d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } else { 12659477c6e6581ce97976250951f33e1297604ac777Romain Guy if (mUpdateDirtyRegions) { 12669477c6e6581ce97976250951f33e1297604ac777Romain Guy enableDirtyRegions(); 12679477c6e6581ce97976250951f33e1297604ac777Romain Guy mUpdateDirtyRegions = false; 12689477c6e6581ce97976250951f33e1297604ac777Romain Guy } 1269d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_UPDATED; 1270fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 1271fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 1272d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_SUCCESS; 1273fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 1274e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 1275fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 1276e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 1277e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Hardware renderer using OpenGL ES 2.0. 1278e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 1279e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static class Gl20Renderer extends GlRenderer { 1280e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy private GLES20Canvas mGlCanvas; 1281e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 1282912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy private static EGLSurface sPbuffer; 1283912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy private static final Object[] sPbufferLock = new Object[0]; 1284912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 128531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy static class Gl20RendererEglContext extends ManagedEGLContext { 1286717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn final Handler mHandler = new Handler(); 1287717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 128831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy public Gl20RendererEglContext(EGLContext context) { 1289717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn super(context); 1290717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1291717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1292717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn @Override 1293717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn public void onTerminate(final EGLContext eglContext) { 1294717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn // Make sure we do this on the correct thread. 1295717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (mHandler.getLooper() != Looper.myLooper()) { 1296717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn mHandler.post(new Runnable() { 12975d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy @Override 12985d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy public void run() { 1299717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn onTerminate(eglContext); 1300717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1301717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn }); 1302717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn return; 1303717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1304717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1305717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn synchronized (sEglLock) { 1306717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (sEgl == null) return; 1307717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1308717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (EGLImpl.getInitCount(sEglDisplay) == 1) { 1309717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn usePbufferSurface(eglContext); 1310717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn GLES20Canvas.terminateCaches(); 1311717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1312717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEgl.eglDestroyContext(sEglDisplay, eglContext); 1313a998dff5d49a423aaf7097aa8f96bf5bdc681d25Romain Guy sEglContextStorage.set(null); 1314717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEglContextStorage.remove(); 1315717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1316717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEgl.eglDestroySurface(sEglDisplay, sPbuffer); 131731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, 131831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy EGL_NO_SURFACE, EGL_NO_CONTEXT); 1319717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1320717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEgl.eglReleaseThread(); 1321717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEgl.eglTerminate(sEglDisplay); 1322717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1323717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEgl = null; 1324717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEglDisplay = null; 1325717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sEglConfig = null; 1326717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn sPbuffer = null; 1327717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1328717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1329717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1330717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn } 1331717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn 1332e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy Gl20Renderer(boolean translucent) { 1333e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy super(2, translucent); 1334e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 1335e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 13362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 13375d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy HardwareCanvas createCanvas() { 13386b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy return mGlCanvas = new GLES20Canvas(mTranslucent); 1339e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 1340e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 1341e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy @Override 13425d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy ManagedEGLContext createManagedContext(EGLContext eglContext) { 13435d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy return new Gl20Renderer.Gl20RendererEglContext(mEglContext); 13445d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy } 13455d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy 13465d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy @Override 1347e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy int[] getConfig(boolean dirtyRegions) { 1348e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return new int[] { 1349484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1350484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_RED_SIZE, 8, 1351484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_GREEN_SIZE, 8, 1352484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_BLUE_SIZE, 8, 1353484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_ALPHA_SIZE, 8, 1354484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_DEPTH_SIZE, 0, 1355530041d3191ce817832a0108514617768e43cda6Romain Guy EGL_STENCIL_SIZE, GLES20Canvas.getStencilSize(), 1356484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_SURFACE_TYPE, EGL_WINDOW_BIT | 135708645eb0f4a8d73b2b2f26d3232f45cf459a27bcRomain Guy (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), 1358484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_NONE 1359e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy }; 1360e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 13618ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy 13628ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy @Override 13638ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy void initCaches() { 13648ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy GLES20Canvas.initCaches(); 13658ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy } 1366e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 1367b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy @Override 1368b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy boolean canDraw() { 1369b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy return super.canDraw() && mGlCanvas != null; 1370b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 1371e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 1372e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy @Override 137344b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase int onPreDraw(Rect dirty) { 137444b2fe3fc114ee5f7273c6b0fee2cc999bf244a2Chet Haase return mGlCanvas.onPreDraw(dirty); 1375e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 1376e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 1377b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy @Override 1378b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 1379b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy mGlCanvas.onPostDraw(); 1380b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 1381b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy 1382b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy @Override 138367f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy void destroy(boolean full) { 1384b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 1385b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy super.destroy(full); 1386b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } finally { 1387b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy if (full && mGlCanvas != null) { 1388b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy mGlCanvas = null; 1389b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 139067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 139167f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 139267f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 139367f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy @Override 13949ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy void setup(int width, int height) { 13959ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy super.setup(width, height); 13969ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (mVsyncDisabled) { 1397244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy disableVsync(); 13989ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 13999ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 14009ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 14019ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy @Override 140213631f3da855f200a151e7837ed9f6b079622b58Romain Guy public DisplayList createDisplayList(String name) { 140313631f3da855f200a151e7837ed9f6b079622b58Romain Guy return new GLES20DisplayList(name); 1404b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy } 1405aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 1406aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy @Override 1407a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy HardwareLayer createHardwareLayer(boolean isOpaque) { 1408a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy return new GLES20TextureLayer(isOpaque); 1409aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 1410aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 14116c319ca1275c8db892c39b48fc54864c949f9171Romain Guy @Override 14126c319ca1275c8db892c39b48fc54864c949f9171Romain Guy HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { 1413aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy return new GLES20RenderLayer(width, height, isOpaque); 1414aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 1415aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 1416aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy @Override 1417e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy SurfaceTexture createSurfaceTexture(HardwareLayer layer) { 1418aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy return ((GLES20TextureLayer) layer).getSurfaceTexture(); 1419aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 1420aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 14216d7475d666baefaa3ba9f0dcee25238739454241Romain Guy @Override 14222af3524beb75150d347accc925022daa53b4a789Jamie Gennis void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) { 14232af3524beb75150d347accc925022daa53b4a789Jamie Gennis ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture); 14242af3524beb75150d347accc925022daa53b4a789Jamie Gennis } 14252af3524beb75150d347accc925022daa53b4a789Jamie Gennis 14262af3524beb75150d347accc925022daa53b4a789Jamie Gennis @Override 14276d7475d666baefaa3ba9f0dcee25238739454241Romain Guy void destroyLayers(View view) { 142816260e73f6c1c9dc94acf0d328a3c564426b8711Romain Guy if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) { 14296d7475d666baefaa3ba9f0dcee25238739454241Romain Guy destroyHardwareLayer(view); 14306d7475d666baefaa3ba9f0dcee25238739454241Romain Guy GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); 14316d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 14326d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 14336d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 143431f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy private static void destroyHardwareLayer(View view) { 1435a998dff5d49a423aaf7097aa8f96bf5bdc681d25Romain Guy view.destroyLayer(true); 143631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy 14376d7475d666baefaa3ba9f0dcee25238739454241Romain Guy if (view instanceof ViewGroup) { 14386d7475d666baefaa3ba9f0dcee25238739454241Romain Guy ViewGroup group = (ViewGroup) view; 14396d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 14406d7475d666baefaa3ba9f0dcee25238739454241Romain Guy int count = group.getChildCount(); 14416d7475d666baefaa3ba9f0dcee25238739454241Romain Guy for (int i = 0; i < count; i++) { 14426d7475d666baefaa3ba9f0dcee25238739454241Romain Guy destroyHardwareLayer(group.getChildAt(i)); 14436d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 14446d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 14456d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 1446244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 144731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy @Override 14481ac4765e959c79101f64b1279887ed469334c268Romain Guy boolean safelyRun(Runnable action) { 14491ac4765e959c79101f64b1279887ed469334c268Romain Guy boolean needsContext = true; 14501ac4765e959c79101f64b1279887ed469334c268Romain Guy if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; 14511ac4765e959c79101f64b1279887ed469334c268Romain Guy 14521ac4765e959c79101f64b1279887ed469334c268Romain Guy if (needsContext) { 14531ac4765e959c79101f64b1279887ed469334c268Romain Guy Gl20RendererEglContext managedContext = 14541ac4765e959c79101f64b1279887ed469334c268Romain Guy (Gl20RendererEglContext) sEglContextStorage.get(); 14551ac4765e959c79101f64b1279887ed469334c268Romain Guy if (managedContext == null) return false; 14561ac4765e959c79101f64b1279887ed469334c268Romain Guy usePbufferSurface(managedContext.getContext()); 14571ac4765e959c79101f64b1279887ed469334c268Romain Guy } 14580872b370422eb1f9007b4717b8796543873e6390Jesse Hall 14591ac4765e959c79101f64b1279887ed469334c268Romain Guy try { 14601ac4765e959c79101f64b1279887ed469334c268Romain Guy action.run(); 14611ac4765e959c79101f64b1279887ed469334c268Romain Guy } finally { 14620872b370422eb1f9007b4717b8796543873e6390Jesse Hall if (needsContext) { 14630872b370422eb1f9007b4717b8796543873e6390Jesse Hall sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, 14640872b370422eb1f9007b4717b8796543873e6390Jesse Hall EGL_NO_SURFACE, EGL_NO_CONTEXT); 14650872b370422eb1f9007b4717b8796543873e6390Jesse Hall } 146631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy } 14671ac4765e959c79101f64b1279887ed469334c268Romain Guy 14681ac4765e959c79101f64b1279887ed469334c268Romain Guy return true; 14691ac4765e959c79101f64b1279887ed469334c268Romain Guy } 14701ac4765e959c79101f64b1279887ed469334c268Romain Guy 14711ac4765e959c79101f64b1279887ed469334c268Romain Guy @Override 14721ac4765e959c79101f64b1279887ed469334c268Romain Guy void destroyHardwareResources(final View view) { 14731ac4765e959c79101f64b1279887ed469334c268Romain Guy if (view != null) { 14741ac4765e959c79101f64b1279887ed469334c268Romain Guy safelyRun(new Runnable() { 14751ac4765e959c79101f64b1279887ed469334c268Romain Guy @Override 14761ac4765e959c79101f64b1279887ed469334c268Romain Guy public void run() { 14771ac4765e959c79101f64b1279887ed469334c268Romain Guy destroyResources(view); 14781ac4765e959c79101f64b1279887ed469334c268Romain Guy GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); 14791ac4765e959c79101f64b1279887ed469334c268Romain Guy } 14801ac4765e959c79101f64b1279887ed469334c268Romain Guy }); 14811ac4765e959c79101f64b1279887ed469334c268Romain Guy } 148231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy } 1483244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy 148431f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy private static void destroyResources(View view) { 148531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy view.destroyHardwareResources(); 148631f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy 148731f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy if (view instanceof ViewGroup) { 148831f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy ViewGroup group = (ViewGroup) view; 148931f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy 149031f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy int count = group.getChildCount(); 149131f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy for (int i = 0; i < count; i++) { 149231f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy destroyResources(group.getChildAt(i)); 149331f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy } 149431f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy } 149531f2c2e94656530fbf6282803e62edb47e9a894dRomain Guy } 14966d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 14976d7475d666baefaa3ba9f0dcee25238739454241Romain Guy static HardwareRenderer create(boolean translucent) { 14986d7475d666baefaa3ba9f0dcee25238739454241Romain Guy if (GLES20Canvas.isAvailable()) { 14996d7475d666baefaa3ba9f0dcee25238739454241Romain Guy return new Gl20Renderer(translucent); 15006d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 15016d7475d666baefaa3ba9f0dcee25238739454241Romain Guy return null; 15026d7475d666baefaa3ba9f0dcee25238739454241Romain Guy } 15036d7475d666baefaa3ba9f0dcee25238739454241Romain Guy 150419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy static void startTrimMemory(int level) { 1505912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy if (sEgl == null || sEglConfig == null) return; 1506912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 15075d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy Gl20RendererEglContext managedContext = 15085d6999e1ca457948e06792ea6259ffa947c9fa81Romain Guy (Gl20RendererEglContext) sEglContextStorage.get(); 1509912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy // We do not have OpenGL objects 1510717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn if (managedContext == null) { 1511912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy return; 1512912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } else { 1513717a25dc2a411edb548859cd6870363346c71b01Dianne Hackborn usePbufferSurface(managedContext.getContext()); 15142d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1515912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 151627ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { 151727ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL); 151827ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { 151927ff913d56de8400083a13fc572e2812b32c890cDianne Hackborn GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); 1520bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 152119f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy } 15220872b370422eb1f9007b4717b8796543873e6390Jesse Hall 152319f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy static void endTrimMemory() { 152419f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy if (sEgl != null && sEglDisplay != null) { 152519f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 152619f86e831ee0629b24385b0bb51d27ff91961dd2Romain Guy } 1527bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 15288ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy 15298ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy private static void usePbufferSurface(EGLContext eglContext) { 15308ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy synchronized (sPbufferLock) { 15318ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy // Create a temporary 1x1 pbuffer so we have a context 15328ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy // to clear our OpenGL objects 15338ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy if (sPbuffer == null) { 15348ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] { 15358ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE 15368ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy }); 15378ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy } 15388ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy } 15398ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext); 15408ff6b9ebeeb24a6161ec6098e6bfdf8790ee5695Romain Guy } 15412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 15422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy} 1543