HardwareRenderer.java revision 62687ec12cb8e0b1d4044a235b1387b9a8c3b4b4
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 202d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport android.graphics.Canvas; 217d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Paint; 227d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guyimport android.graphics.Rect; 232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport android.os.SystemClock; 249a40babc62416259d18783ce8c03c00042ec317bRomain Guyimport android.util.EventLog; 25e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport android.util.Log; 262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL10; 282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGL11; 292d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLConfig; 302d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLContext; 312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLDisplay; 322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guyimport javax.microedition.khronos.egl.EGLSurface; 33e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guyimport javax.microedition.khronos.opengles.GL; 342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy/** 362d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Interface for rendering a ViewRoot using hardware acceleration. 372d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 382d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @hide 392d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 4061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guypublic abstract class HardwareRenderer { 414f6aff386045000c2c03b903c7109cb42092b7eaRomain Guy static final String LOG_TAG = "HardwareRenderer"; 42fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 435233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 447d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to only refresh the parts of the screen that need updating. 457d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 467d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy public static final boolean RENDER_DIRTY_REGIONS = true; 477d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 487d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 497d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * Turn on to draw dirty regions every other frame. 507d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy */ 517d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy private static final boolean DEBUG_DIRTY_REGION = false; 527d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy /** 545233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * A process can set this flag to false to prevent the use of hardware 555233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * rendering. 565233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 575233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 585233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 595233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy public static boolean sRendererDisabled = false; 605233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mEnabled; 622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy private boolean mRequested = true; 632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 642d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 6567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy * Invoke this method to disable hardware rendering in the current process. 665233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * 675233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy * @hide 685233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy */ 695233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy public static void disable() { 705233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy sRendererDisabled = true; 715233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy } 725233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy 735233920a216302b4aa03b100c32e8b3efe33cbc6Romain Guy /** 7461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * Indicates whether hardware acceleration is available under any form for 7561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * the view hierarchy. 7661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * 7761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * @return True if the view hierarchy can potentially be hardware accelerated, 7861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy * false otherwise 7961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy */ 8061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy public static boolean isAvailable() { 8161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy return GLES20Canvas.isAvailable(); 8261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } 8361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy 8461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy /** 852d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Destroys the hardware rendering context. 864caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * 874caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * @param full If true, destroys all associated resources. 882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 894caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy abstract void destroy(boolean full); 902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface. 932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param holder The holder for the surface to hardware accelerate. 952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if the initialization was successful, false otherwise. 972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy abstract boolean initialize(SurfaceHolder holder); 992a83f001fdb189f945e82e81e717ba204824b112Romain Guy 1002a83f001fdb189f945e82e81e717ba204824b112Romain Guy /** 1012a83f001fdb189f945e82e81e717ba204824b112Romain Guy * Updates the hardware renderer for the specified surface. 1022a83f001fdb189f945e82e81e717ba204824b112Romain Guy * 1032a83f001fdb189f945e82e81e717ba204824b112Romain Guy * @param holder The holder for the surface to hardware accelerate. 1042a83f001fdb189f945e82e81e717ba204824b112Romain Guy */ 1052a83f001fdb189f945e82e81e717ba204824b112Romain Guy abstract void updateSurface(SurfaceHolder holder); 1062d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1072d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1082d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Setup the hardware renderer for drawing. This is called for every 1092d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * frame to draw. 1102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width Width of the drawing surface. 1122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height Height of the drawing surface. 1132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 114fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy abstract void setup(int width, int height); 1152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1160f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn interface HardwareDrawCallbacks { 1170f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn void onHardwarePreDraw(Canvas canvas); 1180f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn void onHardwarePostDraw(Canvas canvas); 1190f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn } 1200f761d6b8f5d5a607c87dbcdca6fe0ec7911970eDianne Hackborn 1212d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Draws the specified view. 1237d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * 1242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param view The view to draw. 1252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param attachInfo AttachInfo tied to the specified view. 1267d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param callbacks Callbacks invoked when drawing happens. 1277d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy * @param dirty The dirty rectangle to update, can be null. 1282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1297d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 1307d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty); 1312d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1322d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 13353ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * Creates a new display list that can be used to record batches of 13453ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * drawing operations. 135b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy * 13653ca03d9a3a6a95286302802173c4820b16328ceRomain Guy * @return A new display list. 137b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy */ 138daf98e941e140e8739458126640183b9f296a2abChet Haase abstract DisplayList createDisplayList(View v); 139b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy 140b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy /** 1416c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * Creates a new hardware layer. 1426c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 1436c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param width The minimum width of the layer 1446c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param height The minimum height of the layer 1456c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @param isOpaque Whether the layer should be opaque or not 1466c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * 1476c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * @return A hardware layer 1486c319ca1275c8db892c39b48fc54864c949f9171Romain Guy */ 1496c319ca1275c8db892c39b48fc54864c949f9171Romain Guy abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque); 1506c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 1516c319ca1275c8db892c39b48fc54864c949f9171Romain Guy /** 1522d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Initializes the hardware renderer for the specified surface and setup the 1532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * renderer for drawing, if needed. This is invoked when the ViewRoot has 1542d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * potentially lost the hardware renderer. The hardware renderer should be 1552d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * reinitialized and setup when the render {@link #isRequested()} and 1562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * {@link #isEnabled()}. 1572d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1582d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param width The width of the drawing surface. 1592d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param height The height of the drawing surface. 1602d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param attachInfo The 1612d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param holder 1622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 1642d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy SurfaceHolder holder) { 1652d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (isRequested()) { 1662d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy // We lost the gl context, so recreate it. 1672d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (!isEnabled()) { 1682d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy if (initialize(holder)) { 169fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy setup(width, height); 1702d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1712d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1722d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1732d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1742d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1752d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1762d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Creates a hardware renderer using OpenGL. 1772d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1782d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.) 179e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * @param translucent True if the surface is translucent, false otherwise 1802d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1812d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return A hardware renderer backed by OpenGL. 1822d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 183e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) { 1842d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy switch (glVersion) { 185e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy case 2: 186163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return Gl20Renderer.create(translucent); 1872d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1882d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy throw new IllegalArgumentException("Unknown GL version: " + glVersion); 1892d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1902d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 1912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 1922d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 1932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 1942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if hardware acceleration is in use, false otherwise. 1952d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 1962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isEnabled() { 1972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mEnabled; 1982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 1992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 2012d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently enabled. 2022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @param enabled True if the hardware renderer is in use, false otherwise. 2042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 2052d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setEnabled(boolean enabled) { 2062d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mEnabled = enabled; 2072d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2082d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2092d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 2102d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Indicates whether hardware acceleration is currently request but not 2112d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 2122d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2132d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True if requested, false otherwise. 2142d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 2152d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy boolean isRequested() { 2162d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy return mRequested; 2172d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2182d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2192d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /** 2209745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy * Indicates whether hardware acceleration is currently requested but not 2212d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * necessarily enabled yet. 2222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * 2232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * @return True to request hardware acceleration, false otherwise. 2242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 2252d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy void setRequested(boolean requested) { 2262d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mRequested = requested; 2272d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2282d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 2292d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @SuppressWarnings({"deprecation"}) 230e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static abstract class GlRenderer extends HardwareRenderer { 231e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 2327d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy private static final int EGL_SURFACE_TYPE = 0x3033; 2337d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy private static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400; 234e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 235d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_ERROR = 0; 236d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_SUCCESS = 1; 237d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private static final int SURFACE_STATE_UPDATED = 2; 238d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 239fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLContext sEglContext; 240fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGL10 sEgl; 241fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLDisplay sEglDisplay; 242fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy static EGLConfig sEglConfig; 243e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 244fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy private static Thread sEglThread; 245fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 246fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy EGLSurface mEglSurface; 247fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 248e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy GL mGl; 24967f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy HardwareCanvas mCanvas; 2507d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy int mFrameCount; 2517d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Paint mDebugPaint; 2527d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 2532d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 254e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final int mGlVersion; 255e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy final boolean mTranslucent; 2562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 257fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy private boolean mDestroyed; 258fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 259e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy GlRenderer(int glVersion, boolean translucent) { 260e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGlVersion = glVersion; 261e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy mTranslucent = translucent; 2622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 2632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 264e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 2655d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd * Return a string for the EGL error code, or the hex representation 266d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * if the error is unknown. 267d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * 268d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * @param error The EGL error to convert into a String. 269d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * 270d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * @return An error string correponding to the EGL error code. 2715d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd */ 2725d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd static String getEGLErrorString(int error) { 2735d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd switch (error) { 2745d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_SUCCESS: 2755d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_SUCCESS"; 2765d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_NOT_INITIALIZED: 2775d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_NOT_INITIALIZED"; 2785d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_ACCESS: 2795d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ACCESS"; 2805d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_ALLOC: 2815d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ALLOC"; 2825d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_ATTRIBUTE: 2835d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_ATTRIBUTE"; 2845d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_CONFIG: 2855d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CONFIG"; 2865d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_CONTEXT: 2875d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CONTEXT"; 2885d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_CURRENT_SURFACE: 2895d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_CURRENT_SURFACE"; 2905d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_DISPLAY: 2915d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_DISPLAY"; 2925d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_MATCH: 2935d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_MATCH"; 2945d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_NATIVE_PIXMAP: 2955d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_NATIVE_PIXMAP"; 2965d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_NATIVE_WINDOW: 2975d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_NATIVE_WINDOW"; 2985d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_PARAMETER: 2995d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_PARAMETER"; 3005d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL10.EGL_BAD_SURFACE: 3015d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_BAD_SURFACE"; 3025d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd case EGL11.EGL_CONTEXT_LOST: 3035d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "EGL_CONTEXT_LOST"; 3045d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd default: 3055d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd return "0x" + Integer.toHexString(error); 3065d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd } 3075d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd } 3085d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd 3095d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd /** 3104caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)} 311e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * is invoked and the requested flag is turned off. The error code is 312e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * also logged as a warning. 313e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 314b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void checkEglErrors() { 315e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isEnabled()) { 316fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int error = sEgl.eglGetError(); 317e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (error != EGL10.EGL_SUCCESS) { 318e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // something bad has happened revert to 319e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // normal rendering. 3209745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy fallback(error != EGL11.EGL_CONTEXT_LOST); 3215d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd Log.w(LOG_TAG, "EGL error: " + getEGLErrorString(error)); 322e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 3232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 3242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 32567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 3269745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy private void fallback(boolean fallback) { 3279745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy destroy(true); 3289745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy if (fallback) { 3299745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy // we'll try again if it was context lost 3309745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy setRequested(false); 3319745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.w(LOG_TAG, "Mountain View, we've had a problem here. " 3329745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy + "Switching back to software rendering."); 3339745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 3349745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy } 3359745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy 336e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 337e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy boolean initialize(SurfaceHolder holder) { 338e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isRequested() && !isEnabled()) { 339e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy initializeEgl(); 340e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = createEglSurface(holder); 341fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mDestroyed = false; 3422d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 343e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mGl != null) { 344fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int err = sEgl.eglGetError(); 345e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (err != EGL10.EGL_SUCCESS) { 3464caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy destroy(true); 347e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setRequested(false); 348e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 3494caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (mCanvas == null) { 3504caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = createCanvas(); 351fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 352e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mCanvas != null) { 353e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy setEnabled(true); 354e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } else { 355e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy Log.w(LOG_TAG, "Hardware accelerated Canvas could not be created"); 356e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 357e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 358e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 359e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mCanvas != null; 360e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 361e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 362e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return false; 363e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 3642a83f001fdb189f945e82e81e717ba204824b112Romain Guy 3652a83f001fdb189f945e82e81e717ba204824b112Romain Guy @Override 3662a83f001fdb189f945e82e81e717ba204824b112Romain Guy void updateSurface(SurfaceHolder holder) { 3672a83f001fdb189f945e82e81e717ba204824b112Romain Guy if (isRequested() && isEnabled()) { 3682a83f001fdb189f945e82e81e717ba204824b112Romain Guy createEglSurface(holder); 3692a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 3702a83f001fdb189f945e82e81e717ba204824b112Romain Guy } 371e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 372fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy abstract GLES20Canvas createCanvas(); 3732d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 374e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy void initializeEgl() { 375fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglContext != null) return; 376fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 377fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEglThread = Thread.currentThread(); 378fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl = (EGL10) EGLContext.getEGL(); 379e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 380e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Get to the default display. 381fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 382e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 383fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglDisplay == EGL10.EGL_NO_DISPLAY) { 3845d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new RuntimeException("eglGetDisplay failed " 3855d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(sEgl.eglGetError())); 386e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 387e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 388e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // We can now initialize EGL for that display 389e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int[] version = new int[2]; 390fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (!sEgl.eglInitialize(sEglDisplay, version)) { 3915d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new RuntimeException("eglInitialize failed " 3925d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(sEgl.eglGetError())); 393e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 394fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); 395e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 3962d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 397e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Create an EGL context. We want to do this as rarely as we can, because an 398e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * EGL context is a somewhat heavy object. 399e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 400fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEglContext = createContext(sEgl, sEglDisplay, sEglConfig); 401e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 402e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 403e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy GL createEglSurface(SurfaceHolder holder) { 404e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Check preconditions. 405fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEgl == null) { 406e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("egl not initialized"); 407e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 408fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglDisplay == null) { 409e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("eglDisplay not initialized"); 410e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 411fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEglConfig == null) { 412e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new RuntimeException("mEglConfig not initialized"); 413e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 414fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (Thread.currentThread() != sEglThread) { 415fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy throw new IllegalStateException("HardwareRenderer cannot be used " 416fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy + "from multiple threads"); 417fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 418e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 4192d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 420e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * The window size has changed, so we need to create a new 421e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * surface. 4222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 423e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { 424e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /* 425e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Unbind and destroy the old EGL surface, if 426e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * there is one. 427e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 428fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, 429e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 430fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 431e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 432e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 433e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy // Create an EGL surface we can render into. 434fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); 435e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 436e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 437fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy int error = sEgl.eglGetError(); 438e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { 4397d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); 440e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return null; 441e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 4425d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new RuntimeException("createWindowSurface failed " 4435d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(error)); 444e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 445e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 4462d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy /* 4472d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * Before we can issue GL commands, we need to make sure 4482d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy * the context is current and bound to a surface. 4492d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy */ 450fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { 4515d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new RuntimeException("eglMakeCurrent failed " 4525d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(sEgl.eglGetError())); 453e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 4547d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 4557d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (RENDER_DIRTY_REGIONS) { 4567d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (!GLES20Canvas.preserveBackBuffer()) { 4577d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Log.w(LOG_TAG, "Backbuffer cannot be preserved"); 4587d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 4597d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 460e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 461fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy return sEglContext.getGL(); 4622d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 4632d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 464e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { 465e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL10.EGL_NONE }; 466e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 467e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, 468e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGlVersion != 0 ? attrib_list : null); 469e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 470e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 471e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 472e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 473e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy SurfaceHolder holder) { 474e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (isRequested()) { 475b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy checkEglErrors(); 476e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy super.initializeIfNeeded(width, height, attachInfo, holder); 477e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 478e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 479e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 4802d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 4814caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy void destroy(boolean full) { 4824caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy if (full && mCanvas != null) { 4834caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy mCanvas = null; 4844caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy } 4854caa4ed120a86e855d4d3b6b455c6fb9ca22e365Romain Guy 486fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (!isEnabled() || mDestroyed) return; 487fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 488fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mDestroyed = true; 489e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 490fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, 4912d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 492fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglDestroySurface(sEglDisplay, mEglSurface); 4932d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 4942d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy mEglSurface = null; 495e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGl = null; 496fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 4972d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy setEnabled(false); 498fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 499fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 5002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 501fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy void setup(int width, int height) { 502fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy mCanvas.setViewport(width, height); 503e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 5047d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 505e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy boolean canDraw() { 506e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mGl != null && mCanvas != null; 507e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 508e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 5097d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void onPreDraw(Rect dirty) { 510e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 511e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 512b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 513b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 514b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy 515e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 516d10cd5765a2b706fc174f16b951d6b0a5d3740d3Romain Guy * Defines the EGL configuration for this renderer. 517e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * 518e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. 519e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 520e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EglConfigChooser getConfigChooser(int glVersion) { 521fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0); 5222d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5232d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy 5242d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 5257d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, 5267d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy Rect dirty) { 527e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (canDraw()) { 5287d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy //noinspection PointlessBooleanExpression,ConstantConditions 5297d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 5307d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy dirty = null; 5317d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 5327d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 5332d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy attachInfo.mDrawingTime = SystemClock.uptimeMillis(); 5342d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy attachInfo.mIgnoreDirtyState = true; 5352d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy view.mPrivateFlags |= View.DRAWN; 5369a40babc62416259d18783ce8c03c00042ec317bRomain Guy 5379a40babc62416259d18783ce8c03c00042ec317bRomain Guy long startTime; 5389a40babc62416259d18783ce8c03c00042ec317bRomain Guy if (ViewDebug.DEBUG_PROFILE_DRAWING) { 5399a40babc62416259d18783ce8c03c00042ec317bRomain Guy startTime = SystemClock.elapsedRealtime(); 5409a40babc62416259d18783ce8c03c00042ec317bRomain Guy } 541e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 542d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy final int surfaceState = checkCurrent(); 543d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState != SURFACE_STATE_ERROR) { 544d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy // We had to change the current surface and/or context, redraw everything 545d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy if (surfaceState == SURFACE_STATE_UPDATED) { 546d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy dirty = null; 547d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } 548d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 5497d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy onPreDraw(dirty); 55062687ec12cb8e0b1d4044a235b1387b9a8c3b4b4Romain Guy 551daf98e941e140e8739458126640183b9f296a2abChet Haase HardwareCanvas canvas = mCanvas; 552daf98e941e140e8739458126640183b9f296a2abChet Haase attachInfo.mHardwareCanvas = canvas; 5537d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 554b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy int saveCount = canvas.save(); 555b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy callbacks.onHardwarePreDraw(canvas); 556daf98e941e140e8739458126640183b9f296a2abChet Haase 557b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 558daf98e941e140e8739458126640183b9f296a2abChet Haase view.mRecreateDisplayList = 559daf98e941e140e8739458126640183b9f296a2abChet Haase (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED; 560daf98e941e140e8739458126640183b9f296a2abChet Haase view.mPrivateFlags &= ~View.INVALIDATED; 5617d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 562daf98e941e140e8739458126640183b9f296a2abChet Haase DisplayList displayList = view.getDisplayList(); 563daf98e941e140e8739458126640183b9f296a2abChet Haase if (displayList != null) { 564daf98e941e140e8739458126640183b9f296a2abChet Haase if (canvas.drawDisplayList(displayList)) { 565daf98e941e140e8739458126640183b9f296a2abChet Haase view.invalidate(); 566daf98e941e140e8739458126640183b9f296a2abChet Haase } 567daf98e941e140e8739458126640183b9f296a2abChet Haase } else { 568daf98e941e140e8739458126640183b9f296a2abChet Haase // Shouldn't reach here 569daf98e941e140e8739458126640183b9f296a2abChet Haase view.draw(canvas); 570daf98e941e140e8739458126640183b9f296a2abChet Haase } 5717d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy 5727d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (DEBUG_DIRTY_REGION) { 5737d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (mDebugPaint == null) { 5747d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint = new Paint(); 5757d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mDebugPaint.setColor(0x7fff0000); 5767d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 5777d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (dirty != null && (mFrameCount++ & 1) == 0) { 5787d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy canvas.drawRect(dirty, mDebugPaint); 5797d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 5807d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 581b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } finally { 582b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy callbacks.onHardwarePostDraw(canvas); 583b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy canvas.restoreToCount(saveCount); 584daf98e941e140e8739458126640183b9f296a2abChet Haase view.mRecreateDisplayList = false; 585b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 586daf98e941e140e8739458126640183b9f296a2abChet Haase 587b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy onPostDraw(); 588daf98e941e140e8739458126640183b9f296a2abChet Haase 589b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy if (ViewDebug.DEBUG_PROFILE_DRAWING) { 590b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime); 591b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 592b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy 593b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy attachInfo.mIgnoreDirtyState = false; 594b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy 595b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); 596b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy checkEglErrors(); 5979a40babc62416259d18783ce8c03c00042ec317bRomain Guy } 5982d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 5992d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 600d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy 601d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy private int checkCurrent() { 602fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy // TODO: Don't check the current context when we have one per UI thread 603fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy // TODO: Use a threadlocal flag to know whether the surface has changed 604fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (sEgl.eglGetCurrentContext() != sEglContext || 605fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { 606fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { 6079745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy fallback(true); 6089745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy Log.e(LOG_TAG, "eglMakeCurrent failed " + 6099745fae73b584f3e9a9c304098ed9b11f506e93bRomain Guy getEGLErrorString(sEgl.eglGetError())); 610d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_ERROR; 611d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy } else { 612d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_UPDATED; 613fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 614fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 615d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy return SURFACE_STATE_SUCCESS; 616fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 617fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 618e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static abstract class EglConfigChooser { 619e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy final int[] mConfigSpec; 620e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private final int mGlVersion; 621e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 622e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EglConfigChooser(int glVersion, int[] configSpec) { 623e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGlVersion = glVersion; 624e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mConfigSpec = filterConfigSpec(configSpec); 625e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 626e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 627e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { 628f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy int[] index = new int[1]; 629f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, index)) { 6305d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new IllegalArgumentException("eglChooseConfig failed " 6315d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(egl.eglGetError())); 632e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 633e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 634f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy int numConfigs = index[0]; 635e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (numConfigs <= 0) { 636f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy throw new IllegalArgumentException("No configs match configSpec"); 637e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 638e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 639e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLConfig[] configs = new EGLConfig[numConfigs]; 640f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, index)) { 6415d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd throw new IllegalArgumentException("eglChooseConfig failed " 6425d3e2ea6f3a02b5bd073887eabfa4f50a59bbcf0Mike Dodd + getEGLErrorString(egl.eglGetError())); 643e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 644f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 645e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLConfig config = chooseConfig(egl, display, configs); 646e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (config == null) { 647e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy throw new IllegalArgumentException("No config chosen"); 648e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 649f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy 650e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return config; 651e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 652e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 653f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs); 654e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 655e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int[] filterConfigSpec(int[] configSpec) { 656e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (mGlVersion != 2) { 657e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return configSpec; 658e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 659e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /* We know none of the subclasses define EGL_RENDERABLE_TYPE. 660e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * And we know the configSpec is well formed. 661e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 662e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int len = configSpec.length; 663e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int[] newConfigSpec = new int[len + 2]; 664f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1); 665f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE; 666e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ 667f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy newConfigSpec[len + 1] = EGL10.EGL_NONE; 668e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return newConfigSpec; 669e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 670e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 671e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 672e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 673e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Choose a configuration with exactly the specified r,g,b,a sizes, 674e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * and at least the specified depth and stencil sizes. 675e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 676e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static class ComponentSizeChooser extends EglConfigChooser { 677e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int[] mValue; 678e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 679e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mRedSize; 680e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mGreenSize; 681e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mBlueSize; 682e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mAlphaSize; 683e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mDepthSize; 684e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy private int mStencilSize; 685e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 686e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize, 687e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int alphaSize, int depthSize, int stencilSize) { 688d88f54c5c4ce59585b8b9e6009836f14c00be743Romain Guy //noinspection PointlessBitwiseExpression 689e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy super(glVersion, new int[] { 690e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_RED_SIZE, redSize, 691e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_GREEN_SIZE, greenSize, 692e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_BLUE_SIZE, blueSize, 693e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_ALPHA_SIZE, alphaSize, 694e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_DEPTH_SIZE, depthSize, 695e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_STENCIL_SIZE, stencilSize, 6967d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | 6977d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy (RENDER_DIRTY_REGIONS ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0), 698e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGL10.EGL_NONE }); 699e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mValue = new int[1]; 700e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mRedSize = redSize; 701e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mGreenSize = greenSize; 702e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mBlueSize = blueSize; 703e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mAlphaSize = alphaSize; 704e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mDepthSize = depthSize; 705e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy mStencilSize = stencilSize; 706e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 707e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 708e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy @Override 709e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { 710e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy for (EGLConfig config : configs) { 711e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0); 712e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0); 713f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (d >= mDepthSize && s >= mStencilSize) { 714e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0); 715e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0); 716e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); 717e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); 7187d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy boolean backBuffer; 7197d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (RENDER_DIRTY_REGIONS) { 7207d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy int surfaceType = findConfigAttrib(egl, display, config, 7217d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy EGL_SURFACE_TYPE, 0); 7227d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0; 7237d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } else { 7247d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy backBuffer = true; 7257d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy } 7267d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize 7277d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy && backBuffer) { 728e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return config; 729e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 730e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 731e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 732e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return null; 733e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 734e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 735f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, 736f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy int attribute, int defaultValue) { 737e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { 738e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return mValue[0]; 739e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 740e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 741e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy return defaultValue; 742e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 743f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy } 744e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 745fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 746e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy /** 747e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy * Hardware renderer using OpenGL ES 2.0. 748e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy */ 749e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy static class Gl20Renderer extends GlRenderer { 750e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy private GLES20Canvas mGlCanvas; 751e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 752e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy Gl20Renderer(boolean translucent) { 753e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy super(2, translucent); 754e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 755e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 7562d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy @Override 757fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy GLES20Canvas createCanvas() { 7586b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy return mGlCanvas = new GLES20Canvas(mTranslucent); 759e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy } 760b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy 761b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy @Override 762b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy boolean canDraw() { 763b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy return super.canDraw() && mGlCanvas != null; 764b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 765e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 766e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy @Override 7677d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy void onPreDraw(Rect dirty) { 7687d7b5490a0b0763e831b31bc11f17d8159b5914aRomain Guy mGlCanvas.onPreDraw(dirty); 769e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy } 770e3924992733234fd7d7a614c165a94e0a2cd6b84Romain Guy 771b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy @Override 772b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy void onPostDraw() { 773b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy mGlCanvas.onPostDraw(); 774b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy } 775b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy 776b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy @Override 77767f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy void destroy(boolean full) { 778b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy try { 779b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy super.destroy(full); 780b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } finally { 781b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy if (full && mGlCanvas != null) { 782b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy mGlCanvas = null; 783b8c0de2c2726f4e8f0029710047efe0c8e6661edRomain Guy } 78467f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 78567f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy } 78667f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy 78767f27952c1bcb2230beef9b5ca0bf42edad436a9Romain Guy @Override 788daf98e941e140e8739458126640183b9f296a2abChet Haase DisplayList createDisplayList(View v) { 789daf98e941e140e8739458126640183b9f296a2abChet Haase return new GLES20DisplayList(v); 790b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy } 7916c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 7926c319ca1275c8db892c39b48fc54864c949f9171Romain Guy @Override 7936c319ca1275c8db892c39b48fc54864c949f9171Romain Guy HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { 7946c319ca1275c8db892c39b48fc54864c949f9171Romain Guy return new GLES20Layer(width, height, isOpaque); 7956c319ca1275c8db892c39b48fc54864c949f9171Romain Guy } 796b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy 797163935113919a184122b8b3bd672ef08c8df65dcRomain Guy static HardwareRenderer create(boolean translucent) { 798163935113919a184122b8b3bd672ef08c8df65dcRomain Guy if (GLES20Canvas.isAvailable()) { 799163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return new Gl20Renderer(translucent); 8002d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 801163935113919a184122b8b3bd672ef08c8df65dcRomain Guy return null; 8022d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 8032d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy } 8042d6145993e19d2bb664766dbaf3c1e9ad3d12cdcRomain Guy} 805