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:
parent
36de7a412e
commit
cc18cfed4c
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user