Merge "hwc: Perform MDP downscaling for WFD/HDMI Scenario"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 50528c7..89ac919 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -75,9 +75,10 @@
static bool useUncached(int usage)
{
- if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED ||
- usage & GRALLOC_USAGE_SW_WRITE_RARELY ||
- usage & GRALLOC_USAGE_SW_READ_RARELY)
+ if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
+ return true;
+ if(((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY)
+ ||((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY))
return true;
return false;
}
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index f90420f..113e916 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -134,16 +134,11 @@
ctx->layerProp[dpy] = new LayerProp[numAppLayers];
}
-static int display_commit(hwc_context_t *ctx, int dpy) {
- struct mdp_display_commit commit_info;
- memset(&commit_info, 0, sizeof(struct mdp_display_commit));
- commit_info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
- if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_DISPLAY_COMMIT, &commit_info) < 0){
- ALOGE("%s: MSMFB_DISPLAY_COMMIT for dpy %d failed", __FUNCTION__,
- dpy);
- return -errno;
+static void handleGeomChange(hwc_context_t *ctx, int dpy,
+ hwc_display_contents_1_t *list) {
+ if(list->flags & HWC_GEOMETRY_CHANGED) {
+ ctx->mOverlay->forceSet(dpy);
}
- return 0;
}
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
@@ -153,6 +148,7 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive) {
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ handleGeomChange(ctx, dpy, list);
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(fbLayer->handle) {
@@ -179,6 +175,7 @@
ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected) {
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ handleGeomChange(ctx, dpy, list);
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(!ctx->dpyAttr[dpy].isPause) {
@@ -220,6 +217,7 @@
ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected) {
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ handleGeomChange(ctx, dpy, list);
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(!ctx->dpyAttr[dpy].isPause) {
@@ -257,10 +255,8 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- ctx->mBlankLock.lock();
//Will be unlocked at the end of set
- ctx->mExtLock.lock();
- ctx->mSecureLock.lock();
+ ctx->mDrawLock.lock();
reset(ctx, numDisplays, displays);
ctx->mOverlay->configBegin();
@@ -312,7 +308,7 @@
#ifdef QCOM_BSP
case HWC_EVENT_ORIENTATION:
if(dpy == HWC_DISPLAY_PRIMARY) {
- Locker::Autolock _l(ctx->mBlankLock);
+ Locker::Autolock _l(ctx->mDrawLock);
// store the primary display orientation
// will be used in hwc_video::configure to disable
// rotation animation on external display
@@ -331,7 +327,7 @@
ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev);
- Locker::Autolock _l(ctx->mBlankLock);
+ Locker::Autolock _l(ctx->mDrawLock);
int ret = 0, value = 0;
ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
blank==1 ? "Blanking":"Unblanking", dpy);
@@ -365,14 +361,22 @@
* activate/deactive VIRTUAL DISPLAY */
if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
- if(blank)
- display_commit(ctx, HWC_DISPLAY_VIRTUAL);
+ if(blank) {
+ int dpy = HWC_DISPLAY_VIRTUAL;
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
+ ret = -1;
+ }
+ }
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
}
break;
case HWC_DISPLAY_EXTERNAL:
if(blank) {
- display_commit(ctx, HWC_DISPLAY_EXTERNAL);
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail for external!", __FUNCTION__);
+ ret = -1;
+ }
}
break;
default:
@@ -383,7 +387,7 @@
ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
blank ? "blanking":"unblanking", dpy);
- return 0;
+ return ret;
}
static int hwc_query(struct hwc_composer_device_1* dev,
@@ -447,8 +451,8 @@
}
}
- if (display_commit(ctx, dpy) < 0) {
- ALOGE("%s: display commit fail!", __FUNCTION__);
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
}
@@ -467,49 +471,47 @@
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected) {
+ ctx->dpyAttr[dpy].connected &&
+ !ctx->dpyAttr[dpy].isPause) {
+ uint32_t last = list->numHwLayers - 1;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+ int fd = -1; //FenceFD from the Copybit(valid in async mode)
+ bool copybitDone = false;
+ if(ctx->mCopyBit[dpy])
+ copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
- if(!ctx->dpyAttr[dpy].isPause) {
- uint32_t last = list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- int fd = -1; //FenceFD from the Copybit(valid in async mode)
- bool copybitDone = false;
- if(ctx->mCopyBit[dpy])
- copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+ if(list->numHwLayers > 1)
+ hwc_sync(ctx, list, dpy, fd);
- if(list->numHwLayers > 1)
- hwc_sync(ctx, list, dpy, fd);
+ // Dump the layers for external
+ if(ctx->mHwcDebug[dpy])
+ ctx->mHwcDebug[dpy]->dumpLayers(list);
- // Dump the layers for external
- if(ctx->mHwcDebug[dpy])
- ctx->mHwcDebug[dpy]->dumpLayers(list);
+ if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+ ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+ ret = -1;
+ }
- if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
- ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+ int extOnlyLayerIndex =
+ ctx->listStats[dpy].extOnlyLayerIndex;
+
+ private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+ if(extOnlyLayerIndex!= -1) {
+ hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
+ hnd = (private_handle_t *)extLayer->handle;
+ } else if(copybitDone) {
+ hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+ }
+
+ if(hnd && !isYuvBuffer(hnd)) {
+ if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
+ ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
}
-
- int extOnlyLayerIndex =
- ctx->listStats[dpy].extOnlyLayerIndex;
-
- private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
- if(extOnlyLayerIndex!= -1) {
- hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
- hnd = (private_handle_t *)extLayer->handle;
- } else if(copybitDone) {
- hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
- }
-
- if(hnd && !isYuvBuffer(hnd)) {
- if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
- ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
- ret = -1;
- }
- }
}
- if (display_commit(ctx, dpy) < 0) {
- ALOGE("%s: display commit fail!", __FUNCTION__);
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
}
@@ -566,15 +568,15 @@
}
}
- if (display_commit(ctx, dpy) < 0) {
- ALOGE("%s: display commit fail!", __FUNCTION__);
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
}
closeAcquireFds(list);
- if (list && !ctx->mVirtualonExtActive) {
+ if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
// SF assumes HWC waits for the acquire fence and returns a new fence
// that signals when we're done. Since we don't wait, and also don't
// touch the buffer, we can just handle the acquire fence back to SF
@@ -615,9 +617,7 @@
MDPComp::resetIdleFallBack();
ctx->mVideoTransFlag = false;
//Was locked at the beginning of prepare
- ctx->mSecureLock.unlock();
- ctx->mExtLock.unlock();
- ctx->mBlankLock.unlock();
+ ctx->mDrawLock.unlock();
return ret;
}
@@ -707,6 +707,7 @@
void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ Locker::Autolock _l(ctx->mDrawLock);
android::String8 aBuf("");
dumpsys_log(aBuf, "Qualcomm HWC state:\n");
dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version);
@@ -751,7 +752,7 @@
//Setup HWC methods
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_2;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 068e28a..a395ee0 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -127,6 +127,20 @@
return renderArea;
}
+bool checkNonWormholeRegion(private_handle_t* hnd, hwc_rect_t& rect)
+{
+ unsigned int height = rect.bottom - rect.top;
+ unsigned int width = rect.right - rect.left;
+ copybit_image_t buf;
+ buf.w = ALIGN(hnd->width, 32);
+ buf.h = hnd->height;
+
+ if (buf.h != height || buf.w != width)
+ return false;
+
+ return true;
+}
+
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy) {
@@ -181,6 +195,15 @@
if (layer->planeAlpha != 0xFF)
return true;
}
+ /*
+ * Fallback to GPU in MDP3 when NonWormholeRegion is not of frame buffer
+ * size as artifact is seen in WormholeRegion of previous frame.
+ */
+ hwc_rect_t nonWormHoleRegion;
+ getNonWormholeRegion(list, nonWormHoleRegion);
+ if(!checkNonWormholeRegion(fbHnd, nonWormHoleRegion))
+ return true;
+
}
//Allocate render buffers if they're not allocated
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 7c2e643..fafe03b 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -165,7 +165,10 @@
orient = ovutils::OVERLAY_TRANSFORM_0;
transform = 0;
ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
- static_cast<ovutils::eRotFlags>(rotFlags));
+ static_cast<ovutils::eRotFlags>(rotFlags),
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ret = true;
if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
NULL, mDest) < 0) {
@@ -262,11 +265,16 @@
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+ //XXX: FB layer plane alpha is currently sent as zero from
+ //surfaceflinger
ovutils::PipeArgs pargL(mdpFlagsL,
info,
zOrder,
ovutils::IS_FG_OFF,
- ovutils::ROT_FLAGS_NONE);
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ov.setSource(pargL, destL);
ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
@@ -275,7 +283,10 @@
info,
zOrder,
ovutils::IS_FG_OFF,
- ovutils::ROT_FLAGS_NONE);
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
ov.setSource(pargR, destR);
hwc_rect_t sourceCrop = layer->sourceCrop;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index e97d769..f2217b9 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -55,7 +55,9 @@
void MDPComp::dump(android::String8& buf)
{
- Locker::Autolock _l(mMdpCompLock);
+ if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
+ return;
+
dumpsys_log(buf,"HWC Map for Dpy: %s \n",
(mDpy == 0) ? "\"PRIMARY\"" :
(mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
@@ -440,11 +442,15 @@
hwc_layer_1_t* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if((layer->transform & HWC_TRANSFORM_ROT_90) && !isYuvBuffer(hnd)) {
- ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
- return false;
+ if(layer->transform & HWC_TRANSFORM_ROT_90) {
+ if(!isYuvBuffer(hnd) ) {
+ ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
+ return false;
+ }else if(!canUseRotator(ctx, mDpy)) {
+ ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
+ return false;
+ }
}
-
if(!isValidDimension(ctx,layer)) {
ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
__FUNCTION__);
@@ -558,6 +564,11 @@
return false;
}
+ if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
+ ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
+ return false;
+ }
+
if(isSecuring(ctx, layer)) {
ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
return false;
@@ -569,6 +580,13 @@
return false;
}
+ if(layer->planeAlpha < 0xFF) {
+ ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
+ in video only mode",
+ __FUNCTION__);
+ return false;
+ }
+
return true;
}
@@ -738,92 +756,88 @@
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
const int numLayers = ctx->listStats[mDpy].numAppLayers;
- { //LOCK SCOPE BEGIN
- Locker::Autolock _l(mMdpCompLock);
+ //reset old data
+ mCurrentFrame.reset(numLayers);
- //reset old data
- mCurrentFrame.reset(numLayers);
-
- //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
- //do not cache the information for next draw cycle.
- if(numLayers > MAX_NUM_APP_LAYERS) {
- mCachedFrame.updateCounts(mCurrentFrame);
- ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
- __FUNCTION__);
- return -1;
- }
-
- //Hard conditions, if not met, cannot do MDP comp
- if(!isFrameDoable(ctx)) {
- ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
- __FUNCTION__);
- reset(numLayers, list);
- return -1;
- }
-
- //Check whether layers marked for MDP Composition is actually doable.
- if(isFullFrameDoable(ctx, list)){
- mCurrentFrame.map();
- //Configure framebuffer first if applicable
- if(mCurrentFrame.fbZ >= 0) {
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
- mCurrentFrame.fbZ)) {
- ALOGE("%s configure framebuffer failed", __func__);
- reset(numLayers, list);
- return -1;
- }
- }
- //Acquire and Program MDP pipes
- if(!programMDP(ctx, list)) {
- reset(numLayers, list);
- return -1;
- } else { //Success
- //Any change in composition types needs an FB refresh
- mCurrentFrame.needsRedraw = false;
- if(mCurrentFrame.fbCount &&
- ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
- (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
- (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
- (!mCurrentFrame.mdpCount) ||
- (list->flags & HWC_GEOMETRY_CHANGED) ||
- isSkipPresent(ctx, mDpy) ||
- (mDpy > HWC_DISPLAY_PRIMARY))) {
- mCurrentFrame.needsRedraw = true;
- }
- }
- } else if(isOnlyVideoDoable(ctx, list)) {
- //All layers marked for MDP comp cannot be bypassed.
- //Try to compose atleast YUV layers through MDP comp and let
- //all the RGB layers compose in FB
- //Destination over
- mCurrentFrame.fbZ = -1;
- if(mCurrentFrame.fbCount)
- mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
-
- mCurrentFrame.map();
-
- //Configure framebuffer first if applicable
- if(mCurrentFrame.fbZ >= 0) {
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
- ALOGE("%s configure framebuffer failed", __func__);
- reset(numLayers, list);
- return -1;
- }
- }
- if(!programYUV(ctx, list)) {
- reset(numLayers, list);
- return -1;
- }
- } else {
- reset(numLayers, list);
- return -1;
- }
-
- //UpdateLayerFlags
- setMDPCompLayerFlags(ctx, list);
+ //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+ //do not cache the information for next draw cycle.
+ if(numLayers > MAX_NUM_APP_LAYERS) {
mCachedFrame.updateCounts(mCurrentFrame);
+ ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
+ __FUNCTION__);
+ return -1;
+ }
- } //LOCK SCOPE END. dump also need this lock.
+ //Hard conditions, if not met, cannot do MDP comp
+ if(!isFrameDoable(ctx)) {
+ ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+ __FUNCTION__);
+ reset(numLayers, list);
+ return -1;
+ }
+
+ //Check whether layers marked for MDP Composition is actually doable.
+ if(isFullFrameDoable(ctx, list)) {
+ mCurrentFrame.map();
+ //Configure framebuffer first if applicable
+ if(mCurrentFrame.fbZ >= 0) {
+ if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list,
+ mCurrentFrame.fbZ)) {
+ ALOGE("%s configure framebuffer failed", __func__);
+ reset(numLayers, list);
+ return -1;
+ }
+ }
+ //Acquire and Program MDP pipes
+ if(!programMDP(ctx, list)) {
+ reset(numLayers, list);
+ return -1;
+ } else { //Success
+ //Any change in composition types needs an FB refresh
+ mCurrentFrame.needsRedraw = false;
+ if(mCurrentFrame.fbCount &&
+ ((mCurrentFrame.mdpCount != mCachedFrame.mdpCount) ||
+ (mCurrentFrame.fbCount != mCachedFrame.cacheCount) ||
+ (mCurrentFrame.fbZ != mCachedFrame.fbZ) ||
+ (!mCurrentFrame.mdpCount) ||
+ (list->flags & HWC_GEOMETRY_CHANGED) ||
+ isSkipPresent(ctx, mDpy) ||
+ (mDpy > HWC_DISPLAY_PRIMARY))) {
+ mCurrentFrame.needsRedraw = true;
+ }
+ }
+ } else if(isOnlyVideoDoable(ctx, list)) {
+ //All layers marked for MDP comp cannot be bypassed.
+ //Try to compose atleast YUV layers through MDP comp and let
+ //all the RGB layers compose in FB
+ //Destination over
+ mCurrentFrame.fbZ = -1;
+ if(mCurrentFrame.fbCount)
+ mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
+
+ mCurrentFrame.map();
+
+ //Configure framebuffer first if applicable
+ if(mCurrentFrame.fbZ >= 0) {
+ if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
+ ALOGE("%s configure framebuffer failed", __func__);
+ reset(numLayers, list);
+ return -1;
+ }
+ }
+ if(!programYUV(ctx, list)) {
+ reset(numLayers, list);
+ return -1;
+ }
+ } else {
+ reset(numLayers, list);
+ return -1;
+ }
+
+ //UpdateLayerFlags
+ setMDPCompLayerFlags(ctx, list);
+ mCachedFrame.updateCounts(mCurrentFrame);
+
// unlock it before calling dump function to avoid deadlock
if(isDebug()) {
ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
@@ -925,8 +939,6 @@
return true;
}
- Locker::Autolock _l(mMdpCompLock);
-
/* reset Invalidator */
if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
idleInvalidator->markForSleep();
@@ -1132,8 +1144,6 @@
return true;
}
- Locker::Autolock _l(mMdpCompLock);
-
/* reset Invalidator */
if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
idleInvalidator->markForSleep();
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 1385fbb..2f1670b 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -170,7 +170,6 @@
static IdleInvalidator *idleInvalidator;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
- mutable Locker mMdpCompLock;
};
class MDPCompLowRes : public MDPComp {
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index c20f5c1..45c82fd 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -71,7 +71,7 @@
}
void QClient::securing(uint32_t startEnd) {
- Locker::Autolock _sl(mHwcContext->mSecureLock);
+ Locker::Autolock _sl(mHwcContext->mDrawLock);
//The only way to make this class in this process subscribe to media
//player's death.
IMediaDeathNotifier::getMediaPlayerService();
@@ -85,7 +85,7 @@
}
void QClient::unsecuring(uint32_t startEnd) {
- Locker::Autolock _sl(mHwcContext->mSecureLock);
+ Locker::Autolock _sl(mHwcContext->mDrawLock);
mHwcContext->mSecuring = startEnd;
//We're done unsecuring
if(startEnd == IQService::END)
@@ -95,7 +95,7 @@
}
void QClient::MPDeathNotifier::died() {
- Locker::Autolock _sl(mHwcContext->mSecureLock);
+ Locker::Autolock _sl(mHwcContext->mDrawLock);
ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
mHwcContext->mSecuring = false;
mHwcContext->mSecureMode = false;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 1d127f0..5590798 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -33,7 +33,7 @@
#include "external.h"
#include "virtual.h"
#include "mdp_version.h"
-
+using namespace overlay;
namespace qhwc {
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
@@ -125,7 +125,7 @@
break;
}
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
clear(ctx, dpy);
ctx->dpyAttr[dpy].connected = false;
ctx->dpyAttr[dpy].isActive = false;
@@ -164,7 +164,7 @@
//fail, since Layer Mixer#0 is still connected to WriteBack.
//This block will force composition to close fb2 in above
//example.
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
ctx->dpyAttr[dpy].isConfiguring = true;
ctx->proc->invalidate(ctx->proc);
}
@@ -177,7 +177,7 @@
ALOGD_IF(UEVENT_DEBUG,"Received HDMI connection request"
"when WFD is active");
{
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
clear(ctx, HWC_DISPLAY_VIRTUAL);
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
@@ -193,7 +193,7 @@
ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL,
EXTERNAL_OFFLINE);
{
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
ctx->mVirtualonExtActive = false;
}
}
@@ -205,7 +205,7 @@
ctx->mExtDisplay->configure();
} else {
{
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
/* TRUE only when we are on proprietary WFD session */
ctx->mVirtualonExtActive = true;
char property[PROPERTY_VALUE_MAX];
@@ -220,7 +220,7 @@
ctx->mVirtualDisplay->configure();
}
- Locker::Autolock _l(ctx->mExtLock);
+ Locker::Autolock _l(ctx->mDrawLock);
setup(ctx, dpy);
ctx->dpyAttr[dpy].isPause = false;
ctx->dpyAttr[dpy].connected = true;
@@ -233,7 +233,6 @@
* surface for the same. */
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = true;
}
-
if(dpy == HWC_DISPLAY_EXTERNAL ||
ctx->mVirtualonExtActive) {
ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL_OFFLINE ONLINE"
@@ -243,33 +242,51 @@
}
break;
}
- case EXTERNAL_PAUSE:
- {
- ctx->dpyAttr[dpy].isActive = true;
- ctx->dpyAttr[dpy].isPause = true;
- break;
- }
- case EXTERNAL_RESUME:
- {
- //Treat Resume as Online event
- //Since external didnt have any pipes, force primary to give up
- //its pipes; we don't allow inter-mixer pipe transfers.
- {
- Locker::Autolock _l(ctx->mExtLock);
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->dpyAttr[dpy].isActive = true;
- ctx->proc->invalidate(ctx->proc);
+ case EXTERNAL_PAUSE:
+ { // pause case
+ ALOGD("%s Received Pause event",__FUNCTION__);
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->dpyAttr[dpy].isPause = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ // At this point all the pipes used by External have been
+ // marked as UNSET.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ // Perform commit to unstage the pipes.
+ if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail! for %d dpy",
+ __FUNCTION__, dpy);
+ }
+ }
+ break;
}
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
- {
- //At this point external has all the pipes it would need.
- Locker::Autolock _l(ctx->mExtLock);
- ctx->dpyAttr[dpy].isPause = false;
- ctx->proc->invalidate(ctx->proc);
+ case EXTERNAL_RESUME:
+ { // resume case
+ ALOGD("%s Received resume event",__FUNCTION__);
+ //Treat Resume as Online event
+ //Since external didnt have any pipes, force primary to give up
+ //its pipes; we don't allow inter-mixer pipe transfers.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isConfiguring = true;
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ //At this point external has all the pipes it would need.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isPause = false;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ break;
}
- break;
- }
default:
{
ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e013876..ea123d0 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -623,8 +623,9 @@
yuvCount++;
if((layer->transform & HWC_TRANSFORM_ROT_90) &&
- canUseRotator(ctx)) {
- if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
+ canUseRotator(ctx, dpy)) {
+ if( (dpy == HWC_DISPLAY_PRIMARY) &&
+ ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
ctx->isPaddingRound = true;
}
Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
@@ -734,6 +735,18 @@
return false;
}
+int getBlending(int blending) {
+ switch(blending) {
+ case HWC_BLENDING_NONE:
+ return overlay::utils::OVERLAY_BLENDING_OPAQUE;
+ case HWC_BLENDING_PREMULT:
+ return overlay::utils::OVERLAY_BLENDING_PREMULT;
+ case HWC_BLENDING_COVERAGE :
+ default:
+ return overlay::utils::OVERLAY_BLENDING_COVERAGE;
+ }
+}
+
//Crops source buffer against destination and FB boundaries
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
const hwc_rect_t& scissor, int orient) {
@@ -1041,10 +1054,16 @@
}
}
-int configRotator(Rotator *rot, const Whf& whf,
+int configRotator(Rotator *rot, Whf& whf,
hwc_rect_t& crop, const eMdpFlags& mdpFlags,
const eTransform& orient, const int& downscale) {
+ // Fix alignments for TILED format
+ if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+ whf.format == MDP_Y_CBCR_H2V2_TILE) {
+ whf.w = utils::alignup(whf.w, 64);
+ whf.h = utils::alignup(whf.h, 32);
+ }
rot->setSource(whf);
if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
@@ -1220,7 +1239,10 @@
//For the mdp, since either we are pre-rotating or MDP does flips
orient = OVERLAY_TRANSFORM_0;
transform = 0;
- PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags));
+ PipeArgs parg(mdpFlags, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
ALOGE("%s: commit failed for low res panel", __FUNCTION__);
return -1;
@@ -1349,7 +1371,9 @@
//configure left mixer
if(lDest != OV_INVALID) {
PipeArgs pargL(mdpFlagsL, whf, z, isFg,
- static_cast<eRotFlags>(rotFlags));
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
if(configMdp(ctx->mOverlay, pargL, orient,
tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
@@ -1360,7 +1384,9 @@
//configure right mixer
if(rDest != OV_INVALID) {
PipeArgs pargR(mdpFlagsR, whf, z, isFg,
- static_cast<eRotFlags>(rotFlags));
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
tmp_dstR.right = tmp_dstR.right - lSplit;
tmp_dstR.left = tmp_dstR.left - lSplit;
if(configMdp(ctx->mOverlay, pargR, orient,
@@ -1373,10 +1399,15 @@
return 0;
}
-bool canUseRotator(hwc_context_t *ctx) {
+bool canUseRotator(hwc_context_t *ctx, int dpy) {
if(qdutils::MDPVersion::getInstance().is8x26() &&
- ctx->mVirtualDisplay->isConnected()) {
- return false;
+ ctx->mVirtualDisplay->isConnected() &&
+ !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
+ // Allow if YUV needs rotation and DMA is configured to BLOCK mode for
+ // primary. For portrait videos usecase on WFD, Driver supports
+ // multiplexing of DMA pipe in LINE and BLOCK mode.
+ if(dpy == HWC_DISPLAY_PRIMARY)
+ return false;
}
if(ctx->mMDP.version == qdutils::MDP_V3_0_4)
return false;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 8809493..98749c1 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -172,6 +172,7 @@
bool needsScaling(hwc_context_t* ctx, hwc_layer_1_t const* layer, const int& dpy);
bool isAlphaPresent(hwc_layer_1_t const* layer);
int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
+int getBlending(int blending);
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -210,7 +211,7 @@
ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform);
-int configRotator(overlay::Rotator *rot, const ovutils::Whf& whf,
+int configRotator(overlay::Rotator *rot, ovutils::Whf& whf,
hwc_rect_t& crop, const ovutils::eMdpFlags& mdpFlags,
const ovutils::eTransform& orient, const int& downscale);
@@ -240,7 +241,7 @@
//extreme unavailability of pipes. This can also be done via hybrid calculations
//also involving many more variables like number of write-back interfaces etc,
//but the variety of scenarios is too high to warrant that.
-bool canUseRotator(hwc_context_t *ctx);
+bool canUseRotator(hwc_context_t *ctx, int dpy);
int getLeftSplit(hwc_context_t *ctx, const int& dpy);
@@ -287,8 +288,7 @@
void init_vsync_thread(hwc_context_t* ctx);
inline void getLayerResolution(const hwc_layer_1_t* layer,
- int& width, int& height)
-{
+ int& width, int& height) {
hwc_rect_t displayFrame = layer->displayFrame;
width = displayFrame.right - displayFrame.left;
height = displayFrame.bottom - displayFrame.top;
@@ -354,17 +354,8 @@
bool mVirtualonExtActive;
//Display in secure mode indicator
bool mSecureMode;
- //Lock to prevent set from being called while blanking
- mutable Locker mBlankLock;
- //Lock to protect prepare & set when detaching external disp
- mutable Locker mExtLock;
- /*Lock to set both mSecureMode and mSecuring as part
- of binder thread without context switch to composition
- thread. This lock is needed only for A-family targets
- since the state of mSecureMode and mSecuring variables
- are not checked in B-family targets.
- */
- mutable Locker mSecureLock;
+ //Lock to protect drawing data structures
+ mutable Locker mDrawLock;
//Drawing round when we use GPU
bool isPaddingRound;
// External Orientation
diff --git a/liblight/lights.c b/liblight/lights.c
index eb71b74..ccfbe10 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -51,6 +51,9 @@
char const*const LCD_FILE
= "/sys/class/leds/lcd-backlight/brightness";
+char const*const BUTTON_FILE
+ = "/sys/class/leds/button-backlight/brightness";
+
char const*const RED_BLINK_FILE
= "/sys/class/leds/red/blink";
@@ -209,6 +212,16 @@
return 0;
}
+static int
+set_light_buttons(struct light_device_t* dev,
+ struct light_state_t const* state)
+{
+ int err = 0;
+ pthread_mutex_lock(&g_lock);
+ err = write_int(BUTTON_FILE, state->color & 0xFF);
+ pthread_mutex_unlock(&g_lock);
+ return err;
+}
/** Close the lights device */
static int
@@ -238,6 +251,8 @@
set_light = set_light_backlight;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
+ else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
+ set_light = set_light_buttons;
else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
set_light = set_light_attention;
else
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index ecd66a6..afe62e2 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -58,12 +58,11 @@
PipeBook::resetUse(i);
PipeBook::resetAllocation(i);
}
+ sForceSetBitmap = 0;
mDumpStr[0] = '\0';
}
void Overlay::configDone() {
- if(PipeBook::pipeUsageUnchanged()) return;
-
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if(PipeBook::isNotUsed(i)) {
//Forces UNSET on pipes, flushes rotator memory and session, closes
@@ -142,6 +141,9 @@
if(mPipeBook[index].mPipe->commit()) {
ret = true;
PipeBook::setUse((int)dest);
+ if(sForceSetBitmap & (1 << mPipeBook[index].mDisplay)) {
+ mPipeBook[index].mPipe->forceSet();
+ }
} else {
int dpy = mPipeBook[index].mDisplay;
for(int i = 0; i < PipeBook::NUM_PIPES; i++)
@@ -387,6 +389,7 @@
Overlay* Overlay::sInstance = 0;
int Overlay::sDpyFbMap[DPY_MAX] = {0, -1, -1};
int Overlay::sDMAMode = DMA_LINE_MODE;
+int Overlay::sForceSetBitmap = 0;
int Overlay::PipeBook::NUM_PIPES = 0;
int Overlay::PipeBook::sPipeUsageBitmap = 0;
int Overlay::PipeBook::sLastUsageBitmap = 0;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index fea50b3..280223c 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -82,10 +82,6 @@
bool commit(utils::eDest dest);
bool queueBuffer(int fd, uint32_t offset, utils::eDest dest);
- /* Closes open pipes, called during startup */
- static int initOverlay();
- /* Returns the singleton instance of overlay */
- static Overlay* getInstance();
/* Returns available ("unallocated") pipes for a display's mixer */
int availablePipes(int dpy, int mixer);
/* Returns if any of the requested pipe type is attached to any of the
@@ -98,6 +94,13 @@
void getDump(char *buf, size_t len);
/* Reset usage and allocation bits on all pipes for given display */
void clear(int dpy);
+ /* Marks the display, whose pipes need to be forcibaly configured */
+ void forceSet(const int& dpy);
+
+ /* Closes open pipes, called during startup */
+ static int initOverlay();
+ /* Returns the singleton instance of overlay */
+ static Overlay* getInstance();
static void setDMAMode(const int& mode);
static int getDMAMode();
/* Returns the framebuffer node backing up the display */
@@ -168,6 +171,7 @@
static Overlay *sInstance;
static int sDpyFbMap[DPY_MAX];
static int sDMAMode;
+ static int sForceSetBitmap;
};
inline void Overlay::validate(int index) {
@@ -208,6 +212,10 @@
return sDpyFbMap[dpy];
}
+inline void Overlay::forceSet(const int& dpy) {
+ sForceSetBitmap |= (1 << dpy);
+}
+
inline bool Overlay::PipeBook::valid() {
return (mPipe != NULL);
}
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 2d88376..674e62d 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -94,13 +94,14 @@
setSrcWhf(args.whf);
//TODO These are hardcoded. Can be moved out of setSource.
- mOVInfo.alpha = 0xff;
mOVInfo.transp_mask = 0xffffffff;
//TODO These calls should ideally be a part of setPipeParams API
setFlags(args.mdpFlags);
setZ(args.zorder);
setIsFg(args.isFg);
+ setPlaneAlpha(args.planeAlpha);
+ setBlending(args.blending);
}
void MdpCtrl::setCrop(const utils::Dim& d) {
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 056d982..5bfec6b 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -99,8 +99,13 @@
void setZ(utils::eZorder z);
/* set isFg flag */
void setIsFg(utils::eIsFg isFg);
- /* return a copy of src whf*/
+ /* return a copy of src whf*/
utils::Whf getSrcWhf() const;
+ /* set plane alpha */
+ void setPlaneAlpha(int planeAlpha);
+ /* set blending method */
+ void setBlending(overlay::utils::eBlending blending);
+
/* set src whf */
void setSrcWhf(const utils::Whf& whf);
/* set src/dst rect dim */
@@ -241,6 +246,24 @@
mDownscale = dscale;
}
+inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
+ mOVInfo.alpha = planeAlpha;
+}
+
+inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
+ switch((int) blending) {
+ case utils::OVERLAY_BLENDING_OPAQUE:
+ mOVInfo.blend_op = BLEND_OP_OPAQUE;
+ break;
+ case utils::OVERLAY_BLENDING_PREMULT:
+ mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
+ break;
+ case utils::OVERLAY_BLENDING_COVERAGE:
+ default:
+ mOVInfo.blend_op = BLEND_OP_COVERAGE;
+ }
+}
+
inline bool MdpCtrl::ovChanged() const {
#ifdef USES_POST_PROCESSING
// Some pp params are stored as pointer address,
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index c3d00f1..927e7e9 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -119,6 +119,9 @@
case HAL_PIXEL_FORMAT_YCrCb_444_SP:
return MDP_Y_CRCB_H1V1;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+ //NV12 encodeable format maps to the venus format on
+ //B-Family targets
return MDP_Y_CBCR_H2V2_VENUS;
default:
//Unsupported by MDP
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index b543018..e49a50c 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -212,6 +212,8 @@
enum { MAX_PATH_LEN = 256 };
+enum { DEFAULT_PLANE_ALPHA = 0xFF };
+
/**
* Rotator flags: not to be confused with orientation flags.
* Usually, you want to open the rotator to make sure it is
@@ -329,21 +331,36 @@
OVERLAY_TRANSFORM_INV = 0x80
};
+enum eBlending {
+ OVERLAY_BLENDING_UNDEFINED = 0x0,
+ /* No blending */
+ OVERLAY_BLENDING_OPAQUE,
+ /* src.rgb + dst.rgb*(1-src_alpha) */
+ OVERLAY_BLENDING_PREMULT,
+ /* src.rgb * src_alpha + dst.rgb (1 - src_alpha) */
+ OVERLAY_BLENDING_COVERAGE,
+};
+
// Used to consolidate pipe params
struct PipeArgs {
PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
zorder(Z_SYSTEM_ALLOC),
isFg(IS_FG_OFF),
- rotFlags(ROT_FLAGS_NONE){
+ rotFlags(ROT_FLAGS_NONE),
+ planeAlpha(DEFAULT_PLANE_ALPHA),
+ blending(OVERLAY_BLENDING_COVERAGE){
}
PipeArgs(eMdpFlags f, Whf _whf,
- eZorder z, eIsFg fg, eRotFlags r) :
+ eZorder z, eIsFg fg, eRotFlags r,
+ int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
mdpFlags(f),
whf(_whf),
zorder(z),
isFg(fg),
- rotFlags(r) {
+ rotFlags(r),
+ planeAlpha(pA),
+ blending(b){
}
eMdpFlags mdpFlags; // for mdp_overlay flags
@@ -351,6 +368,8 @@
eZorder zorder; // stage number
eIsFg isFg; // control alpha & transp
eRotFlags rotFlags;
+ int planeAlpha;
+ eBlending blending;
};
// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time