Merge "Check that HWC exists before trying to use it" into jb-mr1-dev
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 6e5a478..37e7eb1 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -246,7 +246,7 @@
         virtual ~BufferRejecter() { }
     };
     friend class Layer;
-    status_t updateTexImage(BufferRejecter* rejecter);
+    status_t updateTexImage(BufferRejecter* rejecter, bool skipSync);
 
     // createImage creates a new EGLImage from a GraphicBuffer.
     EGLImageKHR createImage(EGLDisplay dpy,
@@ -264,6 +264,13 @@
     // to compute this matrix and stores it in mCurrentTransformMatrix.
     void computeCurrentTransformMatrix();
 
+    // doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
+    // stream to ensure that it is safe for future OpenGL ES commands to
+    // access the current texture buffer.  This must be called each time
+    // updateTexImage is called before issuing OpenGL ES commands that access
+    // the texture.
+    status_t doGLFenceWaitLocked() const;
+
     // syncForReleaseLocked performs the synchronization needed to release the
     // current slot from an OpenGL ES context.  If needed it will set the
     // current slot's fence to guard against a producer accessing the buffer
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 36a2af7..f2e9077 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -164,7 +164,7 @@
 }
 
 status_t SurfaceTexture::updateTexImage() {
-    return SurfaceTexture::updateTexImage(NULL);
+    return SurfaceTexture::updateTexImage(NULL, false);
 }
 
 status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) {
@@ -205,7 +205,7 @@
     return err;
 }
 
-status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
+status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter, bool skipSync) {
     ATRACE_CALL();
     ST_LOGV("updateTexImage");
     Mutex::Autolock lock(mMutex);
@@ -308,6 +308,15 @@
         mCurrentScalingMode = item.mScalingMode;
         mCurrentTimestamp = item.mTimestamp;
         mCurrentFence = item.mFence;
+        if (!skipSync) {
+            // SurfaceFlinger needs to lazily perform GLES synchronization
+            // only when it's actually going to use GLES for compositing.
+            // Eventually SurfaceFlinger should have its own consumer class,
+            // but for now we'll just hack it in to SurfaceTexture.
+            // SurfaceFlinger is responsible for calling doGLFenceWait before
+            // texturing from this SurfaceTexture.
+            doGLFenceWaitLocked();
+        }
         computeCurrentTransformMatrix();
     } else  {
         if (err < 0) {
@@ -738,6 +747,10 @@
 
 status_t SurfaceTexture::doGLFenceWait() const {
     Mutex::Autolock lock(mMutex);
+    return doGLFenceWaitLocked();
+}
+
+status_t SurfaceTexture::doGLFenceWaitLocked() const {
 
     EGLDisplay dpy = eglGetCurrentDisplay();
     EGLContext ctx = eglGetCurrentContext();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 569f6bb..3d79baf 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -637,7 +637,7 @@
 
         Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
 
-        if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
+        if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
             return outDirtyRegion;