TextureView Vulkan support and optimized OpenGL draw

Render TextureView as hardware bitmaps, instead of GL textures.
Cache SkImage for each observed GraphicBuffer, which is faster
even for GL.
Implement C++ SurfaceTexture, which allows Java SurfaceTexture
to be used with Vulkan HWUI render thread and application GL.
threads. Delete GLLayer and VkLayer classes and texture code
from old HWUI pipeline.

Test: Ran skiagl and skiavk pipeline with a TextureView app.
Test: TextureView CTS tests pass for GL pipeline.
Test: Ran Android NDK Native codec sample app.
Change-Id: Idc94f864ce2d34fd6ceff4be4fc7d3327e99879c
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index bec80b1e..c45eeda 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -21,6 +21,7 @@
 #include "RenderThread.h"
 #include "pipeline/skia/ShaderCache.h"
 #include "pipeline/skia/SkiaMemoryTracer.h"
+#include "Properties.h"
 #include "renderstate/RenderState.h"
 
 #include <GrContextOptions.h>
@@ -214,11 +215,12 @@
             log.appendFormat("  Layer Info:\n");
         }
 
+        const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
+                ? "GlLayer" : "VkLayer";
         size_t layerMemoryTotal = 0;
         for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
              it != renderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
-            const char* layerType = layer->getApi() == Layer::Api::OpenGL ? "GlLayer" : "VkLayer";
             log.appendFormat("    %s size %dx%d\n", layerType, layer->getWidth(),
                              layer->getHeight());
             layerMemoryTotal += layer->getWidth() * layer->getHeight() * 4;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5d72523..8b07d1d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -18,7 +18,6 @@
 #include <GpuMemoryTracker.h>
 
 #include "AnimationContext.h"
-#include "Caches.h"
 #include "EglManager.h"
 #include "Frame.h"
 #include "LayerUpdateQueue.h"
@@ -495,13 +494,6 @@
     }
 
     GpuMemoryTracker::onFrameCompleted();
-#ifdef BUGREPORT_FONT_CACHE_USAGE
-    auto renderType = Properties::getRenderPipelineType();
-    if (RenderPipelineType::OpenGL == renderType) {
-        Caches& caches = Caches::getInstance();
-        caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
-    }
-#endif
 }
 
 // Called by choreographer to do an RT-driven animation
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index cd21822..5f8d7ad 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -18,6 +18,7 @@
 
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <private/gui/SyncFeatures.h>
 #include <utils/Trace.h>
 #include "utils/StringUtils.h"
 
@@ -464,6 +465,109 @@
     return preserved;
 }
 
+status_t EglManager::fenceWait(sp<Fence>& fence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::fenceWait: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useWaitSync() &&
+        SyncFeatures::getInstance().useNativeFenceSync()) {
+        // Block GPU on the fence.
+        // Create an EGLSyncKHR from the current fence.
+        int fenceFd = fence->dup();
+        if (fenceFd == -1) {
+            ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
+            return -errno;
+        }
+        EGLint attribs[] = {
+            EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
+            EGL_NONE
+        };
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+        if (sync == EGL_NO_SYNC_KHR) {
+            close(fenceFd);
+            ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+
+        // XXX: The spec draft is inconsistent as to whether this should
+        // return an EGLint or void.  Ignore the return value for now, as
+        // it's not strictly needed.
+        eglWaitSyncKHR(mEglDisplay, sync, 0);
+        EGLint eglErr = eglGetError();
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (eglErr != EGL_SUCCESS) {
+            ALOGE("EglManager::fenceWait: error waiting for EGL fence: %#x", eglErr);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        // Block CPU on the fence.
+        status_t err = fence->waitForever("EglManager::fenceWait");
+        if (err != NO_ERROR) {
+            ALOGE("EglManager::fenceWait: error waiting for fence: %d", err);
+            return err;
+        }
+    }
+    return OK;
+}
+
+status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
+        sp<Fence>& nativeFence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useNativeFenceSync()) {
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+        if (sync == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
+                    eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+        int fenceFd = eglDupNativeFenceFDANDROID(mEglDisplay, sync);
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+            ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
+                    "fd: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        nativeFence = new Fence(fenceFd);
+        *eglFence = EGL_NO_SYNC_KHR;
+    } else if (useFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+        if (*eglFence != EGL_NO_SYNC_KHR) {
+            // There is already a fence for the current slot.  We need to
+            // wait on that before replacing it with another fence to
+            // ensure that all outstanding buffer accesses have completed
+            // before the producer accesses it.
+            EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
+            if (result == EGL_FALSE) {
+                ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
+                        eglGetError());
+                return UNKNOWN_ERROR;
+            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
+                return TIMED_OUT;
+            }
+            eglDestroySyncKHR(mEglDisplay, *eglFence);
+        }
+
+        // Create a fence for the outstanding accesses in the current
+        // OpenGL ES context.
+        *eglFence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, nullptr);
+        if (*eglFence == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+    }
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 8e8bb8b..507673a 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -17,8 +17,10 @@
 #define EGLMANAGER_H
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <SkRect.h>
 #include <cutils/compiler.h>
