Loading core/java/android/view/GLES20Canvas.java +16 −7 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ class GLES20Canvas extends Canvas { @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private final GL mGl; private final boolean mOpaque; private final int mRenderer; private int mRenderer; private int mWidth; private int mHeight; Loading Loading @@ -76,16 +76,25 @@ class GLES20Canvas extends Canvas { mOpaque = !translucent; mRenderer = nCreateRenderer(); if (mRenderer == 0) { throw new IllegalStateException("Could not create GLES20Canvas renderer"); } } private native int nCreateRenderer(); @Override protected void finalize() throws Throwable { try { super.finalize(); } finally { /** * This method <strong>must</strong> be called before releasing a * reference to a GLES20Canvas. This method is responsible for freeing * native resources associated with the hardware. Not invoking this * method properly can result in memory leaks. * * @hide */ public synchronized void destroy() { if (mRenderer != 0) { nDestroyRenderer(mRenderer); mRenderer = 0; } } Loading core/java/android/view/HardwareRenderer.java +89 −59 Original line number Diff line number Diff line Loading @@ -35,9 +35,10 @@ import javax.microedition.khronos.opengles.GL; * @hide */ public abstract class HardwareRenderer { private static final String LOG_TAG = "HardwareRenderer"; private boolean mEnabled; private boolean mRequested = true; private static final String LOG_TAG = "HardwareRenderer"; /** * Indicates whether hardware acceleration is available under any form for Loading Loading @@ -70,9 +71,8 @@ public abstract class HardwareRenderer { * * @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); abstract void setup(int width, int height); /** * Draws the specified view. Loading @@ -96,12 +96,11 @@ public abstract class HardwareRenderer { */ 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); setup(width, height); } } } Loading Loading @@ -165,18 +164,23 @@ public abstract class HardwareRenderer { static abstract class GlRenderer extends HardwareRenderer { private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; EGL10 mEgl; EGLDisplay mEglDisplay; EGLContext mEglContext; static EGLContext sEglContext; static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; private static Thread sEglThread; EGLSurface mEglSurface; EGLConfig mEglConfig; GL mGl; Canvas mCanvas; GLES20Canvas mCanvas; final int mGlVersion; final boolean mTranslucent; private boolean mDestroyed; GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mTranslucent = translucent; Loading @@ -189,7 +193,7 @@ public abstract class HardwareRenderer { */ void checkErrors() { if (isEnabled()) { int error = mEgl.eglGetError(); int error = sEgl.eglGetError(); if (error != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. Loading @@ -208,13 +212,17 @@ public abstract class HardwareRenderer { if (isRequested() && !isEnabled()) { initializeEgl(); mGl = createEglSurface(holder); mDestroyed = false; if (mGl != null) { int err = mEgl.eglGetError(); int err = sEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroy(); setRequested(false); } else { if (mCanvas != null) { destroyCanvas(); } mCanvas = createCanvas(); if (mCanvas != null) { setEnabled(true); Loading @@ -229,64 +237,75 @@ public abstract class HardwareRenderer { return false; } abstract Canvas createCanvas(); private void destroyCanvas() { mCanvas.destroy(); mCanvas = null; } abstract GLES20Canvas createCanvas(); void initializeEgl() { mEgl = (EGL10) EGLContext.getEGL(); if (sEglContext != null) return; sEglThread = Thread.currentThread(); sEgl = (EGL10) EGLContext.getEGL(); // Get to the default display. mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { if (sEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed"); } // We can now initialize EGL for that display int[] version = new int[2]; if (!mEgl.eglInitialize(mEglDisplay, version)) { if (!sEgl.eglInitialize(sEglDisplay, version)) { throw new RuntimeException("eglInitialize failed"); } mEglConfig = getConfigChooser(mGlVersion).chooseConfig(mEgl, mEglDisplay); sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); /* * Create an EGL context. We want to do this as rarely as we can, because an * EGL context is a somewhat heavy object. */ mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); sEglContext = createContext(sEgl, sEglDisplay, sEglConfig); } GL createEglSurface(SurfaceHolder holder) { // Check preconditions. if (mEgl == null) { if (sEgl == null) { throw new RuntimeException("egl not initialized"); } if (mEglDisplay == null) { if (sEglDisplay == null) { throw new RuntimeException("eglDisplay not initialized"); } if (mEglConfig == null) { if (sEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); } if (Thread.currentThread() != sEglThread) { throw new IllegalStateException("HardwareRenderer cannot be used " + "from multiple threads"); } /* * The window size has changed, so we need to create a new * surface. */ if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { /* * Unbind and destroy the old EGL surface, if * there is one. */ mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); } // Create an EGL surface we can render into. mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, holder, null); mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { int error = mEgl.eglGetError(); int error = sEgl.eglGetError(); if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); return null; Loading @@ -298,11 +317,11 @@ public abstract class HardwareRenderer { * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } return mEglContext.getGL(); return sEglContext.getGL(); } EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { Loading @@ -315,7 +334,6 @@ public abstract class HardwareRenderer { @Override void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { checkErrors(); super.initializeIfNeeded(width, height, attachInfo, holder); Loading @@ -324,28 +342,34 @@ public abstract class HardwareRenderer { @Override void destroy() { if (!isEnabled()) return; if (!isEnabled() || mDestroyed) return; mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, mDestroyed = true; checkCurrent(); // Destroy the Canvas first in case it needs to use a GL context // to perform its cleanup. destroyCanvas(); sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGl = null; mCanvas = null; // mEgl.eglDestroyContext(mEglDisplay, mEglContext); // mEglContext = null; // mEgl.eglTerminate(mEglDisplay); // mEgl = null; // mEglDisplay = null; setEnabled(false); } @Override void setup(int width, int height, View.AttachInfo attachInfo) { final float scale = attachInfo.mApplicationScale; mCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f)); void setup(int width, int height) { mCanvas.setViewport(width, height); } boolean canDraw() { Loading @@ -363,7 +387,8 @@ public abstract class HardwareRenderer { * @param glVersion */ EglConfigChooser getConfigChooser(int glVersion) { return new ComponentSizeChooser(glVersion, 8, 8, 8, mTranslucent ? 8 : 0, 0, 0); // TODO: Check for mTranslucent here, which means at least 2 EGL contexts return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0); } @Override Loading @@ -373,14 +398,7 @@ public abstract class HardwareRenderer { attachInfo.mIgnoreDirtyState = true; view.mPrivateFlags |= View.DRAWN; // TODO: Don't check the current context when we have one per UI thread // TODO: Use a threadlocal flag to know whether the surface has changed if (mEgl.eglGetCurrentContext() != mEglContext || mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } } checkCurrent(); onPreDraw(); Loading @@ -396,11 +414,22 @@ public abstract class HardwareRenderer { attachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); checkErrors(); } } private void checkCurrent() { // TODO: Don't check the current context when we have one per UI thread // TODO: Use a threadlocal flag to know whether the surface has changed if (sEgl.eglGetCurrentContext() != sEglContext || sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } } } static abstract class EglConfigChooser { final int[] mConfigSpec; private final int mGlVersion; Loading Loading @@ -496,7 +525,7 @@ public abstract class HardwareRenderer { int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0); int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); if (r == mRedSize && g == mGreenSize && b == mBlueSize && a >= mAlphaSize) { if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize) { return config; } } Loading Loading @@ -526,8 +555,9 @@ public abstract class HardwareRenderer { } @Override Canvas createCanvas() { return mGlCanvas = new GLES20Canvas(mGl, mTranslucent); GLES20Canvas createCanvas() { // TODO: Pass mTranslucent instead of true return mGlCanvas = new GLES20Canvas(mGl, true); } @Override Loading core/java/android/view/ViewRoot.java +17 −17 Original line number Diff line number Diff line Loading @@ -251,7 +251,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mTempRect = new Rect(); mVisRect = new Rect(); mWinFrame = new Rect(); mWindow = new W(this, context); mWindow = new W(this); mInputMethodCallback = new InputMethodCallback(this); mViewVisibility = View.GONE; mTransparentRegion = new Region(); Loading Loading @@ -469,6 +469,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn if (attrs != null && (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) { final boolean translucent = attrs.format != PixelFormat.OPAQUE; destroyHardwareRenderer(); mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent); } } Loading Loading @@ -677,9 +678,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn attachInfo.mWindowVisibility = viewVisibility; host.dispatchWindowVisibilityChanged(viewVisibility); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { if (mHwRenderer != null) { mHwRenderer.destroy(); } destroyHardwareRenderer(); } if (viewVisibility == View.GONE) { // After making a window gone, we will count it as being Loading Loading @@ -963,7 +962,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } if (hwIntialized) { mHwRenderer.setup(mWidth, mHeight, mAttachInfo); mHwRenderer.setup(mWidth, mHeight); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( Loading Loading @@ -1598,9 +1597,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mAttachInfo.mRootView = null; mAttachInfo.mSurface = null; if (mHwRenderer != null) { mHwRenderer.destroy(); } destroyHardwareRenderer(); mHwRenderer = null; mSurface.release(); if (mInputChannel != null) { Loading @@ -1625,6 +1624,12 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } } private void destroyHardwareRenderer() { if (mHwRenderer != null) { mHwRenderer.destroy(); } } void updateConfiguration(Configuration config, boolean force) { if (DEBUG_CONFIGURATION) Log.v(TAG, "Applying new config to window " Loading Loading @@ -2734,10 +2739,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn public void childDrawableStateChanged(View child) { } protected Rect getWindowFrame() { return mWinFrame; } void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( Loading Loading @@ -2816,16 +2817,15 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn static class W extends IWindow.Stub { private final WeakReference<ViewRoot> mViewRoot; public W(ViewRoot viewRoot, Context context) { W(ViewRoot viewRoot) { mViewRoot = new WeakReference<ViewRoot>(viewRoot); } public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw, Configuration newConfig) { public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw, Configuration newConfig) { final ViewRoot viewRoot = mViewRoot.get(); if (viewRoot != null) { viewRoot.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw, newConfig); viewRoot.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw, newConfig); } } Loading core/jni/android_view_GLES20Canvas.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ #include <SkiaShader.h> #include <SkiaColorFilter.h> #include <Rect.h> #include <ui/Rect.h> #include "TextLayout.h" Loading libs/hwui/Caches.h 0 → 100644 +75 −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. */ #ifndef ANDROID_UI_CACHES_H #define ANDROID_UI_CACHES_H #define LOG_TAG "OpenGLRenderer" #include <utils/Singleton.h> #include "TextureCache.h" #include "LayerCache.h" #include "GradientCache.h" #include "PatchCache.h" #include "FontRenderer.h" #include "ProgramCache.h" #include "PathCache.h" #include "TextDropShadowCache.h" namespace android { namespace uirenderer { struct CacheLogger { CacheLogger() { LOGD("Creating caches"); } }; // struct CacheLogger class Caches: public Singleton<Caches> { Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO), lastDstMode(GL_ZERO), currentProgram(NULL) { dropShadowCache.setFontRenderer(fontRenderer); } friend class Singleton<Caches>; CacheLogger logger; public: bool blend; GLenum lastSrcMode; GLenum lastDstMode; Program* currentProgram; TextureCache textureCache; LayerCache layerCache; GradientCache gradientCache; ProgramCache programCache; PathCache pathCache; PatchCache patchCache; TextDropShadowCache dropShadowCache; FontRenderer fontRenderer; }; // class Caches }; // namespace uirenderer using namespace uirenderer; ANDROID_SINGLETON_STATIC_INSTANCE(Caches); }; // namespace android #endif // ANDROID_UI_CACHES_H Loading
core/java/android/view/GLES20Canvas.java +16 −7 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ class GLES20Canvas extends Canvas { @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private final GL mGl; private final boolean mOpaque; private final int mRenderer; private int mRenderer; private int mWidth; private int mHeight; Loading Loading @@ -76,16 +76,25 @@ class GLES20Canvas extends Canvas { mOpaque = !translucent; mRenderer = nCreateRenderer(); if (mRenderer == 0) { throw new IllegalStateException("Could not create GLES20Canvas renderer"); } } private native int nCreateRenderer(); @Override protected void finalize() throws Throwable { try { super.finalize(); } finally { /** * This method <strong>must</strong> be called before releasing a * reference to a GLES20Canvas. This method is responsible for freeing * native resources associated with the hardware. Not invoking this * method properly can result in memory leaks. * * @hide */ public synchronized void destroy() { if (mRenderer != 0) { nDestroyRenderer(mRenderer); mRenderer = 0; } } Loading
core/java/android/view/HardwareRenderer.java +89 −59 Original line number Diff line number Diff line Loading @@ -35,9 +35,10 @@ import javax.microedition.khronos.opengles.GL; * @hide */ public abstract class HardwareRenderer { private static final String LOG_TAG = "HardwareRenderer"; private boolean mEnabled; private boolean mRequested = true; private static final String LOG_TAG = "HardwareRenderer"; /** * Indicates whether hardware acceleration is available under any form for Loading Loading @@ -70,9 +71,8 @@ public abstract class HardwareRenderer { * * @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); abstract void setup(int width, int height); /** * Draws the specified view. Loading @@ -96,12 +96,11 @@ public abstract class HardwareRenderer { */ 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); setup(width, height); } } } Loading Loading @@ -165,18 +164,23 @@ public abstract class HardwareRenderer { static abstract class GlRenderer extends HardwareRenderer { private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; EGL10 mEgl; EGLDisplay mEglDisplay; EGLContext mEglContext; static EGLContext sEglContext; static EGL10 sEgl; static EGLDisplay sEglDisplay; static EGLConfig sEglConfig; private static Thread sEglThread; EGLSurface mEglSurface; EGLConfig mEglConfig; GL mGl; Canvas mCanvas; GLES20Canvas mCanvas; final int mGlVersion; final boolean mTranslucent; private boolean mDestroyed; GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mTranslucent = translucent; Loading @@ -189,7 +193,7 @@ public abstract class HardwareRenderer { */ void checkErrors() { if (isEnabled()) { int error = mEgl.eglGetError(); int error = sEgl.eglGetError(); if (error != EGL10.EGL_SUCCESS) { // something bad has happened revert to // normal rendering. Loading @@ -208,13 +212,17 @@ public abstract class HardwareRenderer { if (isRequested() && !isEnabled()) { initializeEgl(); mGl = createEglSurface(holder); mDestroyed = false; if (mGl != null) { int err = mEgl.eglGetError(); int err = sEgl.eglGetError(); if (err != EGL10.EGL_SUCCESS) { destroy(); setRequested(false); } else { if (mCanvas != null) { destroyCanvas(); } mCanvas = createCanvas(); if (mCanvas != null) { setEnabled(true); Loading @@ -229,64 +237,75 @@ public abstract class HardwareRenderer { return false; } abstract Canvas createCanvas(); private void destroyCanvas() { mCanvas.destroy(); mCanvas = null; } abstract GLES20Canvas createCanvas(); void initializeEgl() { mEgl = (EGL10) EGLContext.getEGL(); if (sEglContext != null) return; sEglThread = Thread.currentThread(); sEgl = (EGL10) EGLContext.getEGL(); // Get to the default display. mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { if (sEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException("eglGetDisplay failed"); } // We can now initialize EGL for that display int[] version = new int[2]; if (!mEgl.eglInitialize(mEglDisplay, version)) { if (!sEgl.eglInitialize(sEglDisplay, version)) { throw new RuntimeException("eglInitialize failed"); } mEglConfig = getConfigChooser(mGlVersion).chooseConfig(mEgl, mEglDisplay); sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay); /* * Create an EGL context. We want to do this as rarely as we can, because an * EGL context is a somewhat heavy object. */ mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); sEglContext = createContext(sEgl, sEglDisplay, sEglConfig); } GL createEglSurface(SurfaceHolder holder) { // Check preconditions. if (mEgl == null) { if (sEgl == null) { throw new RuntimeException("egl not initialized"); } if (mEglDisplay == null) { if (sEglDisplay == null) { throw new RuntimeException("eglDisplay not initialized"); } if (mEglConfig == null) { if (sEglConfig == null) { throw new RuntimeException("mEglConfig not initialized"); } if (Thread.currentThread() != sEglThread) { throw new IllegalStateException("HardwareRenderer cannot be used " + "from multiple threads"); } /* * The window size has changed, so we need to create a new * surface. */ if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { /* * Unbind and destroy the old EGL surface, if * there is one. */ mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); } // Create an EGL surface we can render into. mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, holder, null); mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null); if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { int error = mEgl.eglGetError(); int error = sEgl.eglGetError(); if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); return null; Loading @@ -298,11 +317,11 @@ public abstract class HardwareRenderer { * Before we can issue GL commands, we need to make sure * the context is current and bound to a surface. */ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } return mEglContext.getGL(); return sEglContext.getGL(); } EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { Loading @@ -315,7 +334,6 @@ public abstract class HardwareRenderer { @Override void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, SurfaceHolder holder) { if (isRequested()) { checkErrors(); super.initializeIfNeeded(width, height, attachInfo, holder); Loading @@ -324,28 +342,34 @@ public abstract class HardwareRenderer { @Override void destroy() { if (!isEnabled()) return; if (!isEnabled() || mDestroyed) return; mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, mDestroyed = true; checkCurrent(); // Destroy the Canvas first in case it needs to use a GL context // to perform its cleanup. destroyCanvas(); sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); mEgl.eglDestroyContext(mEglDisplay, mEglContext); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglTerminate(mEglDisplay); sEgl.eglDestroySurface(sEglDisplay, mEglSurface); mEglContext = null; mEglSurface = null; mEglDisplay = null; mEgl = null; mGl = null; mCanvas = null; // mEgl.eglDestroyContext(mEglDisplay, mEglContext); // mEglContext = null; // mEgl.eglTerminate(mEglDisplay); // mEgl = null; // mEglDisplay = null; setEnabled(false); } @Override void setup(int width, int height, View.AttachInfo attachInfo) { final float scale = attachInfo.mApplicationScale; mCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f)); void setup(int width, int height) { mCanvas.setViewport(width, height); } boolean canDraw() { Loading @@ -363,7 +387,8 @@ public abstract class HardwareRenderer { * @param glVersion */ EglConfigChooser getConfigChooser(int glVersion) { return new ComponentSizeChooser(glVersion, 8, 8, 8, mTranslucent ? 8 : 0, 0, 0); // TODO: Check for mTranslucent here, which means at least 2 EGL contexts return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0); } @Override Loading @@ -373,14 +398,7 @@ public abstract class HardwareRenderer { attachInfo.mIgnoreDirtyState = true; view.mPrivateFlags |= View.DRAWN; // TODO: Don't check the current context when we have one per UI thread // TODO: Use a threadlocal flag to know whether the surface has changed if (mEgl.eglGetCurrentContext() != mEglContext || mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } } checkCurrent(); onPreDraw(); Loading @@ -396,11 +414,22 @@ public abstract class HardwareRenderer { attachInfo.mIgnoreDirtyState = false; mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); checkErrors(); } } private void checkCurrent() { // TODO: Don't check the current context when we have one per UI thread // TODO: Use a threadlocal flag to know whether the surface has changed if (sEgl.eglGetCurrentContext() != sEglContext || sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) { if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) { throw new RuntimeException("eglMakeCurrent failed"); } } } static abstract class EglConfigChooser { final int[] mConfigSpec; private final int mGlVersion; Loading Loading @@ -496,7 +525,7 @@ public abstract class HardwareRenderer { int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0); int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0); int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0); if (r == mRedSize && g == mGreenSize && b == mBlueSize && a >= mAlphaSize) { if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize) { return config; } } Loading Loading @@ -526,8 +555,9 @@ public abstract class HardwareRenderer { } @Override Canvas createCanvas() { return mGlCanvas = new GLES20Canvas(mGl, mTranslucent); GLES20Canvas createCanvas() { // TODO: Pass mTranslucent instead of true return mGlCanvas = new GLES20Canvas(mGl, true); } @Override Loading
core/java/android/view/ViewRoot.java +17 −17 Original line number Diff line number Diff line Loading @@ -251,7 +251,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mTempRect = new Rect(); mVisRect = new Rect(); mWinFrame = new Rect(); mWindow = new W(this, context); mWindow = new W(this); mInputMethodCallback = new InputMethodCallback(this); mViewVisibility = View.GONE; mTransparentRegion = new Region(); Loading Loading @@ -469,6 +469,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn if (attrs != null && (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) { final boolean translucent = attrs.format != PixelFormat.OPAQUE; destroyHardwareRenderer(); mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent); } } Loading Loading @@ -677,9 +678,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn attachInfo.mWindowVisibility = viewVisibility; host.dispatchWindowVisibilityChanged(viewVisibility); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { if (mHwRenderer != null) { mHwRenderer.destroy(); } destroyHardwareRenderer(); } if (viewVisibility == View.GONE) { // After making a window gone, we will count it as being Loading Loading @@ -963,7 +962,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } if (hwIntialized) { mHwRenderer.setup(mWidth, mHeight, mAttachInfo); mHwRenderer.setup(mWidth, mHeight); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( Loading Loading @@ -1598,9 +1597,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn mAttachInfo.mRootView = null; mAttachInfo.mSurface = null; if (mHwRenderer != null) { mHwRenderer.destroy(); } destroyHardwareRenderer(); mHwRenderer = null; mSurface.release(); if (mInputChannel != null) { Loading @@ -1625,6 +1624,12 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn } } private void destroyHardwareRenderer() { if (mHwRenderer != null) { mHwRenderer.destroy(); } } void updateConfiguration(Configuration config, boolean force) { if (DEBUG_CONFIGURATION) Log.v(TAG, "Applying new config to window " Loading Loading @@ -2734,10 +2739,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn public void childDrawableStateChanged(View child) { } protected Rect getWindowFrame() { return mWinFrame; } void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( Loading Loading @@ -2816,16 +2817,15 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn static class W extends IWindow.Stub { private final WeakReference<ViewRoot> mViewRoot; public W(ViewRoot viewRoot, Context context) { W(ViewRoot viewRoot) { mViewRoot = new WeakReference<ViewRoot>(viewRoot); } public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw, Configuration newConfig) { public void resized(int w, int h, Rect coveredInsets, Rect visibleInsets, boolean reportDraw, Configuration newConfig) { final ViewRoot viewRoot = mViewRoot.get(); if (viewRoot != null) { viewRoot.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw, newConfig); viewRoot.dispatchResized(w, h, coveredInsets, visibleInsets, reportDraw, newConfig); } } Loading
core/jni/android_view_GLES20Canvas.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ #include <SkiaShader.h> #include <SkiaColorFilter.h> #include <Rect.h> #include <ui/Rect.h> #include "TextLayout.h" Loading
libs/hwui/Caches.h 0 → 100644 +75 −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. */ #ifndef ANDROID_UI_CACHES_H #define ANDROID_UI_CACHES_H #define LOG_TAG "OpenGLRenderer" #include <utils/Singleton.h> #include "TextureCache.h" #include "LayerCache.h" #include "GradientCache.h" #include "PatchCache.h" #include "FontRenderer.h" #include "ProgramCache.h" #include "PathCache.h" #include "TextDropShadowCache.h" namespace android { namespace uirenderer { struct CacheLogger { CacheLogger() { LOGD("Creating caches"); } }; // struct CacheLogger class Caches: public Singleton<Caches> { Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO), lastDstMode(GL_ZERO), currentProgram(NULL) { dropShadowCache.setFontRenderer(fontRenderer); } friend class Singleton<Caches>; CacheLogger logger; public: bool blend; GLenum lastSrcMode; GLenum lastDstMode; Program* currentProgram; TextureCache textureCache; LayerCache layerCache; GradientCache gradientCache; ProgramCache programCache; PathCache pathCache; PatchCache patchCache; TextDropShadowCache dropShadowCache; FontRenderer fontRenderer; }; // class Caches }; // namespace uirenderer using namespace uirenderer; ANDROID_SINGLETON_STATIC_INSTANCE(Caches); }; // namespace android #endif // ANDROID_UI_CACHES_H