HardwareRenderer.java revision 912a7b32d0c59ba38265c5dd6ff84ce93f909a7f
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 20bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guyimport android.content.ComponentCallbacks; 217d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Paint; 227d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Rect; 23aa6c24c21c727a196451332448d4e3b11a80be69Romain Guyimport android.graphics.SurfaceTexture; 2402ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemClock; 2502ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guyimport android.os.SystemProperties; 26e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport android.util.Log; 272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL10; 292d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL11; 302d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLConfig; 312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLContext; 322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLDisplay; 332d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLSurface; 34e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport javax.microedition.khronos.opengles.GL; 352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 36484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guyimport static javax.microedition.khronos.egl.EGL10.*; 37484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy/** 39c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * Interface for rendering a ViewAncestor using hardware acceleration. 402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @hide 422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 4361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guypublic abstract class HardwareRenderer { 444f6aff386045000c2c03b903c7109cb42092b7eaRomain Guy static final String LOG_TAG = "HardwareRenderer"; 45fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 465233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 477d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to only refresh the parts of the screen that need updating. 48069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY} 49069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * must also have the value "true". 507d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 517d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy public static final boolean RENDER_DIRTY_REGIONS = true; 527d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 54069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * System property used to enable or disable dirty regions invalidation. 55069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true. 56069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * The default value of this property is assumed to be true. 57069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 58069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Possible values: 59069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * "true", to enable partial invalidates 60069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * "false", to disable partial invalidates 61069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 62069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions"; 639ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 649ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy /** 659ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * System property used to enable or disable vsync. 669ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * The default value of this property is assumed to be false. 679ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * 689ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * Possible values: 699ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * "true", to disable vsync 709ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy * "false", to enable vsync 719ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy */ 729ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync"; 73069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy 74069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 75484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * System property used to debug EGL configuration choice. 76484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * 77484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * Possible values: 78484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * "choice", print the chosen configuration only 79484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy * "all", print all possible configurations 80484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy */ 81484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy static final String PRINT_CONFIG_PROPERTY = "hwui.print_config"; 82484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 83484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy /** 847d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to draw dirty regions every other frame. 857d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 867d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy private static final boolean DEBUG_DIRTY_REGION = false; 877d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 887d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 895233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * A process can set this flag to false to prevent the use of hardware 905233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * rendering. 915233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 925233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 935233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 945233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy public static boolean sRendererDisabled = false; 955233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mEnabled; 972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mRequested = true; 982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 10067f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy * Invoke this method to disable hardware rendering in the current process. 1015233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 1025233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 1035233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 1045233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy public static void disable() { 1055233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy sRendererDisabled = true; 1065233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy } 1075233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 1085233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 10961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * Indicates whether hardware acceleration is available under any form for 11061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * the view hierarchy. 11161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * 11261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * @return True if the view hierarchy can potentially be hardware accelerated, 11361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * false otherwise 11461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy */ 11561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy public static boolean isAvailable() { 11661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy return GLES20Canvas.isAvailable(); 11761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } 11861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy 11961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy /** 1202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Destroys the hardware rendering context. 1214caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * 1224caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * @param full If true, destroys all associated resources. 1232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1244caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy abstract void destroy(boolean full); 1252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface. 1282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1292d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param holder The holder for the surface to hardware accelerate. 1302d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if the initialization was successful, false otherwise. 1322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 133648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn abstract boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException; 1342a83f001fdb189f945e82e81e717ba204824b112Romain Guy 1352a83f001fdb189f945e82e81e717ba204824b112Romain Guy /** 1362a83f001fdb189f945e82e81e717ba204824b112Romain Guy * Updates the hardware renderer for the specified surface. 1372a83f001fdb189f945e82e81e717ba204824b112Romain Guy * 1382a83f001fdb189f945e82e81e717ba204824b112Romain Guy * @param holder The holder for the surface to hardware accelerate. 1392a83f001fdb189f945e82e81e717ba204824b112Romain Guy */ 140648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException; 1412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 143039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * This method should be invoked whenever the current hardware renderer 144039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * context should be reset. 1457e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy */ 146039857520b1a03a52051b966d87d587225bdfcc3Romain Guy abstract void invalidate(); 147039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 148039857520b1a03a52051b966d87d587225bdfcc3Romain Guy /** 149039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * This method should be invoked to ensure the hardware renderer is in 150039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * valid state (for instance, to ensure the correct EGL context is bound 151039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * to the current thread.) 152039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * 153039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * @return true if the renderer is now valid, false otherwise 154039857520b1a03a52051b966d87d587225bdfcc3Romain Guy */ 155039857520b1a03a52051b966d87d587225bdfcc3Romain Guy abstract boolean validate(); 1567e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 1577e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy /** 1587e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy * Setup the hardware renderer for drawing. This is called whenever the 1597e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy * size of the target surface changes or when the surface is first created. 1602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width Width of the drawing surface. 1622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height Height of the drawing surface. 1632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 164fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy abstract void setup(int width, int height); 1652d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 166069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 167069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Interface used to receive callbacks whenever a view is drawn by 168069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * a hardware renderer instance. 169069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 1700f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn interface HardwareDrawCallbacks { 171069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 172069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Invoked before a view is drawn by a hardware renderer. 173069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 174069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * @param canvas The Canvas used to render the view. 175069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 1767d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy void onHardwarePreDraw(HardwareCanvas canvas); 177069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy 178069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy /** 179069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * Invoked after a view is drawn by a hardware renderer. 180069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * 181069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy * @param canvas The Canvas used to render the view. 182069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy */ 1837d70fbf0b5672bada8b25f065bc292796c3d4812Romain Guy void onHardwarePostDraw(HardwareCanvas canvas); 1840f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn } 1850f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn 1862d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Draws the specified view. 1887d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * 1892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param view The view to draw. 1902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param attachInfo AttachInfo tied to the specified view. 1917d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param callbacks Callbacks invoked when drawing happens. 1927d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param dirty The dirty rectangle to update, can be null. 1932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1947d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 1957d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty); 1962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 19853ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * Creates a new display list that can be used to record batches of 19953ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * drawing operations. 200b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy * 20153ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * @return A new display list. 202b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy */ 203162a0217563f4665da6eb183dfce0fef740f641fJeff Brown abstract DisplayList createDisplayList(); 204b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy 205b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy /** 206aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Creates a new hardware layer. A hardware layer built by calling this 207aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * method will be treated as a texture layer, instead of as a render target. 208aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 209a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy * @param isOpaque Whether the layer should be opaque or not 210a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy * 211aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @return A hardware layer 212aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy */ 213a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy abstract HardwareLayer createHardwareLayer(boolean isOpaque); 214aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 215aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 2166c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * Creates a new hardware layer. 2176c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 2186c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param width The minimum width of the layer 2196c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param height The minimum height of the layer 2206c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param isOpaque Whether the layer should be opaque or not 2216c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 2226c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @return A hardware layer 2236c319ca1275c8db892c39b48fc54864c949f9171Romain Guy */ 2246c319ca1275c8db892c39b48fc54864c949f9171Romain Guy abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque); 225aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 226aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 227aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * Creates a new {@link SurfaceTexture} that can be used to render into the 228aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * specified hardware layer. 229aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 230aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 231aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} 232aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * 233aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy * @return A {@link SurfaceTexture} 234aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy */ 235e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer); 236aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 237aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy /** 2382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface and setup the 239c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * renderer for drawing, if needed. This is invoked when the ViewAncestor has 2402d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * potentially lost the hardware renderer. The hardware renderer should be 2412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * reinitialized and setup when the render {@link #isRequested()} and 2422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * {@link #isEnabled()}. 2432d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2442d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width The width of the drawing surface. 2452d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height The height of the drawing surface. 2462d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param attachInfo The 2472d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param holder 2482d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 2492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 250648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn SurfaceHolder holder) throws Surface.OutOfResourcesException { 2512d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (isRequested()) { 2522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy // We lost the gl context, so recreate it. 2532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (!isEnabled()) { 2542d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (initialize(holder)) { 255fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setup(width, height); 2562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2572d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2582d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2592d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 2622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Creates a hardware renderer using OpenGL. 2632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2642d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.) 265e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * @param translucent True if the surface is translucent, false otherwise 2662d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2672d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return A hardware renderer backed by OpenGL. 2682d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 269e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) { 2702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy switch (glVersion) { 271e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy case 2: 272163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return Gl20Renderer.create(translucent); 2732d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2742d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy throw new IllegalArgumentException("Unknown GL version: " + glVersion); 2752d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2762d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2772d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 278bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * Invoke this method when the system is running out of memory. This 279bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * method will attempt to recover as much memory as possible, based on 280bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * the specified hint. 281bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * 282bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * @param level Hint about the amount of memory that should be trimmed, 283bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy * see {@link android.content.ComponentCallbacks} 284bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy */ 285bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy static void trimMemory(int level) { 286912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy Gl20Renderer.trimMemory(level); 287bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 288bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy 289bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy /** 2902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 2912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if hardware acceleration is in use, false otherwise. 2932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 2942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isEnabled() { 2952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mEnabled; 2962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 2992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 3002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 3012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param enabled True if the hardware renderer is in use, false otherwise. 3022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 3032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setEnabled(boolean enabled) { 3042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mEnabled = enabled; 3052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 3062d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 3072d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 3082d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently request but not 3092d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 3102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 3112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if requested, false otherwise. 3122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 3132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isRequested() { 3142d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mRequested; 3152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 3162d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 3172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 3189745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy * Indicates whether hardware acceleration is currently requested but not 3192d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 3202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 3212d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True to request hardware acceleration, false otherwise. 3222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 3232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setRequested(boolean requested) { 3242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mRequested = requested; 3252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 3262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 3272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @SuppressWarnings({"deprecation"}) 328e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static abstract class GlRenderer extends HardwareRenderer { 329aaceeb0c5be11121a81e44b9633c06fc5c0fcd4dRomain Guy // These values are not exposed in our EGL APIs 330e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 331e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy static final int EGL_OPENGL_ES2_BIT = 4; 3327e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final int EGL_SURFACE_TYPE = 0x3033; 3337e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400; 334e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 335d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_ERROR = 0; 336d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_SUCCESS = 1; 337d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_UPDATED = 2; 338d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 339fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGL10 sEgl; 340fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLDisplay sEglDisplay; 341fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLConfig sEglConfig; 342566b3efb25299d2a9c8ae827522802bad965426aRomain Guy static final Object[] sEglLock = new Object[0]; 343e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 344566b3efb25299d2a9c8ae827522802bad965426aRomain Guy static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>(); 345566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 346566b3efb25299d2a9c8ae827522802bad965426aRomain Guy EGLContext mEglContext; 347566b3efb25299d2a9c8ae827522802bad965426aRomain Guy Thread mEglThread; 348fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 349fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy EGLSurface mEglSurface; 350fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 351e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy GL mGl; 35267f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy HardwareCanvas mCanvas; 3537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy int mFrameCount; 3547d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Paint mDebugPaint; 3557d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 3567e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static boolean sDirtyRegions; 3577e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static final boolean sDirtyRegionsRequested; 3587e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy static { 3597e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true"); 3607e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy //noinspection PointlessBooleanExpression,ConstantConditions 3617e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); 3627e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy sDirtyRegionsRequested = sDirtyRegions; 3637e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } 3647e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 3657e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy boolean mDirtyRegionsEnabled; 3669ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy final boolean mVsyncDisabled; 3672d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 368e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final int mGlVersion; 369e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final boolean mTranslucent; 3702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 371fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy private boolean mDestroyed; 372566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 373cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy private final Rect mRedrawClip = new Rect(); 374fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 375e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy GlRenderer(int glVersion, boolean translucent) { 376e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGlVersion = glVersion; 377e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy mTranslucent = translucent; 3789ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 3799ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy final String vsyncProperty = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false"); 3809ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy mVsyncDisabled = "true".equalsIgnoreCase(vsyncProperty); 3819ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (mVsyncDisabled) { 3829ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy Log.d(LOG_TAG, "Disabling v-sync"); 3839ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 3842d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 3852d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 386e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 38702ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy * Indicates whether this renderer instance can track and update dirty regions. 38802ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy */ 38902ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy boolean hasDirtyRegions() { 3907e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy return mDirtyRegionsEnabled; 39102ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy } 39202ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy 39302ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy /** 3945d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd * Return a string for the EGL error code, or the hex representation 395d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * if the error is unknown. 396d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * 397d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * @param error The EGL error to convert into a String. 398d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * 399d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * @return An error string correponding to the EGL error code. 4005d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd */ 4015d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd static String getEGLErrorString(int error) { 4025d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd switch (error) { 403484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_SUCCESS: 4045d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_SUCCESS"; 405484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_NOT_INITIALIZED: 4065d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_NOT_INITIALIZED"; 407484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_ACCESS: 4085d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ACCESS"; 409484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_ALLOC: 4105d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ALLOC"; 411484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_ATTRIBUTE: 4125d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ATTRIBUTE"; 413484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_CONFIG: 4145d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CONFIG"; 415484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_CONTEXT: 4165d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CONTEXT"; 417484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_CURRENT_SURFACE: 4185d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CURRENT_SURFACE"; 419484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_DISPLAY: 4205d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_DISPLAY"; 421484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_MATCH: 4225d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_MATCH"; 423484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_NATIVE_PIXMAP: 4245d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_NATIVE_PIXMAP"; 425484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_NATIVE_WINDOW: 4265d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_NATIVE_WINDOW"; 427484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_PARAMETER: 4285d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_PARAMETER"; 429484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy case EGL_BAD_SURFACE: 4305d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_SURFACE"; 4315d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL11.EGL_CONTEXT_LOST: 4325d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_CONTEXT_LOST"; 4335d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd default: 4345d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "0x" + Integer.toHexString(error); 4355d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd } 4365d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd } 4375d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd 4385d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd /** 4394caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)} 440e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * is invoked and the requested flag is turned off. The error code is 441e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * also logged as a warning. 442e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 443b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void checkEglErrors() { 444e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isEnabled()) { 445fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int error = sEgl.eglGetError(); 446484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (error != EGL_SUCCESS) { 447e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // something bad has happened revert to 448e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // normal rendering. 4499745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy fallback(error != EGL11.EGL_CONTEXT_LOST); 4505d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd Log.w(LOG_TAG, "EGL error: " + getEGLErrorString(error)); 451e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 4522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 45467f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 4559745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy private void fallback(boolean fallback) { 4569745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy destroy(true); 4579745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy if (fallback) { 4589745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy // we'll try again if it was context lost 4599745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy setRequested(false); 4609745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.w(LOG_TAG, "Mountain View, we've had a problem here. " 4619745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy + "Switching back to software rendering."); 4629745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 4639745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 4649745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy 465e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 466648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn boolean initialize(SurfaceHolder holder) throws Surface.OutOfResourcesException { 467e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isRequested() && !isEnabled()) { 468e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy initializeEgl(); 469e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = createEglSurface(holder); 470fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mDestroyed = false; 4712d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 472e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mGl != null) { 473fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int err = sEgl.eglGetError(); 474484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (err != EGL_SUCCESS) { 4754caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy destroy(true); 476e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setRequested(false); 477e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 4784caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (mCanvas == null) { 4794caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = createCanvas(); 480fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 481e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mCanvas != null) { 482e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setEnabled(true); 483e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 484e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy Log.w(LOG_TAG, "Hardware accelerated Canvas could not be created"); 485e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 486e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 487e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 488e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mCanvas != null; 489e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 490e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 491e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return false; 492e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 4932a83f001fdb189f945e82e81e717ba204824b112Romain Guy 4942a83f001fdb189f945e82e81e717ba204824b112Romain Guy @Override 495648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException { 4962a83f001fdb189f945e82e81e717ba204824b112Romain Guy if (isRequested() && isEnabled()) { 4972a83f001fdb189f945e82e81e717ba204824b112Romain Guy createEglSurface(holder); 4982a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 4992a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 500e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 501fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy abstract GLES20Canvas createCanvas(); 5022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 50329d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy abstract int[] getConfig(boolean dirtyRegions); 50429d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy 505e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy void initializeEgl() { 506566b3efb25299d2a9c8ae827522802bad965426aRomain Guy synchronized (sEglLock) { 507566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sEgl == null && sEglConfig == null) { 508566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sEgl = (EGL10) EGLContext.getEGL(); 509566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 510566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // Get to the default display. 511484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 512566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 513484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (sEglDisplay == EGL_NO_DISPLAY) { 514566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglGetDisplay failed " 515566b3efb25299d2a9c8ae827522802bad965426aRomain Guy + getEGLErrorString(sEgl.eglGetError())); 516566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 517566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 518566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // We can now initialize EGL for that display 519566b3efb25299d2a9c8ae827522802bad965426aRomain Guy int[] version = new int[2]; 520566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglInitialize(sEglDisplay, version)) { 521566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglInitialize failed " + 522566b3efb25299d2a9c8ae827522802bad965426aRomain Guy getEGLErrorString(sEgl.eglGetError())); 523566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 524566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 525e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy sEglConfig = chooseEglConfig(); 526069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy if (sEglConfig == null) { 527566b3efb25299d2a9c8ae827522802bad965426aRomain Guy // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without 528566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sDirtyRegions) { 529566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sDirtyRegions = false; 530566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sEglConfig = chooseEglConfig(); 531566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (sEglConfig == null) { 532566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglConfig not initialized"); 533566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 534566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } else { 535566b3efb25299d2a9c8ae827522802bad965426aRomain Guy throw new RuntimeException("eglConfig not initialized"); 536566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 537069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 538069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 539069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy } 540566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 541566b3efb25299d2a9c8ae827522802bad965426aRomain Guy mEglContext = sEglContextStorage.get(); 542566b3efb25299d2a9c8ae827522802bad965426aRomain Guy mEglThread = Thread.currentThread(); 543566b3efb25299d2a9c8ae827522802bad965426aRomain Guy 544566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (mEglContext == null) { 545566b3efb25299d2a9c8ae827522802bad965426aRomain Guy mEglContext = createContext(sEgl, sEglDisplay, sEglConfig); 546566b3efb25299d2a9c8ae827522802bad965426aRomain Guy sEglContextStorage.set(mEglContext); 547566b3efb25299d2a9c8ae827522802bad965426aRomain Guy } 548e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 549e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 550e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy private EGLConfig chooseEglConfig() { 551e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy EGLConfig[] configs = new EGLConfig[1]; 552484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy int[] configsCount = new int[1]; 5537e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy int[] configSpec = getConfig(sDirtyRegions); 554484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 555484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy // Debug 55629d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, ""); 557484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if ("all".equalsIgnoreCase(debug)) { 558484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount); 559484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 560484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]]; 561484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs, 562484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy configsCount[0], configsCount); 563484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 564484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy for (EGLConfig config : debugConfigs) { 565484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy printConfig(config); 566484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 567484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 568484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 569e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) { 570e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy throw new IllegalArgumentException("eglChooseConfig failed " + 571e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy getEGLErrorString(sEgl.eglGetError())); 572e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } else if (configsCount[0] > 0) { 573484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if ("choice".equalsIgnoreCase(debug)) { 574484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy printConfig(configs[0]); 575484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 576e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return configs[0]; 577e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 578484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 579e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return null; 580e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 581e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 582484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy private void printConfig(EGLConfig config) { 583484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy int[] value = new int[1]; 584484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 585484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, "EGL configuration " + config + ":"); 586484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 587484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value); 588484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " RED_SIZE = " + value[0]); 589484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 590484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value); 591484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " GREEN_SIZE = " + value[0]); 592484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 593484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value); 594484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " BLUE_SIZE = " + value[0]); 595484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 596484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value); 597484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " ALPHA_SIZE = " + value[0]); 598484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 599484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value); 600484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " DEPTH_SIZE = " + value[0]); 601484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 602484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value); 603484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]); 604484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 605484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value); 60629d23ecfd8612ecd4a7b2140acd344934b73a558Romain Guy Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0])); 607484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy } 608484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy 609648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException { 610e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Check preconditions. 611fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEgl == null) { 612e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("egl not initialized"); 613e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 614fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglDisplay == null) { 615e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("eglDisplay not initialized"); 616e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 617fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglConfig == null) { 618069ea0e31a0aa283c83fae79f31a1798a6d85ddeRomain Guy throw new RuntimeException("eglConfig not initialized"); 619e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 620566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (Thread.currentThread() != mEglThread) { 621fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy throw new IllegalStateException("HardwareRenderer cannot be used " 622fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy + "from multiple threads"); 623fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 624e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 6252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 626e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * The window size has changed, so we need to create a new 627e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * surface. 6282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 629484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) { 630e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /* 631e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Unbind and destroy the old EGL surface, if 632e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * there is one. 633e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 634484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 635fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 636e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 637e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 638e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Create an EGL surface we can render into. 639fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); 640e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 641484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) { 642fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int error = sEgl.eglGetError(); 643484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy if (error == EGL_BAD_NATIVE_WINDOW) { 6447d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 645e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return null; 646e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 6475d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new RuntimeException("createWindowSurface failed " 6485d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(error)); 649e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 650e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 6512d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 6522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Before we can issue GL commands, we need to make sure 6532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * the context is current and bound to a surface. 6542d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 655566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 656648251710162cdaf7371012a1cbb79b9bc5bc0e4Dianne Hackborn throw new Surface.OutOfResourcesException("eglMakeCurrent failed " 6575d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(sEgl.eglGetError())); 658e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 6596f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy 6606f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // If mDirtyRegions is set, this means we have an EGL configuration 6616f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set 6627e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy if (sDirtyRegions) { 6637e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) { 6647d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Log.w(LOG_TAG, "Backbuffer cannot be preserved"); 6657d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 6667e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } else if (sDirtyRegionsRequested) { 6676f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // If mDirtyRegions is not set, our EGL configuration does not 6686f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default 6696f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // swap behavior might be EGL_BUFFER_PRESERVED, which means we 6706f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // want to set mDirtyRegions. We try to do this only if dirty 6716f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // regions were initially requested as part of the device 6726f7d9394ec69e9fb38ca5fc2caf6d2aef6f7442dRomain Guy // configuration (see RENDER_DIRTY_REGIONS) 6737e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved(); 6747d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 675e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 676566b3efb25299d2a9c8ae827522802bad965426aRomain Guy return mEglContext.getGL(); 6772d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 6782d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 679e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 680912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE }; 681e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 682484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, 683912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy mGlVersion != 0 ? attribs : null); 684e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 685e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 686e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 6874caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy void destroy(boolean full) { 6884caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (full && mCanvas != null) { 6894caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = null; 6904caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy } 6914caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy 692fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (!isEnabled() || mDestroyed) return; 693fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 694fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mDestroyed = true; 695e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 696484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 697fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 6982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 6992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mEglSurface = null; 700e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = null; 701fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 7022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy setEnabled(false); 703fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 704fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 7052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 706039857520b1a03a52051b966d87d587225bdfcc3Romain Guy void invalidate() { 7077e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy // Cancels any existing buffer to ensure we'll get a buffer 7087e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy // of the right size before we call eglSwapBuffers 709484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, 710484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_NO_SURFACE, EGL_NO_CONTEXT); 711039857520b1a03a52051b966d87d587225bdfcc3Romain Guy } 712039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 713039857520b1a03a52051b966d87d587225bdfcc3Romain Guy @Override 714039857520b1a03a52051b966d87d587225bdfcc3Romain Guy boolean validate() { 715039857520b1a03a52051b966d87d587225bdfcc3Romain Guy return checkCurrent() != SURFACE_STATE_ERROR; 7167e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy } 7177e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy 7187e1160e8664a9c5c79367f4ba3c2266a39bbcef5Romain Guy @Override 719fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy void setup(int width, int height) { 720912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy checkCurrent(); 721fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCanvas.setViewport(width, height); 722e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 7237d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 724e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy boolean canDraw() { 725e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mGl != null && mCanvas != null; 726e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 727e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 7287d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void onPreDraw(Rect dirty) { 729e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 730e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 731b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 732b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 7332d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 7342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 7357d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 7367d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty) { 737e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (canDraw()) { 73802ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy if (!hasDirtyRegions()) { 7397d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy dirty = null; 7407d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 7412d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy attachInfo.mIgnoreDirtyState = true; 74202ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy attachInfo.mDrawingTime = SystemClock.uptimeMillis(); 74302ccac69fd1c0a03c24c5f3ace0ad4bed337b1fdRomain Guy 7442d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy view.mPrivateFlags |= View.DRAWN; 745039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 746d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy final int surfaceState = checkCurrent(); 747d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState != SURFACE_STATE_ERROR) { 748d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy // We had to change the current surface and/or context, redraw everything 749d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState == SURFACE_STATE_UPDATED) { 750d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy dirty = null; 751d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } 752d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 7537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy onPreDraw(dirty); 75462687ec12cb8e0b1d4044a235b1387b9a8c3b4b4Romain Guy 755daf98e941e140e8739458126640183b9f296a2abChet Haase HardwareCanvas canvas = mCanvas; 756daf98e941e140e8739458126640183b9f296a2abChet Haase attachInfo.mHardwareCanvas = canvas; 7577d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 758b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy int saveCount = canvas.save(); 759b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy callbacks.onHardwarePreDraw(canvas); 760daf98e941e140e8739458126640183b9f296a2abChet Haase 761b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 762daf98e941e140e8739458126640183b9f296a2abChet Haase view.mRecreateDisplayList = 763daf98e941e140e8739458126640183b9f296a2abChet Haase (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED; 764daf98e941e140e8739458126640183b9f296a2abChet Haase view.mPrivateFlags &= ~View.INVALIDATED; 7657d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 766daf98e941e140e8739458126640183b9f296a2abChet Haase DisplayList displayList = view.getDisplayList(); 767daf98e941e140e8739458126640183b9f296a2abChet Haase if (displayList != null) { 7687b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy if (canvas.drawDisplayList(displayList, view.getWidth(), 7697b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy view.getHeight(), mRedrawClip)) { 770e294d41593f13edc5598cf62f8a89e573b3eb653Romain Guy if (mRedrawClip.isEmpty() || view.getParent() == null) { 771cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy view.invalidate(); 772cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy } else { 773cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy view.getParent().invalidateChild(view, mRedrawClip); 774cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy } 775cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy mRedrawClip.setEmpty(); 776daf98e941e140e8739458126640183b9f296a2abChet Haase } 777daf98e941e140e8739458126640183b9f296a2abChet Haase } else { 778daf98e941e140e8739458126640183b9f296a2abChet Haase // Shouldn't reach here 779daf98e941e140e8739458126640183b9f296a2abChet Haase view.draw(canvas); 780daf98e941e140e8739458126640183b9f296a2abChet Haase } 7817d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 7827d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (DEBUG_DIRTY_REGION) { 7837d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (mDebugPaint == null) { 7847d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint = new Paint(); 7857d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint.setColor(0x7fff0000); 7867d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 7877d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (dirty != null && (mFrameCount++ & 1) == 0) { 7887d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy canvas.drawRect(dirty, mDebugPaint); 7897d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 7907d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 791b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } finally { 792b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy callbacks.onHardwarePostDraw(canvas); 793b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy canvas.restoreToCount(saveCount); 794daf98e941e140e8739458126640183b9f296a2abChet Haase view.mRecreateDisplayList = false; 795b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 796daf98e941e140e8739458126640183b9f296a2abChet Haase 797b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy onPostDraw(); 798daf98e941e140e8739458126640183b9f296a2abChet Haase 799b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy attachInfo.mIgnoreDirtyState = false; 8004e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown 801b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); 802b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy checkEglErrors(); 8039a40babc62416259d18783ce8c03c00042ec317bRomain Guy } 8042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 8052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 806039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 807039857520b1a03a52051b966d87d587225bdfcc3Romain Guy /** 808566b3efb25299d2a9c8ae827522802bad965426aRomain Guy * Ensures the current EGL context is the one we expect. 809039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * 810039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current, 811039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or 812039857520b1a03a52051b966d87d587225bdfcc3Romain Guy * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one 813039857520b1a03a52051b966d87d587225bdfcc3Romain Guy */ 814912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy int checkCurrent() { 815566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (mEglThread != Thread.currentThread()) { 816039857520b1a03a52051b966d87d587225bdfcc3Romain Guy throw new IllegalStateException("Hardware acceleration can only be used with a " + 817566b3efb25299d2a9c8ae827522802bad965426aRomain Guy "single UI thread.\nOriginal thread: " + mEglThread + "\n" + 818039857520b1a03a52051b966d87d587225bdfcc3Romain Guy "Current thread: " + Thread.currentThread()); 819039857520b1a03a52051b966d87d587225bdfcc3Romain Guy } 820039857520b1a03a52051b966d87d587225bdfcc3Romain Guy 821566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!mEglContext.equals(sEgl.eglGetCurrentContext()) || 822484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) { 823566b3efb25299d2a9c8ae827522802bad965426aRomain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 8249745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy fallback(true); 8259745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.e(LOG_TAG, "eglMakeCurrent failed " + 8269745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy getEGLErrorString(sEgl.eglGetError())); 827d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_ERROR; 828d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } else { 829d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_UPDATED; 830fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 831fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 832d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_SUCCESS; 833fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 834e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 835fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 836e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 837e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Hardware renderer using OpenGL ES 2.0. 838e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 839e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static class Gl20Renderer extends GlRenderer { 840e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy private GLES20Canvas mGlCanvas; 841e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 842912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy private static EGLSurface sPbuffer; 843912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy private static final Object[] sPbufferLock = new Object[0]; 844912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 845e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy Gl20Renderer(boolean translucent) { 846e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy super(2, translucent); 847e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 848e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 8492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 850fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy GLES20Canvas createCanvas() { 8516b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy return mGlCanvas = new GLES20Canvas(mTranslucent); 852e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 853e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 854e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy @Override 855e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy int[] getConfig(boolean dirtyRegions) { 856e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy return new int[] { 857484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 858484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_RED_SIZE, 8, 859484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_GREEN_SIZE, 8, 860484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_BLUE_SIZE, 8, 861484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_ALPHA_SIZE, 8, 862484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_DEPTH_SIZE, 0, 863484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_STENCIL_SIZE, 0, 864484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_SURFACE_TYPE, EGL_WINDOW_BIT | 86508645eb0f4a8d73b2b2f26d3232f45cf459a27bcRomain Guy (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), 866484c719c1c4a86d10d7be821782a808d0e12ea4eRomain Guy EGL_NONE 867e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy }; 868e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy } 869e91a9c7ab075c43e983fdeb9af80447caa501337Romain Guy 870b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy @Override 871b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy boolean canDraw() { 872b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy return super.canDraw() && mGlCanvas != null; 873b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 874e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 875e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy @Override 8767d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void onPreDraw(Rect dirty) { 8777d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mGlCanvas.onPreDraw(dirty); 878e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 879e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 880b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy @Override 881b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 882b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy mGlCanvas.onPostDraw(); 883b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 884b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy 885b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy @Override 88667f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy void destroy(boolean full) { 887b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 888b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy super.destroy(full); 889b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } finally { 890b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy if (full && mGlCanvas != null) { 891b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy mGlCanvas = null; 892b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 89367f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 89467f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 89567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 89667f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy @Override 8979ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy void setup(int width, int height) { 8989ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy super.setup(width, height); 8999ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy if (mVsyncDisabled) { 9009ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy GLES20Canvas.disableVsync(); 9019ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 9029ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy } 9039ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy 9049ace8f5e79e76893fe4ca9e4d10f6c4056330485Romain Guy @Override 905162a0217563f4665da6eb183dfce0fef740f641fJeff Brown DisplayList createDisplayList() { 906162a0217563f4665da6eb183dfce0fef740f641fJeff Brown return new GLES20DisplayList(); 907b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy } 908aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 909aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy @Override 910a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy HardwareLayer createHardwareLayer(boolean isOpaque) { 911a9489274d67b540804aafb587a226f7c2ae4464dRomain Guy return new GLES20TextureLayer(isOpaque); 912aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 913aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 9146c319ca1275c8db892c39b48fc54864c949f9171Romain Guy @Override 9156c319ca1275c8db892c39b48fc54864c949f9171Romain Guy HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { 916aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy return new GLES20RenderLayer(width, height, isOpaque); 917aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 918aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 919aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy @Override 920e5e0c50f7dfaccc220725c5595080e921ffda1e4Romain Guy SurfaceTexture createSurfaceTexture(HardwareLayer layer) { 921aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy return ((GLES20TextureLayer) layer).getSurfaceTexture(); 922aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy } 923aa6c24c21c727a196451332448d4e3b11a80be69Romain Guy 924912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy static void trimMemory(int level) { 925912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy if (sEgl == null || sEglConfig == null) return; 926912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 927912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy EGLContext eglContext = sEglContextStorage.get(); 928912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy // We do not have OpenGL objects 929912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy if (eglContext == null) { 930912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy return; 931912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } else { 932912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy synchronized (sPbufferLock) { 933912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy // Create a temporary 1x1 pbuffer so we have a context 934912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy // to clear our OpenGL objects 935912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy if (sPbuffer == null) { 936912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] { 937912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE 938912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy }); 939912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } 940912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } 941912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext); 9422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 943912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 944bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy switch (level) { 945bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy case ComponentCallbacks.TRIM_MEMORY_MODERATE: 946bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); 947bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy break; 948bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy case ComponentCallbacks.TRIM_MEMORY_COMPLETE: 949bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL); 950bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy break; 951bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 952bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy } 953912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy 954912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy static HardwareRenderer create(boolean translucent) { 955912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy if (GLES20Canvas.isAvailable()) { 956912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy return new Gl20Renderer(translucent); 957912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } 958912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy return null; 959912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy } 9602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 9612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy} 962