Loading api/current.xml +15 −4 Original line number Diff line number Diff line Loading @@ -65146,7 +65146,7 @@ type="android.graphics.Canvas" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="gl" type="javax.microedition.khronos.opengles.GL"> Loading Loading @@ -66075,7 +66075,7 @@ synchronized="false" static="true" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > </method> Loading Loading @@ -66132,7 +66132,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > </method> Loading Loading @@ -66193,6 +66193,17 @@ visibility="public" > </method> <method name="isHardwareAccelerated" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="isOpaque" return="boolean" abstract="false" Loading Loading @@ -66506,7 +66517,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="width" type="int"> core/java/android/view/HardwareRenderer.java 0 → 100644 +341 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view; import android.content.res.CompatibilityInfo; import android.graphics.Canvas; import android.os.SystemClock; import android.util.DisplayMetrics; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL11; import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT; import static javax.microedition.khronos.opengles.GL10.GL_SCISSOR_TEST; /** * Interface for rendering a ViewRoot using hardware acceleration. * * @hide */ abstract class HardwareRenderer { private boolean mEnabled; private boolean mRequested = true; /** * Destroys the hardware rendering context. */ abstract void destroy(); /** * Initializes the hardware renderer for the specified surface. * * @param holder The holder for the surface to hardware accelerate. * * @return True if the initialization was successful, false otherwise. */ abstract boolean initialize(SurfaceHolder holder); /** * Setup the hardware renderer for drawing. This is called for every * frame to draw. * * @param width Width of the drawing surface. * @param height Height of the drawing surface. * @param attachInfo The AttachInfo used to render the ViewRoot. */ abstract void setup(int width, int height, View.AttachInfo attachInfo); /** * Draws the specified view. * * @param view The view to draw. * @param attachInfo AttachInfo tied to the specified view. * @param translator Translator used to draw applications in compatibility mode. * @param yoff The vertical offset for the drawing. * @param scalingRequired Whether drawing should be scaled. */ abstract void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired); /** * Initializes the hardware renderer for the specified surface and setup the * renderer for drawing, if needed. This is invoked when the ViewRoot has * potentially lost the hardware renderer. The hardware renderer should be * reinitialized and setup when the render {@link #isRequested()} and * {@link #isEnabled()}. * * @param width The width of the drawing surface. * @param height The height of the drawing surface. * @param attachInfo The * @param holder */ void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { // We lost the gl context, so recreate it. if (!isEnabled()) { if (initialize(holder)) { setup(width, height, attachInfo); } } } } /** * Creates a hardware renderer using OpenGL. * * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.) * * @return A hardware renderer backed by OpenGL. */ static HardwareRenderer createGlRenderer(int glVersion) { switch (glVersion) { case 1: return new Gl10Renderer(); } throw new IllegalArgumentException("Unknown GL version: " + glVersion); } /** * Indicates whether hardware acceleration is currently enabled. * * @return True if hardware acceleration is in use, false otherwise. */ boolean isEnabled() { return mEnabled; } /** * Indicates whether hardware acceleration is currently enabled. * * @param enabled True if the hardware renderer is in use, false otherwise. */ void setEnabled(boolean enabled) { mEnabled = enabled; } /** * Indicates whether hardware acceleration is currently request but not * necessarily enabled yet. * * @return True if requested, false otherwise. */ boolean isRequested() { return mRequested; } /** * Indicates whether hardware acceleration is currently request but not * necessarily enabled yet. * * @return True to request hardware acceleration, false otherwise. */ void setRequested(boolean requested) { mRequested = requested; } /** * Hardware renderer using OpenGL ES 1.0. */ @SuppressWarnings({"deprecation"}) static class Gl10Renderer extends HardwareRenderer { private EGL10 mEgl; private EGLDisplay mEglDisplay; private EGLContext mEglContext; private EGLSurface mEglSurface; private GL11 mGL; private Canvas mGlCanvas; private Gl10Renderer() { } private void initializeGL(SurfaceHolder holder) { initializeGLInner(holder); int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroy(); setRequested(false); } } private void initializeGLInner(SurfaceHolder holder) { final EGL10 egl = (EGL10) EGLContext.getEGL(); mEgl = egl; final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); mEglDisplay = eglDisplay; int[] version = new int[2]; egl.eglInitialize(eglDisplay, version); final int[] configSpec = { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0, EGL10.EGL_NONE }; final EGLConfig[] configs = new EGLConfig[1]; final int[] numConfig = new int[1]; egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig); final EGLConfig config = configs[0]; /* * Create an OpenGL ES context. This must be done only once, an * OpenGL context is a somewhat heavy object. */ final EGLContext context = egl.eglCreateContext(eglDisplay, config, EGL10.EGL_NO_CONTEXT, null); mEglContext = context; /* * Create an EGL surface we can render into. */ EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, holder, null); mEglSurface = surface; /* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ egl.eglMakeCurrent(eglDisplay, surface, surface, context); /* * Get to the appropriate GL interface. * This is simply done by casting the GL context to either * GL10 or GL11. */ final GL11 gl = (GL11) context.getGL(); mGL = gl; mGlCanvas = new Canvas(gl); setEnabled(true); } @Override void destroy() { if (!isEnabled()) return; // inform skia that the context is gone nativeAbandonGlCaches(); mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGlCanvas = null; mGL = null; setEnabled(false); } private void checkErrors() { if (isEnabled()) { int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. destroy(); if (err != EGL11.EGL_CONTEXT_LOST) { // we'll try again if it was context lost setRequested(false); } } } } @Override boolean initialize(SurfaceHolder holder) { if (isRequested() && !isEnabled()) { initializeGL(holder); return mGlCanvas != null; } return false; } @Override void setup(int width, int height, View.AttachInfo attachInfo) { final float scale = attachInfo.mApplicationScale; mGlCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f)); } @Override void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired) { Canvas canvas = mGlCanvas; if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); attachInfo.mDrawingTime = SystemClock.uptimeMillis(); attachInfo.mIgnoreDirtyState = true; view.mPrivateFlags |= View.DRAWN; int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); if (translator != null) { translator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); view.draw(canvas); } finally { canvas.restoreToCount(saveCount); } attachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkErrors(); } } @Override void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { checkErrors(); super.initializeIfNeeded(width, height, attachInfo, holder); } } } // inform Skia to just abandon its texture cache IDs // doesn't call glDeleteTextures private static native void nativeAbandonGlCaches(); } core/java/android/view/ViewGroup.java +1 −1 Original line number Diff line number Diff line Loading @@ -1566,7 +1566,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean scalingRequired = false; Bitmap cache = null; if (canvas.getGL() == null && if (!canvas.isHardwareAccelerated() && (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE || (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) { cache = child.getDrawingCache(true); Loading core/java/android/view/ViewRoot.java +9 −194 Original line number Diff line number Diff line Loading @@ -56,10 +56,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import javax.microedition.khronos.egl.*; import javax.microedition.khronos.opengles.*; import static javax.microedition.khronos.opengles.GL10.*; /** * The top of a view hierarchy, implementing the needed protocol between View * and the WindowManager. This is for the most part an internal implementation Loading Loading @@ -264,9 +260,8 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mDensity = context.getResources().getDisplayMetrics().densityDpi; // Try to enable hardware acceleration if requested if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { mHwRenderer = new HardwareRenderer(); if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { mHwRenderer = HardwareRenderer.createGlRenderer(1); } } Loading Loading @@ -615,8 +610,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn boolean viewVisibilityChanged = mViewVisibility != viewVisibility || mNewSurfaceNeeded; float appScale = mAttachInfo.mApplicationScale; WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; Loading Loading @@ -665,7 +658,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn host.dispatchWindowVisibilityChanged(viewVisibility); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { if (mHwRenderer != null) { mHwRenderer.destroyGL(); mHwRenderer.destroy(); } } if (viewVisibility == View.GONE) { Loading Loading @@ -873,7 +866,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mPreviousTransparentRegion.setEmpty(); if (mHwRenderer != null) { hwIntialized = mHwRenderer.initialize(); hwIntialized = mHwRenderer.initialize(mHolder); } } } else if (!mSurface.isValid()) { Loading Loading @@ -952,7 +945,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } if (hwIntialized) { mHwRenderer.setup(appScale); mHwRenderer.setup(mWidth, mHeight, mAttachInfo); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( Loading Loading @@ -1248,9 +1241,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn return; } if (mHwRenderer != null && mHwRenderer.mEnabled) { if (mHwRenderer != null && mHwRenderer.isEnabled()) { if (!dirty.isEmpty()) { mHwRenderer.draw(yoff, scalingRequired); mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, scalingRequired); } if (scrolling) { Loading Loading @@ -1578,7 +1571,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mAttachInfo.mSurface = null; if (mHwRenderer != null) { mHwRenderer.destroyGL(); mHwRenderer.destroy(); } mSurface.release(); Loading Loading @@ -1842,7 +1835,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn ensureTouchModeLocally(inTouchMode); if (mHwRenderer != null) { mHwRenderer.initializeAndSetup(); mHwRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mHolder); } } Loading Loading @@ -3313,183 +3306,5 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } } class HardwareRenderer { private EGL10 mEgl; private EGLDisplay mEglDisplay; private EGLContext mEglContext; private EGLSurface mEglSurface; private GL11 mGL; private Canvas mGlCanvas; boolean mEnabled; boolean mRequested = true; private void initializeGL() { initializeGLInner(); int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroyGL(); mRequested = false; } } private void initializeGLInner() { final EGL10 egl = (EGL10) EGLContext.getEGL(); mEgl = egl; final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); mEglDisplay = eglDisplay; int[] version = new int[2]; egl.eglInitialize(eglDisplay, version); final int[] configSpec = { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0, EGL10.EGL_NONE }; final EGLConfig[] configs = new EGLConfig[1]; final int[] numConfig = new int[1]; egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig); final EGLConfig config = configs[0]; /* * Create an OpenGL ES context. This must be done only once, an * OpenGL context is a somewhat heavy object. */ final EGLContext context = egl.eglCreateContext(eglDisplay, config, EGL10.EGL_NO_CONTEXT, null); mEglContext = context; /* * Create an EGL surface we can render into. */ EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null); mEglSurface = surface; /* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ egl.eglMakeCurrent(eglDisplay, surface, surface, context); /* * Get to the appropriate GL interface. * This is simply done by casting the GL context to either * GL10 or GL11. */ final GL11 gl = (GL11) context.getGL(); mGL = gl; mGlCanvas = new Canvas(gl); mEnabled = true; } void destroyGL() { if (!mEnabled) return; // inform skia that the context is gone nativeAbandonGlCaches(); mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGlCanvas = null; mGL = null; mEnabled = false; } private void checkErrors() { if (mEnabled) { int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. destroyGL(); if (err != EGL11.EGL_CONTEXT_LOST) { // we'll try again if it was context lost mRequested = false; } } } } boolean initialize() { if (mRequested && !mEnabled) { initializeGL(); return mGlCanvas != null; } return false; } void setup(float appScale) { mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } void draw(int yoff, boolean scalingRequired) { Canvas canvas = mGlCanvas; if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); mAttachInfo.mIgnoreDirtyState = true; mView.mPrivateFlags |= View.DRAWN; int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); if (mTranslator != null) { mTranslator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); mView.draw(canvas); } finally { canvas.restoreToCount(saveCount); } mAttachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkErrors(); } } void initializeAndSetup() { if (mRequested) { checkErrors(); // we lost the gl context, so recreate it. if (mRequested && !mEnabled) { initializeGL(); if (mGlCanvas != null) { float appScale = mAttachInfo.mApplicationScale; mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } } } } } private static native void nativeShowFPS(Canvas canvas, int durationMillis); // inform skia to just abandon its texture cache IDs // doesn't call glDeleteTextures private static native void nativeAbandonGlCaches(); } core/jni/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -131,7 +131,8 @@ LOCAL_SRC_FILES:= \ android_backup_BackupDataInput.cpp \ android_backup_BackupDataOutput.cpp \ android_backup_FileBackupHelperBase.cpp \ android_backup_BackupHelperDispatcher.cpp android_backup_BackupHelperDispatcher.cpp \ android_view_HardwareRenderer.cpp \ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ Loading Loading
api/current.xml +15 −4 Original line number Diff line number Diff line Loading @@ -65146,7 +65146,7 @@ type="android.graphics.Canvas" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="gl" type="javax.microedition.khronos.opengles.GL"> Loading Loading @@ -66075,7 +66075,7 @@ synchronized="false" static="true" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > </method> Loading Loading @@ -66132,7 +66132,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > </method> Loading Loading @@ -66193,6 +66193,17 @@ visibility="public" > </method> <method name="isHardwareAccelerated" return="boolean" abstract="false" native="false" synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > </method> <method name="isOpaque" return="boolean" abstract="false" Loading Loading @@ -66506,7 +66517,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="width" type="int">
core/java/android/view/HardwareRenderer.java 0 → 100644 +341 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view; import android.content.res.CompatibilityInfo; import android.graphics.Canvas; import android.os.SystemClock; import android.util.DisplayMetrics; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL11; import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT; import static javax.microedition.khronos.opengles.GL10.GL_SCISSOR_TEST; /** * Interface for rendering a ViewRoot using hardware acceleration. * * @hide */ abstract class HardwareRenderer { private boolean mEnabled; private boolean mRequested = true; /** * Destroys the hardware rendering context. */ abstract void destroy(); /** * Initializes the hardware renderer for the specified surface. * * @param holder The holder for the surface to hardware accelerate. * * @return True if the initialization was successful, false otherwise. */ abstract boolean initialize(SurfaceHolder holder); /** * Setup the hardware renderer for drawing. This is called for every * frame to draw. * * @param width Width of the drawing surface. * @param height Height of the drawing surface. * @param attachInfo The AttachInfo used to render the ViewRoot. */ abstract void setup(int width, int height, View.AttachInfo attachInfo); /** * Draws the specified view. * * @param view The view to draw. * @param attachInfo AttachInfo tied to the specified view. * @param translator Translator used to draw applications in compatibility mode. * @param yoff The vertical offset for the drawing. * @param scalingRequired Whether drawing should be scaled. */ abstract void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired); /** * Initializes the hardware renderer for the specified surface and setup the * renderer for drawing, if needed. This is invoked when the ViewRoot has * potentially lost the hardware renderer. The hardware renderer should be * reinitialized and setup when the render {@link #isRequested()} and * {@link #isEnabled()}. * * @param width The width of the drawing surface. * @param height The height of the drawing surface. * @param attachInfo The * @param holder */ void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { // We lost the gl context, so recreate it. if (!isEnabled()) { if (initialize(holder)) { setup(width, height, attachInfo); } } } } /** * Creates a hardware renderer using OpenGL. * * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.) * * @return A hardware renderer backed by OpenGL. */ static HardwareRenderer createGlRenderer(int glVersion) { switch (glVersion) { case 1: return new Gl10Renderer(); } throw new IllegalArgumentException("Unknown GL version: " + glVersion); } /** * Indicates whether hardware acceleration is currently enabled. * * @return True if hardware acceleration is in use, false otherwise. */ boolean isEnabled() { return mEnabled; } /** * Indicates whether hardware acceleration is currently enabled. * * @param enabled True if the hardware renderer is in use, false otherwise. */ void setEnabled(boolean enabled) { mEnabled = enabled; } /** * Indicates whether hardware acceleration is currently request but not * necessarily enabled yet. * * @return True if requested, false otherwise. */ boolean isRequested() { return mRequested; } /** * Indicates whether hardware acceleration is currently request but not * necessarily enabled yet. * * @return True to request hardware acceleration, false otherwise. */ void setRequested(boolean requested) { mRequested = requested; } /** * Hardware renderer using OpenGL ES 1.0. */ @SuppressWarnings({"deprecation"}) static class Gl10Renderer extends HardwareRenderer { private EGL10 mEgl; private EGLDisplay mEglDisplay; private EGLContext mEglContext; private EGLSurface mEglSurface; private GL11 mGL; private Canvas mGlCanvas; private Gl10Renderer() { } private void initializeGL(SurfaceHolder holder) { initializeGLInner(holder); int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroy(); setRequested(false); } } private void initializeGLInner(SurfaceHolder holder) { final EGL10 egl = (EGL10) EGLContext.getEGL(); mEgl = egl; final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); mEglDisplay = eglDisplay; int[] version = new int[2]; egl.eglInitialize(eglDisplay, version); final int[] configSpec = { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0, EGL10.EGL_NONE }; final EGLConfig[] configs = new EGLConfig[1]; final int[] numConfig = new int[1]; egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig); final EGLConfig config = configs[0]; /* * Create an OpenGL ES context. This must be done only once, an * OpenGL context is a somewhat heavy object. */ final EGLContext context = egl.eglCreateContext(eglDisplay, config, EGL10.EGL_NO_CONTEXT, null); mEglContext = context; /* * Create an EGL surface we can render into. */ EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, holder, null); mEglSurface = surface; /* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ egl.eglMakeCurrent(eglDisplay, surface, surface, context); /* * Get to the appropriate GL interface. * This is simply done by casting the GL context to either * GL10 or GL11. */ final GL11 gl = (GL11) context.getGL(); mGL = gl; mGlCanvas = new Canvas(gl); setEnabled(true); } @Override void destroy() { if (!isEnabled()) return; // inform skia that the context is gone nativeAbandonGlCaches(); mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGlCanvas = null; mGL = null; setEnabled(false); } private void checkErrors() { if (isEnabled()) { int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. destroy(); if (err != EGL11.EGL_CONTEXT_LOST) { // we'll try again if it was context lost setRequested(false); } } } } @Override boolean initialize(SurfaceHolder holder) { if (isRequested() && !isEnabled()) { initializeGL(holder); return mGlCanvas != null; } return false; } @Override void setup(int width, int height, View.AttachInfo attachInfo) { final float scale = attachInfo.mApplicationScale; mGlCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f)); } @Override void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired) { Canvas canvas = mGlCanvas; if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); attachInfo.mDrawingTime = SystemClock.uptimeMillis(); attachInfo.mIgnoreDirtyState = true; view.mPrivateFlags |= View.DRAWN; int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); if (translator != null) { translator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); view.draw(canvas); } finally { canvas.restoreToCount(saveCount); } attachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkErrors(); } } @Override void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { checkErrors(); super.initializeIfNeeded(width, height, attachInfo, holder); } } } // inform Skia to just abandon its texture cache IDs // doesn't call glDeleteTextures private static native void nativeAbandonGlCaches(); }
core/java/android/view/ViewGroup.java +1 −1 Original line number Diff line number Diff line Loading @@ -1566,7 +1566,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean scalingRequired = false; Bitmap cache = null; if (canvas.getGL() == null && if (!canvas.isHardwareAccelerated() && (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE || (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) { cache = child.getDrawingCache(true); Loading
core/java/android/view/ViewRoot.java +9 −194 Original line number Diff line number Diff line Loading @@ -56,10 +56,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import javax.microedition.khronos.egl.*; import javax.microedition.khronos.opengles.*; import static javax.microedition.khronos.opengles.GL10.*; /** * The top of a view hierarchy, implementing the needed protocol between View * and the WindowManager. This is for the most part an internal implementation Loading Loading @@ -264,9 +260,8 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mDensity = context.getResources().getDisplayMetrics().densityDpi; // Try to enable hardware acceleration if requested if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { mHwRenderer = new HardwareRenderer(); if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { mHwRenderer = HardwareRenderer.createGlRenderer(1); } } Loading Loading @@ -615,8 +610,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn boolean viewVisibilityChanged = mViewVisibility != viewVisibility || mNewSurfaceNeeded; float appScale = mAttachInfo.mApplicationScale; WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; Loading Loading @@ -665,7 +658,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn host.dispatchWindowVisibilityChanged(viewVisibility); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { if (mHwRenderer != null) { mHwRenderer.destroyGL(); mHwRenderer.destroy(); } } if (viewVisibility == View.GONE) { Loading Loading @@ -873,7 +866,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mPreviousTransparentRegion.setEmpty(); if (mHwRenderer != null) { hwIntialized = mHwRenderer.initialize(); hwIntialized = mHwRenderer.initialize(mHolder); } } } else if (!mSurface.isValid()) { Loading Loading @@ -952,7 +945,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } if (hwIntialized) { mHwRenderer.setup(appScale); mHwRenderer.setup(mWidth, mHeight, mAttachInfo); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( Loading Loading @@ -1248,9 +1241,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn return; } if (mHwRenderer != null && mHwRenderer.mEnabled) { if (mHwRenderer != null && mHwRenderer.isEnabled()) { if (!dirty.isEmpty()) { mHwRenderer.draw(yoff, scalingRequired); mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, scalingRequired); } if (scrolling) { Loading Loading @@ -1578,7 +1571,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mAttachInfo.mSurface = null; if (mHwRenderer != null) { mHwRenderer.destroyGL(); mHwRenderer.destroy(); } mSurface.release(); Loading Loading @@ -1842,7 +1835,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn ensureTouchModeLocally(inTouchMode); if (mHwRenderer != null) { mHwRenderer.initializeAndSetup(); mHwRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mHolder); } } Loading Loading @@ -3313,183 +3306,5 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } } class HardwareRenderer { private EGL10 mEgl; private EGLDisplay mEglDisplay; private EGLContext mEglContext; private EGLSurface mEglSurface; private GL11 mGL; private Canvas mGlCanvas; boolean mEnabled; boolean mRequested = true; private void initializeGL() { initializeGLInner(); int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroyGL(); mRequested = false; } } private void initializeGLInner() { final EGL10 egl = (EGL10) EGLContext.getEGL(); mEgl = egl; final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); mEglDisplay = eglDisplay; int[] version = new int[2]; egl.eglInitialize(eglDisplay, version); final int[] configSpec = { EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0, EGL10.EGL_NONE }; final EGLConfig[] configs = new EGLConfig[1]; final int[] numConfig = new int[1]; egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig); final EGLConfig config = configs[0]; /* * Create an OpenGL ES context. This must be done only once, an * OpenGL context is a somewhat heavy object. */ final EGLContext context = egl.eglCreateContext(eglDisplay, config, EGL10.EGL_NO_CONTEXT, null); mEglContext = context; /* * Create an EGL surface we can render into. */ EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null); mEglSurface = surface; /* * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ egl.eglMakeCurrent(eglDisplay, surface, surface, context); /* * Get to the appropriate GL interface. * This is simply done by casting the GL context to either * GL10 or GL11. */ final GL11 gl = (GL11) context.getGL(); mGL = gl; mGlCanvas = new Canvas(gl); mEnabled = true; } void destroyGL() { if (!mEnabled) return; // inform skia that the context is gone nativeAbandonGlCaches(); mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGlCanvas = null; mGL = null; mEnabled = false; } private void checkErrors() { if (mEnabled) { int err = mEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. destroyGL(); if (err != EGL11.EGL_CONTEXT_LOST) { // we'll try again if it was context lost mRequested = false; } } } } boolean initialize() { if (mRequested && !mEnabled) { initializeGL(); return mGlCanvas != null; } return false; } void setup(float appScale) { mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } void draw(int yoff, boolean scalingRequired) { Canvas canvas = mGlCanvas; if (mGL != null && canvas != null) { mGL.glDisable(GL_SCISSOR_TEST); mGL.glClearColor(0, 0, 0, 0); mGL.glClear(GL_COLOR_BUFFER_BIT); mGL.glEnable(GL_SCISSOR_TEST); mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); mAttachInfo.mIgnoreDirtyState = true; mView.mPrivateFlags |= View.DRAWN; int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { canvas.translate(0, -yoff); if (mTranslator != null) { mTranslator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); mView.draw(canvas); } finally { canvas.restoreToCount(saveCount); } mAttachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkErrors(); } } void initializeAndSetup() { if (mRequested) { checkErrors(); // we lost the gl context, so recreate it. if (mRequested && !mEnabled) { initializeGL(); if (mGlCanvas != null) { float appScale = mAttachInfo.mApplicationScale; mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } } } } } private static native void nativeShowFPS(Canvas canvas, int durationMillis); // inform skia to just abandon its texture cache IDs // doesn't call glDeleteTextures private static native void nativeAbandonGlCaches(); }
core/jni/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -131,7 +131,8 @@ LOCAL_SRC_FILES:= \ android_backup_BackupDataInput.cpp \ android_backup_BackupDataOutput.cpp \ android_backup_FileBackupHelperBase.cpp \ android_backup_BackupHelperDispatcher.cpp android_backup_BackupHelperDispatcher.cpp \ android_view_HardwareRenderer.cpp \ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ Loading