diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk index a95babb..09021b8 100755 --- a/libgralloc/Android.mk +++ b/libgralloc/Android.mk @@ -45,8 +45,8 @@ ifeq ($(TARGET_HAVE_HDMI_OUT),true) LOCAL_SHARED_LIBRARIES += liboverlay endif -ifeq ($(TARGET_USES_SF_BYPASS),true) - LOCAL_CFLAGS += -DSF_BYPASS +ifeq ($(TARGET_HAVE_BYPASS),true) + LOCAL_CFLAGS += -DCOMPOSITION_BYPASS endif ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp index 19ee4d1..885c614 100644 --- a/libgralloc/framebuffer.cpp +++ b/libgralloc/framebuffer.cpp @@ -319,7 +319,7 @@ static void *disp_loop(void *ptr) pthread_mutex_lock(&(m->qlock)); // wait (sleep) while display queue is empty; - if (m->disp.isEmpty()) { + while (m->disp.isEmpty()) { pthread_cond_wait(&(m->qpost),&(m->qlock)); } @@ -347,6 +347,14 @@ static void *disp_loop(void *ptr) LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed"); } +#if defined COMPOSITION_BYPASS + //Signal so that we can close channels if we need to + pthread_mutex_lock(&m->bufferPostLock); + m->bufferPostDone = true; + pthread_cond_signal(&m->bufferPostCond); + pthread_mutex_unlock(&m->bufferPostLock); +#endif + #ifdef DEBUG_CALC_FPS if (debug_fps_level > 0) calc_fps(ns2us(systemTime())); #endif @@ -599,6 +607,34 @@ static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientati } #endif +//Wait until framebuffer content is displayed. +//This is called in the context of threadLoop. +//Display loop wakes this up after display. +static int fb_waitForBufferPost(struct framebuffer_device_t* dev) +{ +#if defined COMPOSITION_BYPASS + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->bufferPostLock); + while(m->bufferPostDone == false) { + pthread_cond_wait(&(m->bufferPostCond), &(m->bufferPostLock)); + } + pthread_mutex_unlock(&m->bufferPostLock); +#endif + return 0; +} + +static int fb_resetBufferPostStatus(struct framebuffer_device_t* dev) +{ +#if defined COMPOSITION_BYPASS + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->bufferPostLock); + m->bufferPostDone = false; + pthread_mutex_unlock(&m->bufferPostLock); +#endif + return 0; +} static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) { if (private_handle_t::validate(buffer) < 0) @@ -990,6 +1026,11 @@ int mapFrameBufferLocked(struct private_module_t* module) pthread_t hdmiUIThread; pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module); #endif +#if defined COMPOSITION_BYPASS + pthread_mutex_init(&(module->bufferPostLock), NULL); + pthread_cond_init(&(module->bufferPostCond), NULL); + module->bufferPostDone = false; +#endif return 0; } @@ -1053,6 +1094,11 @@ int fb_device_open(hw_module_t const* module, const char* name, dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio; #endif +#if defined COMPOSITION_BYPASS + dev->device.waitForBufferPost = fb_waitForBufferPost; + dev->device.resetBufferPostStatus = fb_resetBufferPostStatus; +#endif + private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); if (status >= 0) { diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index 6118001..0e45e4a 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -260,6 +260,11 @@ struct private_module_t { pthread_mutex_t overlayLock; pthread_cond_t overlayPost; #endif +#ifdef COMPOSITION_BYPASS + pthread_mutex_t bufferPostLock; + pthread_cond_t bufferPostCond; + bool bufferPostDone; +#endif }; /*****************************************************************************/ diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 9ad98c7..46962af 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -1091,6 +1091,9 @@ static int hwc_set(hwc_composer_device_t *dev, private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); + + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (!list || !hwcModule) { LOGE("hwc_set invalid list or module"); #ifdef COMPOSITION_BYPASS @@ -1124,16 +1127,29 @@ static int hwc_set(hwc_composer_device_t *dev, storeLockedBypassHandle(list, ctx); // We have stored the handles, unset the current lock states in the context. unsetBypassBufferLockState(ctx); + + //Setup for waiting until 1 FB post is done before closing bypass mode. + if (ctx->bypassState == BYPASS_OFF_PENDING) { + fbDev->resetBufferPostStatus(fbDev); + } #endif + // Do not call eglSwapBuffers if we the skip composition flag is set on the list. if (!(list->flags & HWC_SKIP_COMPOSITION)) { EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); if (!sucess) { ret = HWC_EGL_ERROR; + LOGE("eglSwapBuffers() failed in %s", __FUNCTION__); } } #ifdef COMPOSITION_BYPASS if(ctx->bypassState == BYPASS_OFF_PENDING) { + //Close channels only after fb content is displayed. + //We have already reset status before eglSwapBuffers. + if (!(list->flags & HWC_SKIP_COMPOSITION)) { + fbDev->waitForBufferPost(fbDev); + } + closeBypass(ctx); ctx->bypassState = BYPASS_OFF; }