From b0e7470e4ffc988c6e5be3903124cc3cfef5088c Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 29 Nov 2011 19:12:53 -0800 Subject: [PATCH] libhwcomposer: Lock/unlock bypass buffers using genlock Use genlock to lock the bypass buffers before they are queued to the overlay. After all the bypass buffers are queued, use genlock to unlock the previously locked bypass buffers. Change-Id: Ifdd7921f0c9f5d5744c899a0257a4b954274334b --- libhwcomposer/hwcomposer.cpp | 76 +++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 6fa6b41..e1f72a5 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -83,6 +83,11 @@ enum { MAX_BYPASS_LAYERS = 2, ANIM_FRAME_COUNT = 30, }; + +enum BypassBufferLockState { + BYPASS_BUFFER_UNLOCKED, + BYPASS_BUFFER_LOCKED, +}; #endif enum eHWCOverlayStatus { @@ -98,6 +103,8 @@ struct hwc_context_t { native_handle_t *previousOverlayHandle; #ifdef COMPOSITION_BYPASS overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS]; + native_handle_t* previousBypassHandle[MAX_BYPASS_LAYERS]; + BypassBufferLockState bypassBufferLockState[MAX_BYPASS_LAYERS]; int animCount; BypassState bypassState; #endif @@ -229,14 +236,30 @@ static int hwc_closeOverlayChannels(hwc_context_t* ctx) { #ifdef COMPOSITION_BYPASS // To-do: Merge this with other blocks & move them to a separate file. +void unlockPreviousBypassBuffers(hwc_context_t* ctx) { + // Unlock the previous bypass buffers. We can blindly unlock the buffers here, + // because buffers will be in this list only if the lock was successfully acquired. + for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { + if (ctx->previousBypassHandle[i]) { + private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i]; + if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousBypassHandle[i])) { + LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); + } else { + ctx->previousBypassHandle[i] = NULL; + } + } + } +} + void closeBypass(hwc_context_t* ctx) { - for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { - ctx->mOvUI[index]->closeChannel(); + unlockPreviousBypassBuffers(ctx); + for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { + ctx->mOvUI[index]->closeChannel(); + } #ifdef DEBUG LOGE("%s", __FUNCTION__); #endif } -} #endif /* @@ -461,9 +484,20 @@ static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer, overlay::OverlayUI *ovUI = ctx->mOvUI[index]; int ret = 0; private_handle_t *hnd = (private_handle_t *)layer->handle; + if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, + GENLOCK_MAX_TIMEOUT)) { + LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); + return -1; + } + ctx->bypassBufferLockState[index] = BYPASS_BUFFER_LOCKED; ret = ovUI->queueBuffer(hnd); if (ret) { LOGE("drawLayerUsingBypass queueBuffer failed"); + // Unlock the locked buffer + if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) { + LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); + } + ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED; return -1; } } @@ -572,6 +606,24 @@ void unsetBypassLayerFlags(hwc_layer_list_t* list) { } } +void unsetBypassBufferLockState(hwc_context_t* ctx) { + for (int i=0; i< MAX_BYPASS_LAYERS; i++) { + ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED; + } +} + +void storeLockedBypassHandle(hwc_layer_list_t* list, hwc_context_t* ctx) { + for (int index = 0 ; index < list->numHwLayers; index++) { + // Store the current bypass handle. + if (list->hwLayers[index].flags == HWC_COMP_BYPASS) { + private_handle_t *hnd = (private_handle_t*)list->hwLayers[index].handle; + if (ctx->bypassBufferLockState[index] == BYPASS_BUFFER_LOCKED) + ctx->previousBypassHandle[index] = (native_handle_t*)list->hwLayers[index].handle; + else + ctx->previousBypassHandle[index] = NULL; + } + } +} #endif //COMPOSITION_BYPASS @@ -835,7 +887,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { ctx->bypassState = BYPASS_ON; } } else { + unlockPreviousBypassBuffers(ctx); unsetBypassLayerFlags(list); + unsetBypassBufferLockState(ctx); if(ctx->bypassState == BYPASS_ON) { ctx->bypassState = BYPASS_OFF_PENDING; } @@ -1056,6 +1110,12 @@ static int hwc_set(hwc_composer_device_t *dev, } } +#ifdef COMPOSITION_BYPASS + unlockPreviousBypassBuffers(ctx); + storeLockedBypassHandle(list, ctx); + // We have stored the handles, unset the current lock states in the context. + unsetBypassBufferLockState(ctx); +#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); @@ -1114,9 +1174,11 @@ static int hwc_device_close(struct hw_device_t *dev) delete ctx->mOverlayLibObject; ctx->mOverlayLibObject = NULL; #ifdef COMPOSITION_BYPASS - for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { - delete ctx->mOvUI[i]; - } + for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { + delete ctx->mOvUI[i]; + } + unlockPreviousBypassBuffers(ctx); + unsetBypassBufferLockState(ctx); #endif free(ctx); } @@ -1193,7 +1255,9 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, #ifdef COMPOSITION_BYPASS for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { dev->mOvUI[i] = new overlay::OverlayUI(); + dev->previousBypassHandle[i] = NULL; } + unsetBypassBufferLockState(dev); dev->animCount = 0; dev->bypassState = BYPASS_OFF; #endif