+#include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
@@ -66,6 +68,14 @@
 
     EGLDisplay eglDisplay() const { return mEglDisplay; }
 
+    // Inserts a wait on fence command into the OpenGL ES command stream. If EGL extension
+    // support is missing, block the CPU on the fence.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending GL commands are flushed.
+    // Depending on installed extensions, the result is either Android native fence or EGL fence.
+    status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, sp<Fence>& nativeFence);
+
 private:
 
     void initExtensions();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 3eaf43b..51be54c 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -178,7 +178,7 @@
         return;
     }
     mEglManager->initialize();
-    renderState().onGLContextCreated();
+    renderState().onContextCreated();
 
 #ifdef HWUI_GLES_WRAP_ENABLED
     debug::GlesDriver* driver = debug::GlesDriver::get();
@@ -199,7 +199,7 @@
 void RenderThread::destroyGlContext() {
     if (mEglManager->hasEglContext()) {
         setGrContext(nullptr);
-        renderState().onGLContextDestroyed();
+        renderState().onContextDestroyed();
         mEglManager->destroy();
     }
 }
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index a19edae..67b1972 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -38,7 +38,7 @@
 VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
 
 void VulkanManager::destroy() {
-    mRenderThread.renderState().onVkContextDestroyed();
+    mRenderThread.renderState().onContextDestroyed();
     mRenderThread.setGrContext(nullptr);
 
     if (VK_NULL_HANDLE != mCommandPool) {
@@ -367,7 +367,7 @@
         mSwapBehavior = SwapBehavior::BufferAge;
     }
 
-    mRenderThread.renderState().onVkContextCreated();
+    mRenderThread.renderState().onContextCreated();
 }
 
 // Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -944,6 +944,22 @@
     return surface->mCurrentTime - lastUsed;
 }
 
+status_t VulkanManager::fenceWait(sp<Fence>& fence) {
+    //TODO: Insert a wait on fence command into the Vulkan command buffer.
+    // Block CPU on the fence.
+    status_t err = fence->waitForever("VulkanManager::fenceWait");
+    if (err != NO_ERROR) {
+        ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
+        return err;
+    }
+    return OK;
+}
+
+status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence) {
+    //TODO: Create a fence that is signaled, when all the pending Vulkan commands are flushed.
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 69641d5..7051ee6 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -23,6 +23,8 @@
 #include <vulkan/vulkan.h>
 
 #include <SkSurface.h>
+#include <ui/Fence.h>
+#include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
 
 namespace android {
@@ -108,6 +110,12 @@
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
 
+    // Inserts a wait on fence command into the Vulkan command buffer.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending Vulkan commands are flushed.
+    status_t createReleaseFence(sp<Fence>& nativeFence);
+
 private:
     friend class RenderThread;