hwc/fb/overlay: wait for fbpost and pan display

Draw sequence in hwc_set
--eglSwapBuffers
--wait for fb_post. Its ok to draw to External only at this point.
--draw to external   | Parallel with PAN
--commit to external | Parallel with PAN
--wait for pan (happening in fb_post) to finish.

Call MSMFB_OVERLAY_SET ioctl only when params change.

These thing together ensure a correct sequence and should fix tearing and
stuttering, the latter assuming there are no other display pipeline delays.

Change-Id: Ibb0ad8485fa6b30dc6ac07ae8b25a760941c08ce
(cherry picked from commit c50c90863e41e31ecfe6963396b5def35e9dca34)
This commit is contained in:
Arun Kumar K.R 2012-08-17 19:47:52 -07:00 committed by Andrew Sutherland
parent 36de7a412e
commit cc18cfed4c
7 changed files with 64 additions and 15 deletions

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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();

View File

@ -129,13 +129,6 @@ bool UIMirrorOverlay::draw(hwc_context_t *ctx)
if(fbDev) {
private_module_t* m = reinterpret_cast<private_module_t*>(
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,

View File

@ -17,6 +17,8 @@
#include <overlay.h>
#include <cutils/properties.h>
#include <gralloc_priv.h>
#include <fb_priv.h>
#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<private_module_t*>(
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<private_module_t*>(
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

View File

@ -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)));

View File

@ -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;
}