YUV layer updates during animation and popups.
-- During animation, if yuv layer is marked skip close overlay channels. But if HDMI is connected, let them remain open, and send data. -- During popups on paused video, if the layer above it is skip, let the video layer be displayed via overlay. -- Fix MDP pipe closing mechanism for yuv content. -- Synchronize notification to gralloc with actual video channel status. CRs-Fixed: 342892 Change-Id: I98f442c12e59e4fcf93af87a251e3d489e624c0b (cherry picked from commit 752ee11eb0318dbb2bfdc5200c320cd2db972eb9)
This commit is contained in:
		
				
					committed by
					
						 Andrew Sutherland
						Andrew Sutherland
					
				
			
			
				
	
			
			
			
						parent
						
							d6ffef4cef
						
					
				
				
					commit
					4e0b4170a1
				
			| @@ -81,6 +81,8 @@ struct hwc_context_t { | ||||
|     /* our private state goes below here */ | ||||
|     overlay::Overlay* mOverlayLibObject; | ||||
|     native_handle_t *previousOverlayHandle; | ||||
|     native_handle_t *currentOverlayHandle; | ||||
|     int yuvBufferCount; | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|     overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS]; | ||||
|     native_handle_t* previousBypassHandle[MAX_BYPASS_LAYERS]; | ||||
| @@ -542,6 +544,40 @@ void closeExtraPipes(hwc_context_t* ctx) { | ||||
| } | ||||
| #endif  //COMPOSITION_BYPASS | ||||
|  | ||||
|  | ||||
| // Returns true if external panel is connected | ||||
| static inline bool isExternalConnected(const hwc_context_t* ctx) { | ||||
| #if defined HDMI_DUAL_DISPLAY | ||||
|     return (ctx->mHDMIEnabled != EXT_TYPE_NONE); | ||||
| #endif | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| // Returns true if we have a skip layer | ||||
| static inline bool isSkipLayer(const hwc_layer_t* layer) { | ||||
|     return (layer && (layer->flags & HWC_SKIP_LAYER)); | ||||
| } | ||||
|  | ||||
| // Returns true if the buffer is yuv | ||||
| static inline bool isYuvBuffer(const private_handle_t* hnd) { | ||||
|     return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)); | ||||
| } | ||||
|  | ||||
| //Return true if buffer is marked locked | ||||
| static inline bool isBufferLocked(const private_handle_t* hnd) { | ||||
|     return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags)); | ||||
| } | ||||
|  | ||||
| //Marks layers for GPU composition | ||||
| static inline void markForGPUComp(const hwc_context_t *ctx, | ||||
|     hwc_layer_list_t* list, const int limit) { | ||||
|     for(int i = 0; i < limit; i++) { | ||||
|         list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | ||||
|         list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) { | ||||
| #if defined HDMI_DUAL_DISPLAY | ||||
|     private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>( | ||||
| @@ -563,28 +599,6 @@ static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void setHWCOverlayStatus(hwc_context_t *ctx, bool isVideoPresent) { | ||||
|  | ||||
|     switch (ctx->hwcOverlayStatus) { | ||||
|         case HWC_OVERLAY_OPEN: | ||||
|             ctx->hwcOverlayStatus = | ||||
|                 isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_PREPARE_TO_CLOSE; | ||||
|         break; | ||||
|         case HWC_OVERLAY_PREPARE_TO_CLOSE: | ||||
|             ctx->hwcOverlayStatus = | ||||
|                 isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED; | ||||
|         break; | ||||
|         case HWC_OVERLAY_CLOSED: | ||||
|             ctx->hwcOverlayStatus = | ||||
|                 isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED; | ||||
|         break; | ||||
|         default: | ||||
|           LOGE("%s: Invalid hwcOverlayStatus (status =%d)", __FUNCTION__, | ||||
|                 ctx->hwcOverlayStatus); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int hwc_closeOverlayChannels(hwc_context_t* ctx) { | ||||
| #ifdef USE_OVERLAY | ||||
|     overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; | ||||
| @@ -600,6 +614,7 @@ static int hwc_closeOverlayChannels(hwc_context_t* ctx) { | ||||
|         ovLibObject->closeChannel(); | ||||
|         // Inform the gralloc that video overlay has stopped. | ||||
|         setVideoOverlayStatusInGralloc(ctx, false); | ||||
|         ctx->hwcOverlayStatus = HWC_OVERLAY_CLOSED; | ||||
|     } | ||||
| #endif | ||||
|     return 0; | ||||
| @@ -698,21 +713,19 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const int flag | ||||
|  | ||||
| void unlockPreviousOverlayBuffer(hwc_context_t* ctx) | ||||
| { | ||||
|     if (ctx->previousOverlayHandle) { | ||||
|         // Validate the handle before attempting to use it. | ||||
|         if (!private_handle_t::validate(ctx->previousOverlayHandle)) { | ||||
|             private_handle_t *hnd = (private_handle_t*)ctx->previousOverlayHandle; | ||||
|             // Unlock any previously locked buffers | ||||
|             if (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags) { | ||||
|                 if (GENLOCK_NO_ERROR == genlock_unlock_buffer(ctx->previousOverlayHandle)) { | ||||
|                     ctx->previousOverlayHandle = NULL; | ||||
|                     hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|                 } else { | ||||
|                     LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|                 } | ||||
|     private_handle_t *hnd = (private_handle_t*)ctx->previousOverlayHandle; | ||||
|     if (isBufferLocked(hnd) && !private_handle_t::validate(hnd)) { | ||||
|         if (GENLOCK_NO_ERROR == genlock_unlock_buffer(hnd)) { | ||||
|             //If previous is same as current, keep locked. | ||||
|             if(hnd != ctx->currentOverlayHandle) { | ||||
|                 hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|             } | ||||
|         } else { | ||||
|             LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|         } | ||||
|     } | ||||
|     ctx->previousOverlayHandle = ctx->currentOverlayHandle; | ||||
|     ctx->currentOverlayHandle = NULL; | ||||
| } | ||||
|  | ||||
| bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayerCount, | ||||
| @@ -872,9 +885,6 @@ static int getYUVBufferCount (const hwc_layer_list_t* list) { | ||||
|             if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && | ||||
|                !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) { | ||||
|                 yuvBufferCount++; | ||||
|                 if (yuvBufferCount > 1) { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -956,9 +966,11 @@ static int getLayersNotUpdatingCount(const hwc_layer_list_t* list) { | ||||
|     return numLayersNotUpdating; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|  | ||||
|     hwc_context_t* ctx = (hwc_context_t*)(dev); | ||||
|     ctx->currentOverlayHandle = NULL; | ||||
|  | ||||
|     if(!ctx) { | ||||
|         LOGE("hwc_prepare invalid context"); | ||||
| @@ -989,11 +1001,16 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|  | ||||
|     if (list) { | ||||
|         useCopybit = canUseCopybit(hwcModule->fbDevice, list); | ||||
|         yuvBufferCount = getYUVBufferCount(list); | ||||
|         ctx->yuvBufferCount = getYUVBufferCount(list); | ||||
|         yuvBufferCount = ctx->yuvBufferCount; | ||||
|         numLayersNotUpdating = getLayersNotUpdatingCount(list); | ||||
|         skipComposition = canSkipComposition(ctx, yuvBufferCount, | ||||
|                                 list->numHwLayers, numLayersNotUpdating); | ||||
|  | ||||
|         if ((yuvBufferCount == 0) && (ctx->hwcOverlayStatus == HWC_OVERLAY_OPEN)) { | ||||
|             ctx->hwcOverlayStatus = HWC_OVERLAY_PREPARE_TO_CLOSE; | ||||
|         } | ||||
|  | ||||
|         if (yuvBufferCount == 1) { | ||||
|             s3dVideoFormat = getS3DVideoFormat(list); | ||||
|             if (s3dVideoFormat) | ||||
| @@ -1005,61 +1022,57 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|             unlockPreviousOverlayBuffer(ctx); | ||||
|         } | ||||
|  | ||||
|         if (list->flags & HWC_GEOMETRY_CHANGED) { | ||||
|             if (yuvBufferCount == 1) { | ||||
|                 // Inform the gralloc of the current video overlay status | ||||
|                 setVideoOverlayStatusInGralloc(ctx, true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (size_t i=0 ; i<list->numHwLayers ; i++) { | ||||
|             private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; | ||||
|  | ||||
|             // If there is a single Fullscreen layer, we can bypass it - TBD | ||||
|             // If there is only one video/camera buffer, we can bypass itn | ||||
|             if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { | ||||
|                 // During the animaton UI layers are marked as SKIP | ||||
|                 // need to still mark the layer for S3D composition | ||||
|             if (isSkipLayer(&list->hwLayers[i])) { | ||||
|                 isSkipLayerPresent = true; | ||||
|                 skipComposition = false; | ||||
|                 //Reset count, so that we end up composing once after animation | ||||
|                 //is over, in case of overlay. | ||||
|                 ctx->previousLayerCount = -1; | ||||
|  | ||||
|                 //If YUV layer is marked as SKIP, close pipes. | ||||
|                 //If External is connected we still want to pump data to it, | ||||
|                 //so keep the pipes open. | ||||
|                 if(isYuvBuffer(hnd) && !isExternalConnected(ctx)) { | ||||
|                     if (ctx->hwcOverlayStatus == HWC_OVERLAY_OPEN) | ||||
|                         ctx->hwcOverlayStatus = HWC_OVERLAY_PREPARE_TO_CLOSE; | ||||
|                     unlockPreviousOverlayBuffer(ctx); | ||||
|                 } | ||||
|                 // During the animaton UI layers are marked as SKIP | ||||
|                 // need to still mark the layer for S3D composition | ||||
|                 if (isS3DCompositionNeeded) | ||||
|                     markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat); | ||||
|  | ||||
|                 ssize_t layer_countdown = ((ssize_t)i); | ||||
|                 // Mark every layer below the SKIP layer to be composed by the GPU | ||||
|                 while (layer_countdown >= 0) | ||||
|                 { | ||||
|                     private_handle_t *countdown_handle = | ||||
|                                (private_handle_t *)list->hwLayers[layer_countdown].handle; | ||||
|                     if (countdown_handle && (countdown_handle->bufferType == BUFFER_TYPE_VIDEO) | ||||
|                         && (yuvBufferCount == 1)) { | ||||
|                         unlockPreviousOverlayBuffer(ctx); | ||||
|                     } | ||||
|                     list->hwLayers[layer_countdown].compositionType = HWC_FRAMEBUFFER; | ||||
|                     list->hwLayers[layer_countdown].hints &= ~HWC_HINT_CLEAR_FB; | ||||
|                     layer_countdown--; | ||||
|                 } | ||||
|                 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | ||||
|                 list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB; | ||||
|                 markForGPUComp(ctx, list, i); | ||||
|             } else if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { | ||||
|                 setVideoOverlayStatusInGralloc(ctx, true); | ||||
|                 int flags = WAIT_FOR_VSYNC; | ||||
|                 flags |= (1 == list->numHwLayers) ? DISABLE_FRAMEBUFFER_FETCH : 0; | ||||
|                 if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) { | ||||
|                     list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | ||||
|                     list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB; | ||||
|                     //Even though there are no skip layers, animation is still | ||||
|                     //ON and in its final stages. | ||||
|                     //Reset count, so that we end up composing once after animation | ||||
|                     //is done, if overlay is used. | ||||
|                     ctx->previousLayerCount = -1; | ||||
|                     skipComposition = false; | ||||
|                     if (ctx->hwcOverlayStatus == HWC_OVERLAY_OPEN) | ||||
|                         ctx->hwcOverlayStatus = HWC_OVERLAY_PREPARE_TO_CLOSE; | ||||
|                     unlockPreviousOverlayBuffer(ctx); | ||||
| #ifdef USE_OVERLAY | ||||
|                 } else if(prepareOverlay(ctx, &(list->hwLayers[i]), flags) == 0) { | ||||
|                     list->hwLayers[i].compositionType = HWC_USE_OVERLAY; | ||||
|                     list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; | ||||
|                     // We've opened the channel. Set the state to open. | ||||
|                     ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN; | ||||
|  | ||||
| #endif | ||||
|                 } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D| | ||||
|                             COMPOSITION_TYPE_MDP)) { | ||||
| @@ -1076,6 +1089,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|                     skipComposition = false; | ||||
|                 } | ||||
|             } else if (getLayerS3DFormat(list->hwLayers[i])) { | ||||
|                 setVideoOverlayStatusInGralloc(ctx, true); | ||||
|                 int flags = WAIT_FOR_VSYNC; | ||||
|                 flags |= (1 == list->numHwLayers) ? DISABLE_FRAMEBUFFER_FETCH : 0; | ||||
| #ifdef USE_OVERLAY | ||||
| @@ -1394,6 +1408,7 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) | ||||
|             LOGE("drawLayerUsingLayer null module "); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         private_handle_t *hnd = (private_handle_t *)layer->handle; | ||||
|         overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; | ||||
|         int ret = 0; | ||||
| @@ -1407,19 +1422,15 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) | ||||
|  | ||||
|         ret = ovLibObject->queueBuffer(hnd); | ||||
|  | ||||
|         // Unlock the previously locked buffer, since the overlay has completed reading the buffer | ||||
|         unlockPreviousOverlayBuffer(ctx); | ||||
|  | ||||
|         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; | ||||
|             hnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|             ctx->currentOverlayHandle = hnd; | ||||
|         } | ||||
|  | ||||
|         return ret; | ||||
| @@ -1552,6 +1563,10 @@ static int hwc_set(hwc_composer_device_t *dev, | ||||
|             CALC_FPS(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Unlock the previously locked buffer, since the overlay has completed reading the buffer | ||||
|     unlockPreviousOverlayBuffer(ctx); | ||||
|  | ||||
| #if defined HDMI_DUAL_DISPLAY | ||||
|     if(ctx->pendingHDMI) { | ||||
|         handleHDMIStateChange(dev, ctx->mHDMIEnabled); | ||||
| @@ -1560,9 +1575,6 @@ static int hwc_set(hwc_composer_device_t *dev, | ||||
| #endif | ||||
|  | ||||
|     hwc_closeOverlayChannels(ctx); | ||||
|     int yuvBufferCount = getYUVBufferCount(list); | ||||
|     setHWCOverlayStatus(ctx, yuvBufferCount); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| @@ -1696,6 +1708,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, | ||||
|         dev->pendingHDMI = false; | ||||
| #endif | ||||
|         dev->previousOverlayHandle = NULL; | ||||
|         dev->currentOverlayHandle = NULL; | ||||
|         dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED; | ||||
|         dev->previousLayerCount = -1; | ||||
|         char value[PROPERTY_VALUE_MAX]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user