Eliminate requireGlContext

Bug: 20297820

Change-Id: I37c63bab6f6c0d2337c8c6002046d2ef17e74097
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f75d6a0..1030451 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -23,6 +23,7 @@
 #include "Properties.h"
 #include "renderstate/RenderState.h"
 #include "ShadowTessellator.h"
+#include "utils/GLUtils.h"
 
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -276,6 +277,9 @@
 
     clearGarbage();
     glFinish();
+    // Errors during cleanup should be considered non-fatal, dump them and
+    // and move on. TODO: All errors or just errors like bad surface?
+    GLUtils::dumpGLErrors();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 6b8c780..a17904e 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -119,7 +119,6 @@
 
 void DeferredLayerUpdater::detachSurfaceTexture() {
     if (mSurfaceTexture.get()) {
-        mRenderThread.eglManager().requireGlContext();
         status_t err = mSurfaceTexture->detachFromContext();
         if (err != 0) {
             // TODO: Elevate to fatal exception
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index e54fa5a..d7c8316 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -169,7 +169,8 @@
 
 void RenderState::requireGLContext() {
     assertOnGLThread();
-    mRenderThread.eglManager().requireGlContext();
+    LOG_ALWAYS_FATAL_IF(!mRenderThread.eglManager().hasEglContext(),
+            "No GL context!");
 }
 
 void RenderState::assertOnGLThread() {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8329cd4..706e14e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -262,8 +262,6 @@
 
     if (drew) {
         swapBuffers(dirty, width, height);
-    } else {
-        mEglManager.cancelFrame();
     }
 
     // TODO: Use a fence for real completion?
@@ -297,7 +295,6 @@
     ATRACE_CALL();
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
     if (thread.eglManager().hasEglContext()) {
-        thread.eglManager().requireGlContext();
         mode = DrawGlInfo::kModeProcess;
     }
 
@@ -318,7 +315,6 @@
 
 void CanvasContext::freePrefetechedLayers() {
     if (mPrefetechedLayers.size()) {
-        requireGlContext();
         std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode);
         mPrefetechedLayers.clear();
     }
@@ -329,7 +325,6 @@
     if (!mEglManager.hasEglContext() || !mCanvas) {
         return;
     }
-    requireGlContext();
     // buildLayer() will leave the tree in an unknown state, so we must stop drawing
     stopDrawing();
 
@@ -352,7 +347,6 @@
 }
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
-    requireGlContext();
     layer->apply();
     return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
 }
@@ -360,7 +354,6 @@
 void CanvasContext::destroyHardwareResources() {
     stopDrawing();
     if (mEglManager.hasEglContext()) {
-        requireGlContext();
         freePrefetechedLayers();
         mRootRenderNode->destroyHardwareResources();
         Caches::getInstance().flush(Caches::kFlushMode_Layers);
@@ -372,7 +365,6 @@
     if (!thread.eglManager().hasEglContext()) return;
 
     ATRACE_CALL();
-    thread.eglManager().requireGlContext();
     if (level >= TRIM_MEMORY_COMPLETE) {
         Caches::getInstance().flush(Caches::kFlushMode_Full);
         thread.eglManager().destroy();
@@ -382,7 +374,8 @@
 }
 
 void CanvasContext::runWithGlContext(RenderTask* task) {
-    requireGlContext();
+    LOG_ALWAYS_FATAL_IF(!mEglManager.hasEglContext(),
+            "GL context not initialized!");
     task->run();
 }
 
@@ -391,10 +384,6 @@
     return LayerRenderer::createTextureLayer(mRenderThread.renderState());
 }
 
-void CanvasContext::requireGlContext() {
-    mEglManager.requireGlContext();
-}
-
 void CanvasContext::setTextureAtlas(RenderThread& thread,
         const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize) {
     thread.eglManager().setTextureAtlas(buffer, map, mapSize);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 17917af..10e66e9 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -122,8 +122,6 @@
     void swapBuffers(const SkRect& dirty, EGLint width, EGLint height);
     void requireSurface();
 
-    void requireGlContext();
-
     void freePrefetechedLayers();
 
     RenderThread& mRenderThread;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 6255f5e..c0e7c73 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -78,8 +78,7 @@
         , mAllowPreserveBuffer(load_dirty_regions_property())
         , mCurrentSurface(EGL_NO_SURFACE)
         , mAtlasMap(nullptr)
-        , mAtlasMapSize(0)
-        , mInFrame(false) {
+        , mAtlasMapSize(0) {
     mCanSetPreserveBuffer = mAllowPreserveBuffer;
     ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false");
 }
@@ -101,7 +100,8 @@
 
     loadConfig();
     createContext();
-    usePBufferSurface();
+    createPBufferSurface();
+    makeCurrent(mPBufferSurface);
     mRenderThread.renderState().onGLContextCreated();
     initAtlas();
 }
@@ -110,17 +110,6 @@
     return mEglDisplay != EGL_NO_DISPLAY;
 }
 
-void EglManager::requireGlContext() {
-    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context");
-
-    if (!mInFrame) {
-        // We can't be certain about the state of the current surface (whether
-        // or not it is destroyed, for example), so err on the side of using
-        // the pbuffer surface which we fully control
-        usePBufferSurface();
-    }
-}
-
 void EglManager::loadConfig() {
     EGLint swapBehavior = mCanSetPreserveBuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
     EGLint attribs[] = {
@@ -173,7 +162,6 @@
     mAtlasMapSize = mapSize;
 
     if (hasEglContext()) {
-        usePBufferSurface();
         initAtlas();
     }
 }
@@ -185,7 +173,7 @@
     }
 }
 
-void EglManager::usePBufferSurface() {
+void EglManager::createPBufferSurface() {
     LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
             "usePBufferSurface() called on uninitialized GlobalContext!");
 
@@ -193,7 +181,6 @@
         EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
         mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
     }
-    makeCurrent(mPBufferSurface);
 }
 
 EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
@@ -217,8 +204,6 @@
 void EglManager::destroy() {
     if (mEglDisplay == EGL_NO_DISPLAY) return;
 
-    usePBufferSurface();
-
     mRenderThread.renderState().onGLContextDestroyed();
     eglDestroyContext(mEglDisplay, mEglContext);
     eglDestroySurface(mEglDisplay, mPBufferSurface);
@@ -236,11 +221,10 @@
     if (isCurrent(surface)) return false;
 
     if (surface == EGL_NO_SURFACE) {
-        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
-        // return errors, which would only happen if mEglDisplay had already been
-        // destroyed in which case the current context is already NO_CONTEXT
-        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
+        // Ensure we always have a valid surface & context
+        surface = mPBufferSurface;
+    }
+    if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
         LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
                 (void*)surface, egl_error_str());
     }
@@ -259,12 +243,10 @@
         eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
     }
     eglBeginFrame(mEglDisplay, surface);
-    mInFrame = true;
 }
 
 bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty,
         EGLint width, EGLint height) {
-    mInFrame = false;
 
 #if WAIT_FOR_GPU_COMPLETION
     {
@@ -328,10 +310,6 @@
     eglDestroySyncKHR(mEglDisplay, fence);
 }
 
-void EglManager::cancelFrame() {
-    mInFrame = false;
-}
-
 bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
     if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false;
 
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 0855516..8881de6 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -36,9 +36,7 @@
     void initialize();
 
     bool hasEglContext();
-    void requireGlContext();
 
-    void usePBufferSurface();
     EGLSurface createSurface(EGLNativeWindowType window);
     void destroySurface(EGLSurface surface);
 
@@ -49,7 +47,6 @@
     bool makeCurrent(EGLSurface surface);
     void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
     bool swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height);
-    void cancelFrame();
 
     // Returns true iff the surface is now preserving buffers.
     bool setPreserveBuffer(EGLSurface surface, bool preserve);
@@ -65,6 +62,7 @@
     // EglContext is never destroyed, method is purposely not implemented
     ~EglManager();
 
+    void createPBufferSurface();
     void loadConfig();
     void createContext();
     void initAtlas();
@@ -84,12 +82,6 @@
     sp<GraphicBuffer> mAtlasBuffer;
     int64_t* mAtlasMap;
     size_t mAtlasMapSize;
-
-    // Whether or not we are in the middle of drawing a frame. This is used
-    // to avoid switching surfaces mid-frame if requireGlContext() is called
-    // TODO: Need to be better about surface/context management so that this isn't
-    // necessary
-    bool mInFrame;
 };
 
 } /* namespace renderthread */