diff --git a/libgralloc/fb_priv.h b/libgralloc/fb_priv.h index 48e5669..340968c 100644 --- a/libgralloc/fb_priv.h +++ b/libgralloc/fb_priv.h @@ -54,6 +54,9 @@ struct private_module_t { pthread_mutex_t fbPostLock; //Condition to inform HWC that fb_post called pthread_cond_t fbPostCond; + bool fbPanDone; + pthread_mutex_t fbPanLock; + pthread_cond_t fbPanCond; }; diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp index b257521..48f3bb0 100644 --- a/libgralloc/framebuffer.cpp +++ b/libgralloc/framebuffer.cpp @@ -132,6 +132,12 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) return -errno; } + //Signals the composition thread to unblock and loop over if necessary + pthread_mutex_lock(&m->fbPanLock); + m->fbPanDone = true; + pthread_cond_signal(&m->fbPanCond); + pthread_mutex_unlock(&m->fbPanLock); + if (m->currentBuffer) { genlock_unlock_buffer(m->currentBuffer); m->currentBuffer = 0; @@ -366,6 +372,9 @@ int mapFrameBufferLocked(struct private_module_t* module) module->fbPostDone = false; pthread_mutex_init(&(module->fbPostLock), NULL); pthread_cond_init(&(module->fbPostCond), NULL); + module->fbPanDone = false; + pthread_mutex_init(&(module->fbPanLock), NULL); + pthread_cond_init(&(module->fbPanCond), NULL); return 0; } diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index e6750be..af23ecb 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -175,9 +175,14 @@ static int hwc_set(hwc_composer_device_t *dev, CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); MDPComp::draw(ctx, list); EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + wait4fbPost(ctx); + //Can draw to HDMI only when fb_post is reached UIMirrorOverlay::draw(ctx); + //HDMI commit and primary commit (PAN) happening in parallel if(ctx->mExtDisplay->getExternalDisplay()) ctx->mExtDisplay->commit(); + //Virtual barrier for threads to finish + wait4Pan(ctx); } else { ctx->mOverlay->setState(ovutils::OV_CLOSED); ctx->qbuf->unlockAll(); diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp index 1508fd5..6c37c42 100644 --- a/libhwcomposer/hwc_uimirror.cpp +++ b/libhwcomposer/hwc_uimirror.cpp @@ -129,13 +129,6 @@ bool UIMirrorOverlay::draw(hwc_context_t *ctx) if(fbDev) { private_module_t* m = reinterpret_cast( fbDev->common.module); - //wait for the fb_post to be called - pthread_mutex_lock(&m->fbPostLock); - while(m->fbPostDone == false) { - pthread_cond_wait(&(m->fbPostCond), &(m->fbPostLock)); - } - m->fbPostDone = false; - pthread_mutex_unlock(&m->fbPostLock); switch (state) { case ovutils::OV_UI_MIRROR: if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset, diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index db9eb28..258913d 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include #include "hwc_utils.h" #include "mdp_version.h" #include "hwc_video.h" @@ -217,4 +219,33 @@ void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, } } +void wait4fbPost(hwc_context_t* ctx) { + framebuffer_device_t *fbDev = ctx->mFbDev; + if(fbDev) { + private_module_t* m = reinterpret_cast( + fbDev->common.module); + //wait for the fb_post to be called + pthread_mutex_lock(&m->fbPostLock); + while(m->fbPostDone == false) { + pthread_cond_wait(&(m->fbPostCond), &(m->fbPostLock)); + } + m->fbPostDone = false; + pthread_mutex_unlock(&m->fbPostLock); + } +} + +void wait4Pan(hwc_context_t* ctx) { + framebuffer_device_t *fbDev = ctx->mFbDev; + if(fbDev) { + private_module_t* m = reinterpret_cast( + fbDev->common.module); + //wait for the fb_post's PAN to finish + pthread_mutex_lock(&m->fbPanLock); + while(m->fbPanDone == false) { + pthread_cond_wait(&(m->fbPanCond), &(m->fbPanLock)); + } + m->fbPanDone = false; + pthread_mutex_unlock(&m->fbPanLock); + } +} };//namespace diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 5127e99..54ac1a5 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -79,6 +79,12 @@ void closeContext(hwc_context_t *ctx); void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, const int fbWidth, const int fbHeight); +// Waits for the fb_post to be called +void wait4fbPost(hwc_context_t* ctx); + +// Waits for the fb_post to finish PAN (primary commit) +void wait4Pan(hwc_context_t* ctx); + // Inline utility functions static inline bool isSkipLayer(const hwc_layer_t* l) { return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER))); diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp index 6fd1eb8..e020a59 100644 --- a/liboverlay/overlayMdp.cpp +++ b/liboverlay/overlayMdp.cpp @@ -127,15 +127,17 @@ void MdpCtrl::doTransform() { bool MdpCtrl::set() { //deferred calcs, so APIs could be called in any order. doTransform(); - if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) { - ALOGE("MdpCtrl failed to setOverlay, restoring last known " - "good ov info"); - mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo); - mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo); - this->restore(); - return false; + if(this->ovChanged()) { + if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) { + ALOGE("MdpCtrl failed to setOverlay, restoring last known " + "good ov info"); + mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo); + mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo); + this->restore(); + return false; + } + this->save(); } - this->save(); return true; }