From 3696779bca4e5bc1b60c056db6f892e72e51a20f Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 28 Jan 2013 14:04:07 -0800 Subject: [PATCH] Reinitialize hardware renderer after eglTerminate() Bug #8066455 ViewRootImpl was properly detecting that the renderer was not ready to draw but would simply schedule another frame, thus sending the systemui into an inifite redraw loop. This change reinitializes the renderer if needed (if the renderer is requested but not enabled.) This CL also fixes an issue caused by the default wallpaper. Since it never calls eglTerminate(), managed contexts are never reclaimed. Change-Id: Idb8caa672be8ee35f6e6a7e942d9abd8aa100967 --- core/java/android/view/ViewRootImpl.java | 93 ++++++++++--------- .../com/android/systemui/ImageWallpaper.java | 11 ++- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3faac40d6ca3d..9f075c49d23e0 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1513,16 +1513,7 @@ public final class ViewRootImpl implements ViewParent, hwInitialized = mAttachInfo.mHardwareRenderer.initialize( mHolder.getSurface()); } catch (Surface.OutOfResourcesException e) { - Log.e(TAG, "OutOfResourcesException initializing HW surface", e); - try { - if (!mWindowSession.outOfMemory(mWindow) && - Process.myUid() != Process.SYSTEM_UID) { - Slog.w(TAG, "No processes killed for memory; killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } - mLayoutRequested = true; // ask wm for a new surface next time. + handleOutOfResourcesException(e); return; } } @@ -1549,15 +1540,7 @@ public final class ViewRootImpl implements ViewParent, try { mAttachInfo.mHardwareRenderer.updateSurface(mHolder.getSurface()); } catch (Surface.OutOfResourcesException e) { - Log.e(TAG, "OutOfResourcesException updating HW surface", e); - try { - if (!mWindowSession.outOfMemory(mWindow)) { - Slog.w(TAG, "No processes killed for memory; killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } - mLayoutRequested = true; // ask wm for a new surface next time. + handleOutOfResourcesException(e); return; } } @@ -1879,6 +1862,19 @@ public final class ViewRootImpl implements ViewParent, mIsInTraversal = false; } + private void handleOutOfResourcesException(Surface.OutOfResourcesException e) { + Log.e(TAG, "OutOfResourcesException initializing HW surface", e); + try { + if (!mWindowSession.outOfMemory(mWindow) && + Process.myUid() != Process.SYSTEM_UID) { + Slog.w(TAG, "No processes killed for memory; killing self"); + Process.killProcess(Process.myPid()); + } + } catch (RemoteException ex) { + } + mLayoutRequested = true; // ask wm for a new surface next time. + } + private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure"); try { @@ -2296,8 +2292,35 @@ public final class ViewRootImpl implements ViewParent, animating ? null : mCurrentDirty)) { mPreviousDirty.set(0, 0, mWidth, mHeight); } - } else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) { - return; + } else { + // If we get here with a disabled & requested hardware renderer, something went + // wrong (an invalidate posted right before we destroyed the hardware surface + // for instance) so we should just bail out. Locking the surface with software + // rendering at this point would lock it forever and prevent hardware renderer + // from doing its job when it comes back. + // Before we request a new frame we must however attempt to reinitiliaze the + // hardware renderer if it's in requested state. This would happen after an + // eglTerminate() for instance. + if (attachInfo.mHardwareRenderer != null && + !attachInfo.mHardwareRenderer.isEnabled() && + attachInfo.mHardwareRenderer.isRequested()) { + + try { + attachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight, + mHolder.getSurface()); + } catch (Surface.OutOfResourcesException e) { + handleOutOfResourcesException(e); + return; + } + + mFullRedrawNeeded = true; + scheduleTraversals(); + return; + } + + if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) { + return; + } } } @@ -2313,18 +2336,6 @@ public final class ViewRootImpl implements ViewParent, private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff, boolean scalingRequired, Rect dirty) { - // If we get here with a disabled & requested hardware renderer, something went - // wrong (an invalidate posted right before we destroyed the hardware surface - // for instance) so we should just bail out. Locking the surface with software - // rendering at this point would lock it forever and prevent hardware renderer - // from doing its job when it comes back. - if (attachInfo.mHardwareRenderer != null && !attachInfo.mHardwareRenderer.isEnabled() && - attachInfo.mHardwareRenderer.isRequested()) { - mFullRedrawNeeded = true; - scheduleTraversals(); - return false; - } - // Draw with software renderer. Canvas canvas; try { @@ -2343,15 +2354,7 @@ public final class ViewRootImpl implements ViewParent, // TODO: Do this in native canvas.setDensity(mDensity); } catch (Surface.OutOfResourcesException e) { - Log.e(TAG, "OutOfResourcesException locking surface", e); - try { - if (!mWindowSession.outOfMemory(mWindow)) { - Slog.w(TAG, "No processes killed for memory; killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } - mLayoutRequested = true; // ask wm for a new surface next time. + handleOutOfResourcesException(e); return false; } catch (IllegalArgumentException e) { Log.e(TAG, "Could not lock surface", e); @@ -2996,10 +2999,8 @@ public final class ViewRootImpl implements ViewParent, mSurface != null && mSurface.isValid()) { mFullRedrawNeeded = true; try { - if (mAttachInfo.mHardwareRenderer.initializeIfNeeded( - mWidth, mHeight, mHolder.getSurface())) { - mFullRedrawNeeded = true; - } + mAttachInfo.mHardwareRenderer.initializeIfNeeded( + mWidth, mHeight, mHolder.getSurface()); } catch (Surface.OutOfResourcesException e) { Log.e(TAG, "OutOfResourcesException locking surface", e); try { diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index a1c56506fdfe2..79f965049eae7 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -564,7 +564,7 @@ public class ImageWallpaper extends WallpaperService { return program; } - + private int buildShader(String source, int type) { int shader = glCreateShader(type); @@ -585,27 +585,28 @@ public class ImageWallpaper extends WallpaperService { return shader; } - + private void checkEglError() { int error = mEgl.eglGetError(); if (error != EGL_SUCCESS) { Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error)); } } - + private void checkGlError() { int error = glGetError(); if (error != GL_NO_ERROR) { Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable()); } } - + private void finishGL() { mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEgl.eglTerminate(mEglDisplay); } - + private boolean initGL(SurfaceHolder surfaceHolder) { mEgl = (EGL10) EGLContext.getEGL();