From be1b5f3d66d063e7506ab32ad39556d3127031a5 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 21 Nov 2011 21:01:30 -0800 Subject: [PATCH] libhwcomposer: Use genlock to lock/unlock buffers for composition. For copybit composition, aquire a read lock on the buffer, before the blit operation and release the lock after the blit operation. For overlay, aquire a read lock on buffer N that is sent to the overlay. After the play call for buffer N returns, unlock the lock held by buffer (N-1). Change-Id: I3ff178d8ed8e3a289c199237dbec501afdb7e717 --- libhwcomposer/Android.mk | 4 ++ libhwcomposer/hwcomposer.cpp | 75 ++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 7 deletions(-) mode change 100644 => 100755 libhwcomposer/Android.mk mode change 100644 => 100755 libhwcomposer/hwcomposer.cpp diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk old mode 100644 new mode 100755 index 9338b1d..099ee2f --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -6,16 +6,20 @@ include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay +LOCAL_SHARED_LIBRARIES += libgenlock LOCAL_SRC_FILES := \ hwcomposer.cpp LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" + LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay LOCAL_C_INCLUDES += hardware/qcom/display/libcopybit +LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include + LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr ifeq ($(TARGET_HAVE_HDMI_OUT),true) LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp old mode 100644 new mode 100755 index e94549e..8a5676f --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -37,6 +37,7 @@ #include #include #include +#include /*****************************************************************************/ #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) @@ -94,6 +95,7 @@ struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; + native_handle_t *previousOverlayHandle; #ifdef COMPOSITION_BYPASS overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS]; int animCount; @@ -739,6 +741,12 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { s3dVideoFormat = getS3DVideoFormat(list); if (s3dVideoFormat) isS3DCompositionNeeded = isS3DCompositionRequired(); + } else { + if (ctx->previousOverlayHandle) { + // Unlock any previously locked buffers + if (GENLOCK_NO_ERROR == genlock_unlock_buffer(ctx->previousOverlayHandle)) + ctx->previousOverlayHandle = NULL; + } } if (list->flags & HWC_GEOMETRY_CHANGED) { @@ -763,7 +771,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { bool waitForVsync = skipComposition ? true:false; if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) { list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; - skipComposition = false; #ifdef USE_OVERLAY } else if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; @@ -778,11 +785,17 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { //Use C2D if available. list->hwLayers[i].compositionType = HWC_USE_COPYBIT; - skipComposition = false; } else { //If C2D is not enabled fall back to GPU. list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + } + if (HWC_USE_OVERLAY != list->hwLayers[i].compositionType) { + if (ctx->previousOverlayHandle) { + // Unlock any previously locked buffers before the fallback. + if (GENLOCK_NO_ERROR == genlock_unlock_buffer(ctx->previousOverlayHandle)) + ctx->previousOverlayHandle = NULL; + } skipComposition = false; } } else if (isS3DCompositionNeeded) { @@ -890,6 +903,14 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, return -1; } + // Lock this buffer for read. + genlock_lock_type lockType = GENLOCK_READ_LOCK; + int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT); + if (GENLOCK_FAILURE == err) { + LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); + return -1; + } + // Set the copybit source: copybit_image_t src; src.w = ALIGN(hnd->width, 32); @@ -915,11 +936,13 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface); if (!renderBuffer) { LOGE("eglGetRenderBufferANDROID returned NULL buffer"); + genlock_unlock_buffer(hnd); return -1; } private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; if(!fbHandle) { LOGE("Framebuffer handle is NULL"); + genlock_unlock_buffer(hnd); return -1; } dst.w = ALIGN(fbHandle->width,32); @@ -938,11 +961,17 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, (layer->blending == HWC_BLENDING_NONE) ? 0xFF : layer->alpha); copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); - int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); + err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); if(err < 0) LOGE("copybit stretch failed"); + // Unlock this buffer since copybit is done with it. + err = genlock_unlock_buffer(hnd); + if (GENLOCK_FAILURE == err) { + LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); + } + return err; } @@ -958,13 +987,37 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; int ret = 0; - ret = ovLibObject->queueBuffer(hnd); - if (!ret) { - LOGE("drawLayerUsingOverlay queueBuffer failed"); + // Lock this buffer for read. + if (GENLOCK_NO_ERROR != genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, + GENLOCK_MAX_TIMEOUT)) { + LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); return -1; } + + ret = ovLibObject->queueBuffer(hnd); + + // Unlock the previously locked buffer, since the overlay has completed reading the buffer + if (ctx->previousOverlayHandle) { + if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousOverlayHandle)) { + LOGE("%s: genlock_unlock_buffer for the previous handle failed", + __FUNCTION__); + } + } + + if (!ret) { + LOGE("drawLayerUsingOverlay queueBuffer failed"); + // Unlock the buffer handle + genlock_unlock_buffer(hnd); + ctx->previousOverlayHandle = NULL; + } else { + // Store the current buffer handle as the one that is to be unlocked after + // the next overlay play call. + ctx->previousOverlayHandle = hnd; + } + + return ret; } - return 0; + return -1; } static int hwc_set(hwc_composer_device_t *dev, @@ -1050,6 +1103,13 @@ static int hwc_device_close(struct hw_device_t *dev) hwcModule->fbDevice = NULL; } + if (ctx->previousOverlayHandle) { + if (GENLOCK_NO_ERROR != genlock_unlock_buffer(ctx->previousOverlayHandle)) { + LOGE("%s: genlock_unlock_buffer for the previous handle failed", + __FUNCTION__); + } + } + if (ctx) { delete ctx->mOverlayLibObject; ctx->mOverlayLibObject = NULL; @@ -1142,6 +1202,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->mHDMIEnabled = false; dev->pendingHDMI = false; #endif + dev->previousOverlayHandle = NULL; dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED; /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG;