Loading include/gui/SurfaceTexture.h +9 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ public: // // This call may only be made while the OpenGL ES context to which the // target texture belongs is bound to the calling thread. // // After calling this method the doGLFenceWait method must be called // before issuing OpenGL ES commands that access the texture contents. status_t updateTexImage(); // setReleaseFence stores a fence file descriptor that will signal when the Loading Loading @@ -154,6 +157,12 @@ public: // ready to be read from. sp<Fence> getCurrentFence() const; // doGLFenceWait 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 doGLFenceWait() const; // isSynchronousMode returns whether the SurfaceTexture is currently in // synchronous mode. bool isSynchronousMode() const; Loading libs/gui/SurfaceTexture.cpp +72 −2 Original line number Diff line number Diff line Loading @@ -48,9 +48,19 @@ #ifdef USE_FENCE_SYNC #error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible" #endif const bool useNativeFenceSync = true; static const bool useNativeFenceSync = true; #else const bool useNativeFenceSync = false; static const bool useNativeFenceSync = false; #endif // This compile option makes SurfaceTexture use the EGL_ANDROID_sync_wait // extension to insert server-side waits into the GLES command stream. This // feature requires the EGL_ANDROID_native_fence_sync and // EGL_ANDROID_wait_sync extensions. #ifdef USE_WAIT_SYNC static const bool useWaitSync = true; #else static const bool useWaitSync = false; #endif // This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension Loading Loading @@ -725,6 +735,66 @@ sp<Fence> SurfaceTexture::getCurrentFence() const { return mCurrentFence; } status_t SurfaceTexture::doGLFenceWait() const { Mutex::Autolock lock(mMutex); EGLDisplay dpy = eglGetCurrentDisplay(); EGLContext ctx = eglGetCurrentContext(); if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { ST_LOGE("doGLFenceWait: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { ST_LOGE("doGLFenceWait: invalid current EGLContext"); return INVALID_OPERATION; } if (mCurrentFence != NULL) { if (useWaitSync) { // Create an EGLSyncKHR from the current fence. int fenceFd = mCurrentFence->dup(); if (fenceFd == -1) { ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); return -errno; } EGLint attribs[] = { EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE }; EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (sync == EGL_NO_SYNC_KHR) { close(fenceFd); ST_LOGE("doGLFenceWait: 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. eglWaitSyncANDROID(dpy, sync, 0); EGLint eglErr = eglGetError(); eglDestroySyncKHR(dpy, sync); if (eglErr != EGL_SUCCESS) { ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr); return UNKNOWN_ERROR; } } else { status_t err = mCurrentFence->wait(Fence::TIMEOUT_NEVER); if (err != NO_ERROR) { ST_LOGE("doGLFenceWait: error waiting for fence: %d", err); return err; } } } return NO_ERROR; } bool SurfaceTexture::isSynchronousMode() const { Mutex::Autolock lock(mMutex); return mBufferQueue->isSynchronousMode(); Loading services/surfaceflinger/Layer.cpp +3 −5 Original line number Diff line number Diff line Loading @@ -333,11 +333,9 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const return; } // TODO: replace this with a server-side wait sp<Fence> fence = mSurfaceTexture->getCurrentFence(); if (fence.get()) { status_t err = fence->wait(Fence::TIMEOUT_NEVER); ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err); status_t err = mSurfaceTexture->doGLFenceWait(); if (err != OK) { ALOGE("onDraw: failed waiting for fence: %d", err); // Go ahead and draw the buffer anyway; no matter what we do the screen // is probably going to have something visibly wrong. } Loading Loading
include/gui/SurfaceTexture.h +9 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ public: // // This call may only be made while the OpenGL ES context to which the // target texture belongs is bound to the calling thread. // // After calling this method the doGLFenceWait method must be called // before issuing OpenGL ES commands that access the texture contents. status_t updateTexImage(); // setReleaseFence stores a fence file descriptor that will signal when the Loading Loading @@ -154,6 +157,12 @@ public: // ready to be read from. sp<Fence> getCurrentFence() const; // doGLFenceWait 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 doGLFenceWait() const; // isSynchronousMode returns whether the SurfaceTexture is currently in // synchronous mode. bool isSynchronousMode() const; Loading
libs/gui/SurfaceTexture.cpp +72 −2 Original line number Diff line number Diff line Loading @@ -48,9 +48,19 @@ #ifdef USE_FENCE_SYNC #error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible" #endif const bool useNativeFenceSync = true; static const bool useNativeFenceSync = true; #else const bool useNativeFenceSync = false; static const bool useNativeFenceSync = false; #endif // This compile option makes SurfaceTexture use the EGL_ANDROID_sync_wait // extension to insert server-side waits into the GLES command stream. This // feature requires the EGL_ANDROID_native_fence_sync and // EGL_ANDROID_wait_sync extensions. #ifdef USE_WAIT_SYNC static const bool useWaitSync = true; #else static const bool useWaitSync = false; #endif // This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension Loading Loading @@ -725,6 +735,66 @@ sp<Fence> SurfaceTexture::getCurrentFence() const { return mCurrentFence; } status_t SurfaceTexture::doGLFenceWait() const { Mutex::Autolock lock(mMutex); EGLDisplay dpy = eglGetCurrentDisplay(); EGLContext ctx = eglGetCurrentContext(); if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { ST_LOGE("doGLFenceWait: invalid current EGLDisplay"); return INVALID_OPERATION; } if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { ST_LOGE("doGLFenceWait: invalid current EGLContext"); return INVALID_OPERATION; } if (mCurrentFence != NULL) { if (useWaitSync) { // Create an EGLSyncKHR from the current fence. int fenceFd = mCurrentFence->dup(); if (fenceFd == -1) { ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); return -errno; } EGLint attribs[] = { EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE }; EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); if (sync == EGL_NO_SYNC_KHR) { close(fenceFd); ST_LOGE("doGLFenceWait: 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. eglWaitSyncANDROID(dpy, sync, 0); EGLint eglErr = eglGetError(); eglDestroySyncKHR(dpy, sync); if (eglErr != EGL_SUCCESS) { ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr); return UNKNOWN_ERROR; } } else { status_t err = mCurrentFence->wait(Fence::TIMEOUT_NEVER); if (err != NO_ERROR) { ST_LOGE("doGLFenceWait: error waiting for fence: %d", err); return err; } } } return NO_ERROR; } bool SurfaceTexture::isSynchronousMode() const { Mutex::Autolock lock(mMutex); return mBufferQueue->isSynchronousMode(); Loading
services/surfaceflinger/Layer.cpp +3 −5 Original line number Diff line number Diff line Loading @@ -333,11 +333,9 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const return; } // TODO: replace this with a server-side wait sp<Fence> fence = mSurfaceTexture->getCurrentFence(); if (fence.get()) { status_t err = fence->wait(Fence::TIMEOUT_NEVER); ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err); status_t err = mSurfaceTexture->doGLFenceWait(); if (err != OK) { ALOGE("onDraw: failed waiting for fence: %d", err); // Go ahead and draw the buffer anyway; no matter what we do the screen // is probably going to have something visibly wrong. } Loading