Merge "hwc: Add target specific checks in hwcomposer"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 9f95667..a69e6ee 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -547,6 +547,71 @@
size = getSize(format, width, height, alignedw, alignedh);
}
+int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
+{
+ int err = 0;
+ size_t ystride, cstride;
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+ // Get the chroma offsets from the handle width/height. We take advantage
+ // of the fact the width _is_ the stride
+ switch (hnd->format) {
+ //Semiplanar
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
+ ystride = hnd->width;
+ cstride = hnd->width/2;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ ystride = hnd->width;
+ cstride = hnd->width/2;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2;
+ break;
+
+ //Planar
+ case HAL_PIXEL_FORMAT_YV12:
+ ystride = hnd->width;
+ cstride = hnd->width/2;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
+ cstride * hnd->height/2);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 1;
+
+ break;
+ //Unsupported formats
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ default:
+ ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
+ hnd->format);
+ err = -EINVAL;
+ }
+ return err;
+
+}
+
// Allocate buffer from width, height and format into a
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index fbde8c2..32f3256 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -69,6 +69,7 @@
// It is the responsibility of the caller to free the buffer
int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
void free_buffer(private_handle_t *hnd);
+int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
/*****************************************************************************/
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index b2714c5..8704354 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -82,6 +82,7 @@
GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
+ GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
};
#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index c419da6..4adc67d 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -259,28 +259,8 @@
{
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage);
- size_t ystride, cstride;
- if(!err) {
- //hnd->format holds our implementation defined format
- //HAL_PIXEL_FORMAT_YCrCb_420_SP is the only one set right now.
- switch (hnd->format) {
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- ystride = ALIGN(hnd->width, 16);
- cstride = ALIGN(hnd->width, 16)/2;
- ycbcr->y = (void*)hnd->base;
- ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
- ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
- ycbcr->ystride = ystride;
- ycbcr->cstride = cstride;
- ycbcr->chroma_step = 2;
- memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
- break;
- default:
- ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
- hnd->format);
- err = -EINVAL;
- }
- }
+ if(!err)
+ err = getYUVPlaneInfo(hnd, ycbcr);
return err;
}
@@ -447,6 +427,15 @@
res = 0;
}
} break;
+ case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
+ if (private_handle_t::validate(hnd)) {
+ res = getYUVPlaneInfo(hnd, ycbcr);
+ }
+ } break;
+
default:
break;
}
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index aa7a187..a2c7ad3 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -260,6 +260,48 @@
}
}
+static bool optimizePrepare(hwc_context_t *ctx, int numDisplays,
+ hwc_display_contents_1_t** displays) {
+
+ /* Do not re-program H/W, if frame geometry has not changed.
+ * But honor these exceptions:
+ * 1. Padding round
+ * 2. Idle fallback
+ * 3. Overlay is not configured
+ * 4. External/Virtual display is in Configure state
+ * 5. External/Virtual is Paused OR not connected/active
+ * 6. Non-Overlay device
+ */
+
+ if (ctx->isPaddingRound || MDPComp::isIdleFallback() ||
+ !ctx->mOverlay->isConfigured() || isSecondaryConfiguring(ctx) ||
+ ctx->mMDP.version < qdutils::MDP_V4_0) {
+ return false;
+ }
+
+ bool isOptimized = false;
+ for (uint32_t i = 0; i < numDisplays; i++) {
+ hwc_display_contents_1_t *list = displays[i];
+
+ if (list) {
+ if (list->flags & HWC_GEOMETRY_CHANGED) {
+ return false;
+ }
+ int dpy = getDpyforExternalDisplay(ctx, i);
+ if (dpy && (ctx->dpyAttr[dpy].isPause ||
+ !ctx->dpyAttr[dpy].connected ||
+ !ctx->dpyAttr[dpy].isActive)) {
+ return false;
+ }
+ // Set layer composition type as per last frame
+ ctx->mMDPComp[dpy]->setMDPCompLayerFlags(ctx, list);
+ isOptimized = true;
+ }
+ }
+
+ return isOptimized;
+}
+
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) {
ATRACE_CALL();
@@ -279,7 +321,10 @@
if (fbComp) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
if (ctx->mMDP.version < qdutils::MDP_V4_0) {
@@ -306,7 +351,11 @@
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
} else {
/* External Display is in Pause state.
@@ -338,6 +387,12 @@
setPaddingRound(ctx,numDisplays,displays);
setDMAState(ctx,numDisplays,displays);
setNumActiveDisplays(ctx,numDisplays,displays);
+
+ if (optimizePrepare(ctx, numDisplays, displays)) {
+ // Do not re-program H/W, if it is not needed
+ return ret;
+ }
+
reset(ctx, (int)numDisplays, displays);
ctx->mOverlay->configBegin();
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 0843da4..d7afa19 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -158,7 +158,10 @@
//framebuffers
if ( updatingLayerCount == 1 ) {
- hwc_rect_t dirtyRect =list->hwLayers[changingLayerIndex].dirtyRect;
+ hwc_rect_t dirtyRect = list->hwLayers[changingLayerIndex].displayFrame;
+#ifdef QCOM_BSP
+ dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
+#endif
for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
//disable swap rect for overlapping visible layer(s)
@@ -379,7 +382,11 @@
mDirtyLayerIndex = checkDirtyRect(ctx, list, dpy);
if( mDirtyLayerIndex != -1){
hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
+#ifdef QCOM_BSP
clear(renderBuffer,layer->dirtyRect);
+#else
+ clear(renderBuffer,layer->displayFrame);
+#endif
} else {
hwc_rect_t clearRegion = {0,0,0,0};
if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
@@ -509,6 +516,7 @@
copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
displayFrame.right,
displayFrame.bottom};
+#ifdef QCOM_BSP
//change src and dst with dirtyRect
if(mDirtyLayerIndex != -1) {
srcRect.l = layer->dirtyRect.left;
@@ -517,6 +525,7 @@
srcRect.b = layer->dirtyRect.bottom;
dstRect = srcRect;
}
+#endif
// Copybit dst
copybit_image_t dst;
dst.w = ALIGN(fbHandle->width,32);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 0374dec..a58ea07 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -208,8 +208,6 @@
sourceCrop, mdpFlags, rotFlags);
if(!ret) {
ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
- ctx->mOverlay->clear(mDpy);
- ctx->mLayerRotMap[mDpy]->clear();
return false;
}
//For the mdp, since either we are pre-rotating or MDP does flips
@@ -224,7 +222,6 @@
if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
NULL, mDest) < 0) {
ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
- ctx->mLayerRotMap[mDpy]->clear();
ret = false;
}
}
@@ -387,10 +384,6 @@
ret = false;
}
}
-
- if(ret == false) {
- ctx->mLayerRotMap[mDpy]->clear();
- }
}
return ret;
}
@@ -425,7 +418,6 @@
bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
hwc_rect_t fbUpdatingRect, int fbZorder) {
- bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
// ext only layer present..
@@ -502,7 +494,6 @@
if(configMdp(ctx->mOverlay, parg, orient,
cropL, cropL, NULL /*metadata*/, destL) < 0) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
- ctx->mLayerRotMap[mDpy]->clear();
return false;
}
}
@@ -512,7 +503,6 @@
if(configMdp(ctx->mOverlay, parg, orient,
cropR, cropR, NULL /*metadata*/, destR) < 0) {
ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
- ctx->mLayerRotMap[mDpy]->clear();
return false;
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index d008147..581f57c 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -479,43 +479,44 @@
return true;
}
+bool MDPComp::canDoPartialUpdate(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() || mDpy ||
+ isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED)||
+ isDisplaySplit(ctx, mDpy)) {
+ return false;
+ }
+ return true;
+}
+
void MDPComp::generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- if(!sEnablePartialFrameUpdate) {
- return;
- }
-
- if(mDpy || isDisplaySplit(ctx, mDpy)){
- ALOGE_IF(isDebug(), "%s: ROI not supported for"
- "the (1) external / virtual display's (2) dual DSI displays",
- __FUNCTION__);
- return;
- }
-
- if(isSkipPresent(ctx, mDpy))
- return;
-
- if(list->flags & HWC_GEOMETRY_CHANGED)
+ if(!canDoPartialUpdate(ctx, list))
return;
struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
for(int index = 0; index < numAppLayers; index++ ) {
- if ((mCachedFrame.hnd[index] != list->hwLayers[index].handle) ||
- isYuvBuffer((private_handle_t *)list->hwLayers[index].handle)) {
- hwc_rect_t dstRect = list->hwLayers[index].displayFrame;
- hwc_rect_t srcRect = integerizeSourceCrop(
- list->hwLayers[index].sourceCropf);
-
- /* Intersect against display boundaries */
- roi = getUnion(roi, dstRect);
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ if ((mCachedFrame.hnd[index] != layer->handle) ||
+ isYuvBuffer((private_handle_t *)layer->handle)) {
+ hwc_rect_t updatingRect = layer->displayFrame;
+#ifdef QCOM_BSP
+ if(!needsScaling(layer))
+ updatingRect = layer->dirtyRect;
+#endif
+ roi = getUnion(roi, updatingRect);
}
}
- if(!validateAndApplyROI(ctx, list, roi)){
- roi = (struct hwc_rect) {0, 0,
- (int)ctx->dpyAttr[mDpy].xres, (int)ctx->dpyAttr[mDpy].yres};
- }
+ hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+ (int)ctx->dpyAttr[mDpy].yres};
+
+ // Align ROI coordinates to panel restrictions
+ roi = sanitizeROI(roi, fullFrame);
+
+ if(!validateAndApplyROI(ctx, list, roi))
+ roi = fullFrame;
ctx->listStats[mDpy].roi.x = roi.left;
ctx->listStats[mDpy].roi.y = roi.top;
@@ -616,15 +617,6 @@
ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
return false;
}
-
- //For 8x26, if there is only one layer which needs scale for secondary
- //while no scale for primary display, DMA pipe is occupied by primary.
- //If need to fall back to GLES composition, virtual display lacks DMA
- //pipe and error is reported.
- if(qdutils::MDPVersion::getInstance().is8x26() &&
- mDpy >= HWC_DISPLAY_EXTERNAL &&
- qhwc::needsScaling(layer))
- return false;
}
mCurrentFrame.fbCount = 0;
@@ -1412,6 +1404,7 @@
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
pipeSpecs.dpy = mDpy;
pipeSpecs.fb = false;
+ pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index beb858b..7d4214a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -54,6 +54,9 @@
static void resetIdleFallBack() { sIdleFallBack = false; }
static void reset() { sHandleTimeout = false; };
static bool isIdleFallback() { return sIdleFallBack; }
+ /* set/reset flags for MDPComp */
+ void setMDPCompLayerFlags(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
protected:
enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -142,9 +145,6 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair) = 0;
- /* set/reset flags for MDPComp */
- void setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
void setRedraw(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
/* checks for conditions where mdpcomp is not possible */
@@ -213,6 +213,7 @@
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
bool resourceCheck();
hwc_rect_t getUpdatingFBRect(hwc_display_contents_1_t* list);
+ bool canDoPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
int mDpy;
static bool sEnabled;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index efeff98..699db24 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1177,6 +1177,11 @@
layer->sourceCropf.top = (float)bottomCrop.top;
layer->sourceCropf.right = (float)bottomCrop.right;
layer->sourceCropf.bottom = (float)bottomCrop.bottom;
+#ifdef QCOM_BSP
+ //Update layer dirtyRect
+ layer->dirtyRect = getIntersection(bottomCrop,
+ layer->dirtyRect);
+#endif
}
}
j--;
@@ -2157,4 +2162,58 @@
}
}
+hwc_rect_t sanitizeROI(struct hwc_rect roi, hwc_rect boundary)
+{
+ if(!isValidRect(roi))
+ return roi;
+
+ struct hwc_rect t_roi = roi;
+
+ const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
+ const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
+ const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
+ const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
+ const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
+
+ /* Align to minimum width recommended by the panel */
+ if((t_roi.right - t_roi.left) < MIN_WIDTH) {
+ if((t_roi.left + MIN_WIDTH) > boundary.right)
+ t_roi.left = t_roi.right - MIN_WIDTH;
+ else
+ t_roi.right = t_roi.left + MIN_WIDTH;
+ }
+
+ /* Align left and width to meet panel restrictions */
+ if(WIDTH_ALIGN) {
+ int width = t_roi.right - t_roi.left;
+ width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
+ t_roi.right = t_roi.left + width;
+
+ if(t_roi.right > boundary.right) {
+ t_roi.right = boundary.right;
+ t_roi.left = t_roi.right - width;
+ }
+ }
+
+ if(LEFT_ALIGN)
+ t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+
+ /* Align top and height to meet panel restrictions */
+ if(HEIGHT_ALIGN) {
+ int height = t_roi.bottom - t_roi.top;
+ height = HEIGHT_ALIGN * ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
+ t_roi.bottom = t_roi.top + height;
+
+ if(t_roi.bottom > boundary.bottom) {
+ t_roi.bottom = boundary.bottom;
+ t_roi.top = t_roi.bottom - height;
+ }
+ }
+
+ if(TOP_ALIGN)
+ t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+
+ return t_roi;
+}
+
};//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 6fe993a..6f527aa 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -295,6 +295,9 @@
/* Get External State names */
const char* getExternalDisplayState(uint32_t external_state);
+// Aligns updating ROI to panel restrictions
+hwc_rect_t sanitizeROI(struct hwc_rect roi, hwc_rect boundary);
+
// Handles wfd Pause and resume events
void handle_pause(hwc_context_t *ctx, int dpy);
void handle_resume(hwc_context_t *ctx, int dpy);
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 10ed9d1..97b19ea 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -126,7 +126,11 @@
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
} else {
/* Virtual Display is in Pause state.
@@ -260,7 +264,11 @@
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
} else {
/* Virtual Display is in Pause state.
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index f4b0ecc..d53b46d 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -203,7 +203,9 @@
if(pipeSpecs.formatClass == FORMAT_YUV) { //video
return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
} else if(pipeSpecs.fb == false) { //RGB app layers
- if(not pipeSpecs.needsScaling) {
+ if((not pipeSpecs.needsScaling) and
+ (not (pipeSpecs.numActiveDisplays > 1 &&
+ pipeSpecs.dpy == DPY_PRIMARY))) {
dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
}
if(dest == OV_INVALID) {
@@ -220,7 +222,9 @@
dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
}
}
- if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
+ if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
+ (not (pipeSpecs.numActiveDisplays > 1 &&
+ pipeSpecs.dpy == DPY_PRIMARY))) {
dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
}
}
@@ -233,23 +237,15 @@
eDest dest = OV_INVALID;
if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
- } else if(pipeSpecs.fb == false) { //RGB app layers
+ } else {
//Since this is a specific func, we can assume stuff like RGB pipe not
//having scalar blocks
dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
if(dest == OV_INVALID) {
dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
}
- } else {
- //For 8x16 Secondary we use DMA always for FB for inline rotation
- if(pipeSpecs.dpy == DPY_PRIMARY) {
- dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
- if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
- }
- }
if(dest == OV_INVALID) {
- dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
}
}
return dest;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 0b785d5..17c75e8 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -57,12 +57,13 @@
struct PipeSpecs {
PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false),
- dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT) {}
+ dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {}
int formatClass;
bool needsScaling;
bool fb;
int dpy;
int mixer;
+ int numActiveDisplays;
};
/* dtor close */
@@ -139,6 +140,8 @@
void clear(int dpy);
/* Validate the set of pipes for a display and set them in driver */
bool validateAndSet(const int& dpy, const int& fbFd);
+ /* Returns true if PipeBook has been configured, false otherwise */
+ bool isConfigured();
/* Closes open pipes, called during startup */
static int initOverlay();
@@ -203,6 +206,7 @@
static void resetAllocation(int index);
static bool isAllocated(int index);
static bool isNotAllocated(int index);
+ static bool isConfigured();
static utils::eMdpPipeType getPipeType(utils::eDest dest);
static const char* getDestStr(utils::eDest dest);
@@ -405,6 +409,14 @@
return "Invalid";
}
+inline bool Overlay::PipeBook::isConfigured() {
+ return (sAllocatedBitmap != 0);
+}
+
+inline bool Overlay::isConfigured() {
+ return PipeBook::isConfigured();
+}
+
}; // overlay
#endif // OVERLAY_H