From 3941cb240d438bfdebe24920bb2ada86456a0bf9 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 17 Sep 2012 16:58:17 -0700 Subject: [PATCH] SurfaceTexture: default to doing GL sync This change makes updateTexImage default to performing the necessary synchronization and adds an argument for SurfaceFlinger to disable that synchronization so that it can be performed lazily. Change-Id: I7c20923cc786634126fbf7021c9d2541aa77be5d Bug: 6991805 --- include/gui/SurfaceTexture.h | 9 ++++++++- libs/gui/SurfaceTexture.cpp | 17 +++++++++++++++-- services/surfaceflinger/Layer.cpp | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 6e5a478b1..37e7eb1e6 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -246,7 +246,7 @@ private: 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 @@ private: // 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 36a2af7dc..f2e907760 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -164,7 +164,7 @@ status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) } status_t SurfaceTexture::updateTexImage() { - return SurfaceTexture::updateTexImage(NULL); + return SurfaceTexture::updateTexImage(NULL, false); } status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) { @@ -205,7 +205,7 @@ status_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display, 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 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) { 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 @@ sp SurfaceTexture::getCurrentFence() const { 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 569f6bbc6..3d79baf60 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -637,7 +637,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) Reject r(mDrawingState, currentState(), recomputeVisibleRegions); - if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) { + if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) { // something happened! recomputeVisibleRegions = true; return outDirtyRegion;