Merge "hwc: Clean up scattered definitions of commonly used constants/values"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 7255391..0e80843 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -592,7 +592,7 @@
//Planar
case HAL_PIXEL_FORMAT_YV12:
ystride = hnd->width;
- cstride = hnd->width/2;
+ cstride = ALIGN(hnd->width/2, 16);
ycbcr->y = (void*)hnd->base;
ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
diff --git a/libgralloc/fb_priv.h b/libgralloc/fb_priv.h
index 191aa2a..e2eba6a 100644
--- a/libgralloc/fb_priv.h
+++ b/libgralloc/fb_priv.h
@@ -43,9 +43,7 @@
uint32_t numBuffers;
uint32_t bufferMask;
pthread_mutex_t lock;
- private_handle_t *currentBuffer;
struct fb_var_screeninfo info;
- struct mdp_display_commit commit;
struct fb_fix_screeninfo finfo;
float xdpi;
float ydpi;
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index ca11bea..0ebc3db 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -58,9 +58,10 @@
struct fb_context_t {
framebuffer_device_t device;
+ //fd - which is returned on open
+ int fbFd;
};
-
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
int interval)
{
@@ -87,11 +88,12 @@
reinterpret_cast<private_module_t*>(dev->common.module);
private_handle_t *hnd = static_cast<private_handle_t*>
(const_cast<native_handle_t*>(buffer));
+ fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
const unsigned int offset = (unsigned int) (hnd->base -
m->framebuffer->base);
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = (int)(offset / m->finfo.line_length);
- if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+ if (ioctl(ctx->fbFd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
__FUNCTION__, strerror(errno));
return -errno;
@@ -110,8 +112,11 @@
return 0;
}
-int mapFrameBufferLocked(struct private_module_t* module)
+int mapFrameBufferLocked(framebuffer_device_t *dev)
{
+ private_module_t* module =
+ reinterpret_cast<private_module_t*>(dev->common.module);
+ fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
// already initialized...
if (module->framebuffer) {
return 0;
@@ -134,8 +139,6 @@
if (fd < 0)
return -errno;
- memset(&module->commit, 0, sizeof(struct mdp_display_commit));
-
struct fb_fix_screeninfo finfo;
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
close(fd);
@@ -329,34 +332,55 @@
//adreno needs page aligned offsets. Align the fbsize to pagesize.
unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
module->numBuffers;
- module->framebuffer = new private_handle_t(fd, fbSize,
- private_handle_t::PRIV_FLAGS_USES_ION,
- BUFFER_TYPE_UI,
- module->fbFormat, info.xres, info.yres);
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (vaddr == MAP_FAILED) {
ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
close(fd);
return -errno;
}
+ //store the framebuffer fd in the ctx
+ ctx->fbFd = fd;
+#ifdef MSMFB_METADATA_GET
+ memset(&metadata, 0 , sizeof(metadata));
+ metadata.op = metadata_op_get_ion_fd;
+ // get the ION fd for the framebuffer, as GPU needs ION fd
+ if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+ ALOGE("Error getting ION fd (%s)", strerror(errno));
+ close(fd);
+ return -errno;
+ }
+ if(metadata.data.fbmem_ionfd < 0) {
+ ALOGE("Error: Ioctl returned invalid ION fd = %d",
+ metadata.data.fbmem_ionfd);
+ close(fd);
+ return -errno;
+ }
+ fd = metadata.data.fbmem_ionfd;
+#endif
+ // Create framebuffer handle using the ION fd
+ module->framebuffer = new private_handle_t(fd, fbSize,
+ private_handle_t::PRIV_FLAGS_USES_ION,
+ BUFFER_TYPE_UI,
+ module->fbFormat, info.xres, info.yres);
module->framebuffer->base = uint64_t(vaddr);
memset(vaddr, 0, fbSize);
//Enable vsync
int enable = 1;
- ioctl(module->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL,
- &enable);
+ ioctl(ctx->fbFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
return 0;
}
-static int mapFrameBuffer(struct private_module_t* module)
+static int mapFrameBuffer(framebuffer_device_t *dev)
{
int err = -1;
char property[PROPERTY_VALUE_MAX];
if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
(!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
(!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ private_module_t* module =
+ reinterpret_cast<private_module_t*>(dev->common.module);
pthread_mutex_lock(&module->lock);
- err = mapFrameBufferLocked(module);
+ err = mapFrameBufferLocked(dev);
pthread_mutex_unlock(&module->lock);
}
return err;
@@ -368,6 +392,11 @@
{
fb_context_t* ctx = (fb_context_t*)dev;
if (ctx) {
+#ifdef MSMFB_METADATA_GET
+ if(ctx->fbFd >=0) {
+ close(ctx->fbFd);
+ }
+#endif
//Hack until fbdev is removed. Framework could close this causing hwc a
//pain.
//free(ctx);
@@ -403,8 +432,8 @@
dev->device.setUpdateRect = 0;
dev->device.compositionComplete = fb_compositionComplete;
- private_module_t* m = (private_module_t*)module;
- status = mapFrameBuffer(m);
+ status = mapFrameBuffer((framebuffer_device_t*)dev);
+ private_module_t* m = (private_module_t*)dev->device.common.module;
if (status >= 0) {
int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
const_cast<uint32_t&>(dev->device.flags) = 0;
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 4067050..9b98f1b 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -224,9 +224,11 @@
// create a "fake" handle for it
uint64_t vaddr = uint64_t(m->framebuffer->base);
+ // As GPU needs ION FD, the private handle is created
+ // using ION fd and ION flags are set
private_handle_t* hnd = new private_handle_t(
dup(m->framebuffer->fd), bufferSize,
- private_handle_t::PRIV_FLAGS_USES_PMEM |
+ private_handle_t::PRIV_FLAGS_USES_ION |
private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
BUFFER_TYPE_UI, m->fbFormat, m->info.xres,
m->info.yres);
diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp
index c1c61aa..c0aa8cb 100644
--- a/libgralloc/gralloc.cpp
+++ b/libgralloc/gralloc.cpp
@@ -91,7 +91,6 @@
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
- currentBuffer: 0,
};
// Open Gralloc device
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 267815f..3d3d138 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -147,7 +147,8 @@
* to BLOCK_MODE */
if (canUseRotator(ctx, dpy) &&
- has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ (has90Transform(layer) || getRotDownscale(ctx, layer))
+ && isRotationDoable(ctx, hnd)) {
if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
if(ctx->mOverlay->isPipeTypeAttached(
overlay::utils::OV_MDP_PIPE_DMA))
@@ -673,18 +674,12 @@
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) {
+ if(copybitDone) {
hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
}
- if(hnd && !isYuvBuffer(hnd)) {
+ if(hnd) {
if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index a26f659..f849450 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -76,11 +76,15 @@
"/sys/class/graphics/fb%d/ad", wbFbNum);
int adFd = open(wbFbPath, O_RDONLY);
if(adFd >= 0) {
- char opStr[4] = {'\0'};
- if(read(adFd, opStr, strlen(opStr)) >= 0) {
+ char opStr[4];
+ ssize_t bytesRead = read(adFd, opStr, sizeof(opStr) - 1);
+ if(bytesRead > 0) {
+ opStr[bytesRead] = '\0';
//Should return -1, 0 or 1
ret = atoi(opStr);
ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
+ } else if(bytesRead == 0) {
+ ALOGE("%s: ad node empty", __func__);
} else {
ALOGE("%s: Read from ad node failed with error %s", __func__,
strerror(errno));
@@ -210,7 +214,7 @@
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
- PipeArgs parg(mdpFlags, whf, ZORDER_0, IS_FG_OFF,
+ PipeArgs parg(mdpFlags, whf, ZORDER_0,
ROT_FLAGS_NONE);
hwc_rect_t dst = crop; //input same as output
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 5014af9..7a2ff09 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -132,12 +132,6 @@
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
- int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
- // ext only layer present..
- if(extOnlyLayerIndex != -1) {
- layer = &list->hwLayers[extOnlyLayerIndex];
- layer->compositionType = HWC_OVERLAY;
- }
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
@@ -165,7 +159,6 @@
}
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
- ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
@@ -193,10 +186,8 @@
// Dont do wormhole calculation when extDownscale is enabled on External
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
sourceCrop = layer->displayFrame;
- } else if((!mDpy ||
- (mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mDownScaleMode))
- && (extOnlyLayerIndex == -1)) {
+ } else if((mDpy && !extOrient
+ && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
!ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
@@ -218,7 +209,7 @@
//For the mdp, since either we are pre-rotating or MDP does flips
orient = ovutils::OVERLAY_TRANSFORM_0;
transform = 0;
- ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
+ ovutils::PipeArgs parg(mdpFlags, info, zOrder,
static_cast<ovutils::eRotFlags>(rotFlags),
ovutils::DEFAULT_PLANE_ALPHA,
(ovutils::eBlending)
@@ -285,12 +276,6 @@
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
- /* External only layer present */
- int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
- if(extOnlyLayerIndex != -1) {
- layer = &list->hwLayers[extOnlyLayerIndex];
- layer->compositionType = HWC_OVERLAY;
- }
ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
mTileEnabled));
@@ -333,7 +318,6 @@
ovutils::PipeArgs pargL(mdpFlags,
info,
zOrder,
- ovutils::IS_FG_OFF,
ovutils::ROT_FLAGS_NONE,
ovutils::DEFAULT_PLANE_ALPHA,
(ovutils::eBlending)
@@ -369,7 +353,6 @@
ovutils::PipeArgs pargR(mdpFlagsR,
info,
zOrder,
- ovutils::IS_FG_OFF,
ovutils::ROT_FLAGS_NONE,
ovutils::DEFAULT_PLANE_ALPHA,
(ovutils::eBlending)
@@ -424,13 +407,6 @@
bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
hwc_rect_t fbUpdatingRect, int fbZorder) {
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
- // ext only layer present..
- if(extOnlyLayerIndex != -1) {
- layer = &list->hwLayers[extOnlyLayerIndex];
- layer->compositionType = HWC_OVERLAY;
- }
-
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::Whf info(mAlignedFBWidth,
@@ -444,7 +420,6 @@
ovutils::PipeArgs parg(mdpFlags,
info,
zOrder,
- ovutils::IS_FG_OFF,
ovutils::ROT_FLAGS_NONE,
ovutils::DEFAULT_PLANE_ALPHA,
(ovutils::eBlending)
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 863c69e..0d968c8 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -45,7 +45,7 @@
bool MDPComp::sEnableMixedMode = true;
int MDPComp::sSimulationFlags = 0;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-bool MDPComp::sEnable4k2kYUVSplit = false;
+bool MDPComp::sEnableYUVsplit = false;
bool MDPComp::sSrcSplitEnabled = false;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
@@ -156,10 +156,11 @@
}
if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+ !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
(!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
!strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
- sEnable4k2kYUVSplit = true;
+ sEnableYUVsplit = true;
}
if ((property_get("persist.hwc.ptor.enable", property, NULL) > 0) &&
@@ -237,11 +238,12 @@
}
MDPComp::FrameInfo::FrameInfo() {
+ memset(&mdpToLayer, 0, sizeof(mdpToLayer));
reset(0);
}
void MDPComp::FrameInfo::reset(const int& numLayers) {
- for(int i = 0 ; i < MAX_PIPES_PER_MIXER && numLayers; i++ ) {
+ for(int i = 0; i < MAX_PIPES_PER_MIXER; i++) {
if(mdpToLayer[i].pipeInfo) {
delete mdpToLayer[i].pipeInfo;
mdpToLayer[i].pipeInfo = NULL;
@@ -676,7 +678,9 @@
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- if(sIdleFallBack && !ctx->listStats[mDpy].secureUI) {
+ // No Idle fall back, if secure display or secure RGB layers are present
+ if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
+ !ctx->listStats[mDpy].secureRGBCount)) {
ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
return false;
}
@@ -773,7 +777,7 @@
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
mCurrentFrame.dropCount;
- if(sEnable4k2kYUVSplit){
+ if(sEnableYUVsplit){
adjustForSourceSplit(ctx, list);
}
@@ -907,6 +911,11 @@
private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
+ // Store the blending mode, planeAlpha, and transform of PTOR layers
+ int32_t blending[numPTORLayersFound];
+ uint8_t planeAlpha[numPTORLayersFound];
+ uint32_t transform[numPTORLayersFound];
+
for(int j = 0; j < numPTORLayersFound; j++) {
int index = ctx->mPtorInfo.layerIndex[j];
@@ -925,6 +934,14 @@
hnd->height = renderBuf->height;
hnd->format = renderBuf->format;
+ // Store & update blending mode, planeAlpha and transform of PTOR layer
+ blending[j] = layer->blending;
+ planeAlpha[j] = layer->planeAlpha;
+ transform[j] = layer->transform;
+ layer->blending = HWC_BLENDING_NONE;
+ layer->planeAlpha = 0xFF;
+ layer->transform = 0;
+
// Remove overlap from crop & displayFrame of below layers
for (int i = 0; i < index && index !=-1; i++) {
layer = &list->hwLayers[i];
@@ -964,13 +981,17 @@
layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
}
- // Restore w,h,f of PTOR layers
+ // Restore w,h,f, blending attributes, and transform of PTOR layers
for (int i = 0; i < numPTORLayersFound; i++) {
int idx = ctx->mPtorInfo.layerIndex[i];
+ hwc_layer_1_t* layer = &list->hwLayers[idx];
private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
hnd->width = layerWhf[i].w;
hnd->height = layerWhf[i].h;
hnd->format = layerWhf[i].format;
+ layer->blending = blending[i];
+ layer->planeAlpha = planeAlpha[i];
+ layer->transform = transform[i];
}
if (!result) {
@@ -1029,6 +1050,8 @@
}
updateYUV(ctx, list, false /*secure only*/);
+ /* mark secure RGB layers for MDP comp */
+ updateSecureRGB(ctx, list);
bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
if(!ret) {
ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
@@ -1038,7 +1061,7 @@
int mdpCount = mCurrentFrame.mdpCount;
- if(sEnable4k2kYUVSplit){
+ if(sEnableYUVsplit){
adjustForSourceSplit(ctx, list);
}
@@ -1204,7 +1227,7 @@
if(mCurrentFrame.fbCount)
mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
- if(sEnable4k2kYUVSplit){
+ if(sEnableYUVsplit){
adjustForSourceSplit(ctx, list);
}
@@ -1219,6 +1242,64 @@
return true;
}
+/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
+bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ const bool secureOnly = true;
+ return mdpOnlyLayersComp(ctx, list, not secureOnly) or
+ mdpOnlyLayersComp(ctx, list, secureOnly);
+
+}
+
+bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list, bool secureOnly) {
+
+ if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
+ return false;
+
+ /* Bail out if we are processing only secured video layers
+ * and we dont have any */
+ if(!isSecurePresent(ctx, mDpy) && secureOnly){
+ reset(ctx);
+ return false;
+ }
+
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ mCurrentFrame.reset(numAppLayers);
+ mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
+
+ updateYUV(ctx, list, secureOnly);
+ /* mark secure RGB layers for MDP comp */
+ updateSecureRGB(ctx, list);
+
+ if(mCurrentFrame.mdpCount == 0) {
+ reset(ctx);
+ return false;
+ }
+
+ /* find the maximum batch of layers to be marked for framebuffer */
+ bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
+ if(!ret) {
+ ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+ reset(ctx);
+ return false;
+ }
+
+ if(sEnableYUVsplit){
+ adjustForSourceSplit(ctx, list);
+ }
+
+ if(!postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "post heuristic handling failed");
+ reset(ctx);
+ return false;
+ }
+
+ ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
+ __FUNCTION__);
+ return true;
+}
+
/* Checks for conditions where YUV layers cannot be bypassed */
bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
if(isSkipLayer(layer)) {
@@ -1252,6 +1333,27 @@
return true;
}
+/* Checks for conditions where Secure RGB layers cannot be bypassed */
+bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
+ if(isSkipLayer(layer)) {
+ ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
+
+ if(isSecuring(ctx, layer)) {
+ ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
+ return false;
+ }
+
+ if(not isSupportedForMDPComp(ctx, layer)) {
+ ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
+ __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+
/* starts at fromIndex and check for each layer to find
* if it it has overlapping with any Updating layer above it in zorder
* till the end of the batch. returns true if it finds any intersection */
@@ -1469,6 +1571,32 @@
mCurrentFrame.fbCount);
}
+void MDPComp::updateSecureRGB(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list) {
+ int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
+ for(int index = 0;index < nSecureRGBCount; index++){
+ int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
+ hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
+
+ if(!isSecureRGBDoable(ctx, layer)) {
+ if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
+ mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
+ mCurrentFrame.fbCount++;
+ }
+ } else {
+ if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
+ mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
+ mCurrentFrame.fbCount--;
+ }
+ }
+ }
+
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+ mCurrentFrame.fbCount - mCurrentFrame.dropCount;
+ ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
+ mCurrentFrame.fbCount);
+}
+
hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
@@ -1532,7 +1660,7 @@
cur_pipe->zOrder = mdpNextZOrder++;
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
if(configure4k2kYuv(ctx, layer,
mCurrentFrame.mdpToLayer[mdpIndex])
!= 0 ){
@@ -1690,7 +1818,10 @@
if(isFrameDoable(ctx)) {
generateROI(ctx, list);
- mModeOn = tryFullFrame(ctx, list) || tryVideoOnly(ctx, list);
+ // if tryFullFrame fails, try to push all video and secure RGB layers
+ // to MDP for composition.
+ mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
+ tryVideoOnly(ctx, list);
if(mModeOn) {
setMDPCompLayerFlags(ctx, list);
} else {
@@ -1782,7 +1913,7 @@
mdpNextZOrder++;
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd)) {
+ if(isYUVSplitNeeded(hnd)) {
if(mdpNextZOrder <= mCurrentFrame.fbZ)
mCurrentFrame.fbZ += 1;
mdpNextZOrder++;
@@ -1804,13 +1935,12 @@
*(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eIsFg isFg = IS_FG_OFF;
eDest dest = mdp_info.index;
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
__FUNCTION__, layer, zOrder, dest);
- return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest,
+ return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
&PipeLayerPair.rot);
}
@@ -1822,7 +1952,7 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
if(allocSplitVGPipesfor4k2k(ctx, index)){
continue;
}
@@ -1859,12 +1989,11 @@
MdpYUVPipeInfo& mdp_info =
*(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eIsFg isFg = IS_FG_OFF;
eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
eDest lDest = mdp_info.lIndex;
eDest rDest = mdp_info.rIndex;
- return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg,
+ return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
lDest, rDest, &PipeLayerPair.rot);
}
@@ -1902,7 +2031,7 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit)
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
{
MdpYUVPipeInfo& pipe_info =
*(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
@@ -2001,7 +2130,7 @@
mdpNextZOrder++;
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd)) {
+ if(isYUVSplitNeeded(hnd)) {
hwc_rect_t dst = layer->displayFrame;
if((dst.left > lSplit) || (dst.right < lSplit)) {
mCurrentFrame.mdpCount += 1;
@@ -2062,7 +2191,7 @@
private_handle_t *hnd = (private_handle_t *)layer->handle;
hwc_rect_t dst = layer->displayFrame;
const int lSplit = getLeftSplit(ctx, mDpy);
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
if((dst.left > lSplit)||(dst.right < lSplit)){
if(allocSplitVGPipesfor4k2k(ctx, index)){
continue;
@@ -2092,12 +2221,11 @@
MdpYUVPipeInfo& mdp_info =
*(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eIsFg isFg = IS_FG_OFF;
eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
eDest lDest = mdp_info.lIndex;
eDest rDest = mdp_info.rIndex;
- return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg,
+ return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
lDest, rDest, &PipeLayerPair.rot);
}
else{
@@ -2113,7 +2241,6 @@
MdpPipeInfoSplit& mdp_info =
*(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
- eIsFg isFg = IS_FG_OFF;
eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
eDest lDest = mdp_info.lIndex;
eDest rDest = mdp_info.rIndex;
@@ -2121,7 +2248,7 @@
ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
"dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
- return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, isFg, lDest,
+ return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
rDest, &PipeLayerPair.rot);
}
@@ -2158,7 +2285,7 @@
int mdpIndex = mCurrentFrame.layerToMDP[i];
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit)
+ if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
{
MdpYUVPipeInfo& pipe_info =
*(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
@@ -2294,6 +2421,10 @@
int dstWidth = dst.right - dst.left;
int cropWidth = crop.right - crop.left;
+ //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
+ //pipe line length, we are still using 2 pipes. This is fine just because
+ //this is source split where destination doesn't matter. Evaluate later to
+ //see if going through all the calcs to save a pipe is worth it
if(dstWidth > mdpHw.getMaxMixerWidth() or
cropWidth > mdpHw.getMaxMixerWidth() or
(primarySplitAlways and (cropWidth > lSplit))) {
@@ -2327,14 +2458,12 @@
*(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
Rotator **rot = &PipeLayerPair.rot;
eZorder z = static_cast<eZorder>(mdp_info.zOrder);
- eIsFg isFg = IS_FG_OFF;
eDest lDest = mdp_info.lIndex;
eDest rDest = mdp_info.rIndex;
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform);
- const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
@@ -2350,21 +2479,22 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
+ int downscale = getRotDownscale(ctx, layer);
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
- setMdpFlags(ctx, layer, mdpFlags, 0, transform);
+ setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
}
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[mDpy]->add(layer, *rot);
//If the video is using a single pipe, enable BWC
if(rDest == OV_INVALID) {
- BwcPM::setBwc(crop, dst, transform, mdpFlags);
+ BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
}
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
@@ -2372,7 +2502,7 @@
return -1;
}
updateSource(orient, whf, crop, *rot);
- rotFlags |= ROT_PREROTATED;
+ rotFlags |= ovutils::ROT_PREROTATED;
}
//If 2 pipes being used, divide layer into half, crop and dst
@@ -2385,14 +2515,24 @@
cropR.left = cropL.right;
sanitizeSourceCrop(cropL, cropR, hnd);
+ bool cropSwap = false;
//Swap crops on H flip since 2 pipes are being used
if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
hwc_rect_t tmp = cropL;
cropL = cropR;
cropR = tmp;
+ cropSwap = true;
}
- dstL.right = (dst.right + dst.left) / 2;
+ //cropSwap trick: If the src and dst widths are both odd, let us say
+ //2507, then splitting both into half would cause left width to be 1253
+ //and right 1254. If crop is swapped because of H flip, this will cause
+ //left crop width to be 1254, whereas left dst width remains 1253, thus
+ //inducing a scaling that is unaccounted for. To overcome that we add 1
+ //to the dst width if there is a cropSwap. So if the original width was
+ //2507, the left dst width will be 1254. Even if the original width was
+ //even for ex: 2508, the left dst width will still remain 1254.
+ dstL.right = (dst.right + dst.left + cropSwap) / 2;
dstR.left = dstL.right;
}
@@ -2402,7 +2542,7 @@
//configure left pipe
if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlags, whf, z, isFg,
+ PipeArgs pargL(mdpFlags, whf, z,
static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -2415,7 +2555,7 @@
//configure right pipe
if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlags, whf, z, isFg,
+ PipeArgs pargR(mdpFlags, whf, z,
static_cast<eRotFlags>(rotFlags),
layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 1ebe0bd..8c833c2 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -74,6 +74,7 @@
MDPCOMP_AVOID_CACHE_MDP = 0x002,
MDPCOMP_AVOID_LOAD_MDP = 0x004,
MDPCOMP_AVOID_VIDEO_ONLY = 0x008,
+ MDPCOMP_AVOID_MDP_ONLY_LAYERS = 0x010,
};
/* mdp pipe data */
@@ -190,8 +191,14 @@
bool tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
bool secureOnly);
+ /* checks for conditions where only secure RGB and video can be bypassed */
+ bool tryMDPOnlyLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ bool mdpOnlyLayersComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+ bool secureOnly);
/* checks for conditions where YUV layers cannot be bypassed */
bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
+ /* checks for conditions where Secure RGB layers cannot be bypassed */
+ bool isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
/* checks if MDP/MDSS can process current list w.r.to HW limitations
* All peculiar HW limitations should go here */
bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
@@ -217,6 +224,9 @@
/* updates cache map with YUV info */
void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
bool secureOnly);
+ /* updates cache map with secure RGB info */
+ void updateSecureRGB(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list);
/* Validates if the GPU/MDP layer split chosen by a strategy is supported
* by MDP.
* Sets up MDP comp data structures to reflect covnversion from layers to
@@ -248,7 +258,7 @@
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
- static bool sEnable4k2kYUVSplit;
+ static bool sEnableYUVsplit;
bool mModeOn; // if prepare happened
bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
};
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index fed6f3c..94191b7 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -280,7 +280,7 @@
if(dpy == HWC_DISPLAY_EXTERNAL ||
ctx->mVirtualonExtActive) {
/* External display is HDMI or non-hybrid WFD solution */
- ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL_OFFLINE ONLINE"
+ ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
"hotplug event", __FUNCTION__);
ctx->proc->hotplug(ctx->proc,HWC_DISPLAY_EXTERNAL,
EXTERNAL_ONLINE);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 5cecbaa..e57e573 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -835,12 +835,12 @@
ctx->listStats[dpy].isSecurePresent = false;
ctx->listStats[dpy].yuvCount = 0;
char property[PROPERTY_VALUE_MAX];
- ctx->listStats[dpy].extOnlyLayerIndex = -1;
ctx->listStats[dpy].isDisplayAnimating = false;
ctx->listStats[dpy].secureUI = false;
ctx->listStats[dpy].yuv4k2kCount = 0;
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
ctx->listStats[dpy].renderBufIndexforABC = -1;
+ ctx->listStats[dpy].secureRGBCount = 0;
resetROI(ctx, dpy);
@@ -868,6 +868,12 @@
if (isSecureBuffer(hnd)) {
ctx->listStats[dpy].isSecurePresent = true;
+ if(not isYuvBuffer(hnd)) {
+ // cache secureRGB layer parameters like we cache for YUV layers
+ int& secureRGBCount = ctx->listStats[dpy].secureRGBCount;
+ ctx->listStats[dpy].secureRGBIndices[secureRGBCount] = (int)i;
+ secureRGBCount++;
+ }
}
if (isSkipLayer(&list->hwLayers[i])) {
@@ -879,7 +885,7 @@
ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
yuvCount++;
- if(UNLIKELY(is4kx2kYuvBuffer(hnd))){
+ if(UNLIKELY(isYUVSplitNeeded(hnd))){
int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
yuv4k2kCount++;
@@ -888,10 +894,6 @@
if(layer->blending == HWC_BLENDING_PREMULT)
ctx->listStats[dpy].preMultipliedAlpha = true;
-
- if(UNLIKELY(isExtOnly(hnd))){
- ctx->listStats[dpy].extOnlyLayerIndex = (int)i;
- }
}
if(ctx->listStats[dpy].yuvCount > 0) {
if (property_get("hw.cabl.yuv", property, NULL) > 0) {
@@ -1324,7 +1326,9 @@
rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
}
int ret = 0;
- ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
+ if(not ctx->mLayerRotMap[dpy]->isRotCached(i))
+ ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
+
if(ret < 0) {
ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
__FUNCTION__, strerror(errno));
@@ -1475,22 +1479,20 @@
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
- if(isYuvBuffer(hnd)) {
- if(isSecureBuffer(hnd)) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
- }
- if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
- metadata->interlaced) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_DEINTERLACE);
- }
+ if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
+ metadata->interlaced) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_DEINTERLACE);
+ }
+
+ // Mark MDP flags with SECURE_OVERLAY_SESSION for driver
+ if(isSecureBuffer(hnd)) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
if(isSecureDisplayBuffer(hnd)) {
- // Secure display needs both SECURE_OVERLAY and SECURE_DISPLAY_OV
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+ // Mark MDP flags with SECURE_DISPLAY_OVERLAY_SESSION for driver
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
}
@@ -1574,7 +1576,7 @@
int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
- eIsFg& isFg, const eDest& dest) {
+ const eDest& dest) {
hwc_rect_t dst = layer->displayFrame;
trimLayer(ctx, dpy, 0, dst, dst);
@@ -1590,7 +1592,7 @@
if (layer->blending == HWC_BLENDING_PREMULT)
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_BLEND_FG_PREMULT);
- PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(0),
+ PipeArgs parg(mdpFlags, whf, z, static_cast<eRotFlags>(0),
layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -1633,16 +1635,57 @@
crop.bottom = transformedCrop.y + transformedCrop.h;
}
+int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
+ if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
+ return 0;
+ }
+
+ int downscale = 0;
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ hwc_rect_t dst = layer->displayFrame;
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+ if(not hnd) {
+ return 0;
+ }
+
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ bool isInterlaced = metadata && (metadata->operation & PP_PARAM_INTERLACED)
+ && metadata->interlaced;
+ int transform = layer->transform;
+ uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+
+ if(isYuvBuffer(hnd)) {
+ if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
+ ctx->mMDP.version < qdutils::MDSS_V5) {
+ downscale = Rotator::getDownscaleFactor(crop.right - crop.left,
+ crop.bottom - crop.top, dst.right - dst.left,
+ dst.bottom - dst.top, format, isInterlaced);
+ } else {
+ Dim adjCrop(crop.left, crop.top, crop.right - crop.left,
+ crop.bottom - crop.top);
+ Dim pos(dst.left, dst.top, dst.right - dst.left,
+ dst.bottom - dst.top);
+ if(transform & HAL_TRANSFORM_ROT_90) {
+ swap(adjCrop.w, adjCrop.h);
+ }
+ downscale = Rotator::getDownscaleFactor(adjCrop.w, adjCrop.h, pos.w,
+ pos.h, format, isInterlaced);
+ }
+ }
+ return downscale;
+}
+
int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
- eIsFg& isFg, const eDest& dest, Rotator **rot) {
+ const eDest& dest, Rotator **rot) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
if (layer->flags & HWC_COLOR_FILL) {
// Configure Color layer
- return configColorLayer(ctx, layer, dpy, mdpFlags, z, isFg, dest);
+ return configColorLayer(ctx, layer, dpy, mdpFlags, z, dest);
}
ALOGE("%s: layer handle is NULL", __FUNCTION__);
return -1;
@@ -1654,7 +1697,6 @@
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform);
- int downscale = 0;
int rotFlags = ovutils::ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
@@ -1668,42 +1710,30 @@
}
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
-
- if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
- ctx->mMDP.version < qdutils::MDSS_V5) {
- downscale = getDownscaleFactor(
- crop.right - crop.left,
- crop.bottom - crop.top,
- dst.right - dst.left,
- dst.bottom - dst.top);
- if(downscale) {
- rotFlags = ROT_DOWNSCALE_ENABLED;
- }
- }
-
+ int downscale = getRotDownscale(ctx, layer);
setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
//if 90 component or downscale, use rot
- if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) {
+ if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
*rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
// BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd))
- BwcPM::setBwc(crop, dst, transform, mdpFlags);
+ BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1;
}
updateSource(orient, whf, crop, *rot);
- rotFlags |= ovutils::ROT_PREROTATED;
+ rotFlags |= ROT_PREROTATED;
}
//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,
+ PipeArgs parg(mdpFlags, whf, z,
static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -1745,7 +1775,7 @@
int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
- eIsFg& isFg, const eDest& lDest, const eDest& rDest,
+ const eDest& lDest, const eDest& rDest,
Rotator **rot) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -1761,7 +1791,6 @@
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform);
- const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
@@ -1777,8 +1806,8 @@
/* Calculate the external display position based on MDP downscale,
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
-
- setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
+ int downscale = getRotDownscale(ctx, layer);
+ setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
@@ -1792,7 +1821,7 @@
whf.format = wb->getOutputFormat();
}
- if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1860,7 +1889,7 @@
//configure left mixer
if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+ PipeArgs pargL(mdpFlagsL, whf, z,
static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -1873,7 +1902,7 @@
//configure right mixer
if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+ PipeArgs pargR(mdpFlagsR, whf, z,
static_cast<eRotFlags>(rotFlags),
layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -1891,7 +1920,7 @@
int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
- eIsFg& isFg, const eDest& lDest, const eDest& rDest,
+ const eDest& lDest, const eDest& rDest,
Rotator **rot) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -1928,7 +1957,7 @@
ctx->mLayerRotMap[dpy]->add(layer, *rot);
// BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd))
- BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
+ BwcPM::setBwc(crop, dst, transform, downscale, mdpFlagsL);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -1986,7 +2015,7 @@
//configure left half
if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlagsL, whf, lz, isFg,
+ PipeArgs pargL(mdpFlagsL, whf, lz,
static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -1999,7 +2028,7 @@
//configure right half
if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlagsR, whf, rz, isFg,
+ PipeArgs pargR(mdpFlagsR, whf, rz,
static_cast<eRotFlags>(rotFlags),
layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -2175,9 +2204,12 @@
return (eqBounds == 3);
}
-void BwcPM::setBwc(const hwc_rect_t& crop,
- const hwc_rect_t& dst, const int& transform,
- ovutils::eMdpFlags& mdpFlags) {
+void BwcPM::setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
+ const int& transform,const int& downscale,
+ ovutils::eMdpFlags& mdpFlags) {
+ //BWC not supported with rot-downscale
+ if(downscale) return;
+
//Target doesnt support Bwc
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
if(!mdpHw.supportsBWC()) {
@@ -2211,14 +2243,14 @@
}
void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
- if(mCount >= MAX_SESS) return;
+ if(mCount >= RotMgr::MAX_ROT_SESS) return;
mLayer[mCount] = layer;
mRot[mCount] = rot;
mCount++;
}
void LayerRotMap::reset() {
- for (int i = 0; i < MAX_SESS; i++) {
+ for (int i = 0; i < RotMgr::MAX_ROT_SESS; i++) {
mLayer[i] = 0;
mRot[i] = 0;
}
@@ -2230,9 +2262,27 @@
reset();
}
+bool LayerRotMap::isRotCached(uint32_t index) const {
+ overlay::Rotator* rot = getRot(index);
+ hwc_layer_1_t* layer = getLayer(index);
+
+ if(rot and layer and layer->handle) {
+ private_handle_t *hnd = (private_handle_t *)(layer->handle);
+ return (rot->isRotCached(hnd->fd,(uint32_t)(hnd->offset)));
+ }
+ return false;
+}
+
void LayerRotMap::setReleaseFd(const int& fence) {
for(uint32_t i = 0; i < mCount; i++) {
- mRot[i]->setReleaseFd(dup(fence));
+ if(mRot[i] and mLayer[i] and mLayer[i]->handle) {
+ /* Ensure that none of the above (Rotator-instance,
+ * layer and layer-handle) are NULL*/
+ if(isRotCached(i))
+ mRot[i]->setPrevBufReleaseFd(dup(fence));
+ else
+ mRot[i]->setCurrBufReleaseFd(dup(fence));
+ }
}
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 66fdc65..ca24205 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -29,7 +29,9 @@
#include <gralloc_priv.h>
#include <utils/String8.h>
#include "qdMetaData.h"
+#include "mdp_version.h"
#include <overlayUtils.h>
+#include <overlayRotator.h>
#include <EGL/egl.h>
@@ -118,7 +120,6 @@
//Video specific
int yuvCount;
int yuvIndices[MAX_NUM_APP_LAYERS];
- int extOnlyLayerIndex;
bool preMultipliedAlpha;
int yuv4k2kIndices[MAX_NUM_APP_LAYERS];
int yuv4k2kCount;
@@ -131,6 +132,9 @@
hwc_rect_t rRoi; //right ROI. Unused in single DSI panels.
//App Buffer Composition index
int renderBufIndexforABC;
+ // Secure RGB specific
+ int secureRGBCount;
+ int secureRGBIndices[MAX_NUM_APP_LAYERS];
};
//PTOR Comp info
@@ -161,8 +165,8 @@
};
struct BwcPM {
- static void setBwc(const hwc_rect_t& crop,
- const hwc_rect_t& dst, const int& transform,
+ static void setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
+ const int& transform, const int& downscale,
ovutils::eMdpFlags& mdpFlags);
};
@@ -190,7 +194,6 @@
class LayerRotMap {
public:
LayerRotMap() { reset(); }
- enum { MAX_SESS = 3 };
void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
//Resets the mapping of layer to rotator
void reset();
@@ -200,10 +203,11 @@
uint32_t getCount() const;
hwc_layer_1_t* getLayer(uint32_t index) const;
overlay::Rotator* getRot(uint32_t index) const;
+ bool isRotCached(uint32_t index) const;
void setReleaseFd(const int& fence);
private:
- hwc_layer_1_t* mLayer[MAX_SESS];
- overlay::Rotator* mRot[MAX_SESS];
+ hwc_layer_1_t* mLayer[overlay::RotMgr::MAX_ROT_SESS];
+ overlay::Rotator* mRot[overlay::RotMgr::MAX_ROT_SESS];
uint32_t mCount;
};
@@ -351,7 +355,7 @@
int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- ovutils::eIsFg& isFg, const ovutils::eDest& dest);
+ const ovutils::eDest& dest);
void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
hwc_rect_t& crop, overlay::Rotator *rot);
@@ -359,20 +363,20 @@
//Routine to configure low resolution panels (<= 2048 width)
int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- ovutils::eIsFg& isFg, const ovutils::eDest& dest,
+ const ovutils::eDest& dest,
overlay::Rotator **rot);
//Routine to configure high resolution panels (> 2048 width)
int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
+ const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
//Routine to split and configure high resolution YUV layer (> 2048 width)
int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy,
ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
- ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
+ const ovutils::eDest& lDest,
const ovutils::eDest& rDest, overlay::Rotator **rot);
//On certain targets DMA pipes are used for rotation and they won't be available
@@ -387,6 +391,8 @@
bool isDisplaySplit(hwc_context_t* ctx, int dpy);
+int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer);
+
// Set the GPU hint flag to high for MIXED/GPU composition only for
// first frame after MDP to GPU/MIXED mode transition.
// Set the GPU hint to default if the current composition type is GPU
@@ -406,10 +412,11 @@
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
}
-// Returns true if the buffer is yuv
-static inline bool is4kx2kYuvBuffer(const private_handle_t* hnd) {
+// Returns true if the buffer is yuv and exceeds the mixer width
+static inline bool isYUVSplitNeeded(const private_handle_t* hnd) {
+ int maxMixerWidth = qdutils::MDPVersion::getInstance().getMaxMixerWidth();
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
- (hnd->width > 2048));
+ (hnd->width > maxMixerWidth));
}
// Returns true if the buffer is secure
@@ -430,11 +437,6 @@
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
}
-//Return true if buffer is for external display only
-static inline bool isExtOnly(const private_handle_t* hnd) {
- return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
-}
-
//Return true if the buffer is intended for Secure Display
static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index f8f3b45..db43435 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -351,18 +351,12 @@
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) {
+ if(copybitDone) {
hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
}
- if(hnd && !isYuvBuffer(hnd)) {
+ if(hnd) {
if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h
index e24ad6a..9c38cdb 100644
--- a/liboverlay/mdpWrapper.h
+++ b/liboverlay/mdpWrapper.h
@@ -299,8 +299,8 @@
s, ov.offset, ov.memory_id, ov.id, ov.flags, ov.priv);
}
inline void dump(const char* const s, const mdp_overlay& ov) {
- ALOGE("%s mdp_overlay z=%d fg=%d alpha=%d mask=%d flags=0x%x id=%d",
- s, ov.z_order, ov.is_fg, ov.alpha,
+ ALOGE("%s mdp_overlay z=%d alpha=%d mask=%d flags=0x%x id=%d",
+ s, ov.z_order, ov.alpha,
ov.transp_mask, ov.flags, ov.id);
dump("src", ov.src);
dump("src_rect", ov.src_rect);
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 46b6275..c016d3d 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -161,6 +161,8 @@
return getPipe_8x16(pipeSpecs);
} else if(MDPVersion::getInstance().is8x39()) {
return getPipe_8x39(pipeSpecs);
+ } else if(MDPVersion::getInstance().is8994()) {
+ return getPipe_8994(pipeSpecs);
}
eDest dest = OV_INVALID;
@@ -255,6 +257,26 @@
return getPipe_8x16(pipeSpecs);
}
+utils::eDest Overlay::getPipe_8994(const PipeSpecs& pipeSpecs) {
+ //If DMA pipes need to be used in block mode for downscale, there could be
+ //cases where consecutive rounds need separate modes, which cannot be
+ //supported since we at least need 1 round in between where the DMA is
+ //unused
+ eDest dest = OV_INVALID;
+ if(pipeSpecs.formatClass == FORMAT_YUV) {
+ return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ } else {
+ 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 and not pipeSpecs.needsScaling) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ }
+ return dest;
+}
+
void Overlay::endAllSessions() {
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index c8f68b0..4f5d56d 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -172,6 +172,7 @@
utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
+ utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
/* Returns the handle to libscale.so's programScale function */
static int (*getFnProgramScale())(struct mdp_overlay_list *);
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 7f9f136..ddc40ee 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -96,7 +96,6 @@
//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);
}
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index cb8e057..d415b9d 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -99,8 +99,6 @@
void setFlags(int f);
/* set z order */
void setZ(utils::eZorder z);
- /* set isFg flag */
- void setIsFg(utils::eIsFg isFg);
/* return a copy of src whf*/
utils::Whf getSrcWhf() const;
/* set plane alpha */
@@ -204,10 +202,6 @@
mOVInfo.z_order = z;
}
-inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) {
- mOVInfo.is_fg = isFg;
-}
-
inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
mOVInfo.alpha = planeAlpha;
}
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index bb985d7..d322897 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -17,6 +17,7 @@
* limitations under the License.
*/
+#include <math.h>
#include "overlayUtils.h"
#include "overlayRotator.h"
#include "gr.h"
@@ -36,10 +37,18 @@
void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
+int MdpRot::getSrcMemId() const {
+ return mRotDataInfo.src.memory_id;
+}
+
int MdpRot::getDstMemId() const {
return mRotDataInfo.dst.memory_id;
}
+uint32_t MdpRot::getSrcOffset() const {
+ return mRotDataInfo.src.offset;
+}
+
uint32_t MdpRot::getDstOffset() const {
return mRotDataInfo.dst.offset;
}
@@ -146,7 +155,6 @@
mRotImgInfo.enable = 0;
return false;
}
- save();
mRotDataInfo.session_id = mRotImgInfo.session_id;
}
return true;
@@ -237,7 +245,10 @@
}
bool MdpRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled()) {
+ if(enabled() and (not isRotCached(fd,offset))) {
+ int prev_fd = getSrcMemId();
+ uint32_t prev_offset = getSrcOffset();
+
mRotDataInfo.src.memory_id = fd;
mRotDataInfo.src.offset = offset;
@@ -248,14 +259,17 @@
mRotDataInfo.dst.offset =
mMem.mRotOffset[mMem.mCurrIndex];
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
ALOGE("MdpRot failed rotate");
dump();
+ mRotDataInfo.src.memory_id = prev_fd;
+ mRotDataInfo.src.offset = prev_offset;
return false;
}
+ save();
+ mMem.mCurrIndex =
+ (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
}
return true;
}
@@ -274,4 +288,35 @@
ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo);
}
+int MdpRot::getDownscaleFactor(const int& src_w, const int& src_h,
+ const int& dst_w, const int& dst_h, const uint32_t& /*mdpFormat*/,
+ const bool& /*isInterlaced*/) {
+ int dscale_factor = utils::ROT_DS_NONE;
+ // We need this check to engage the rotator whenever possible to assist MDP
+ // in performing video downscale.
+ // This saves bandwidth and avoids causing the driver to make too many panel
+ // -mode switches between BLT (writeback) and non-BLT (Direct) modes.
+ // Use-case: Video playback [with downscaling and rotation].
+ if (dst_w && dst_h)
+ {
+ float fDscale = (float)(src_w * src_h) / (float)(dst_w * dst_h);
+ uint32_t dscale = (int)sqrtf(fDscale);
+
+ if(dscale < 2) {
+ // Down-scale to > 50% of orig.
+ dscale_factor = utils::ROT_DS_NONE;
+ } else if(dscale < 4) {
+ // Down-scale to between > 25% to <= 50% of orig.
+ dscale_factor = utils::ROT_DS_HALF;
+ } else if(dscale < 8) {
+ // Down-scale to between > 12.5% to <= 25% of orig.
+ dscale_factor = utils::ROT_DS_FOURTH;
+ } else {
+ // Down-scale to <= 12.5% of orig.
+ dscale_factor = utils::ROT_DS_EIGHTH;
+ }
+ }
+ return dscale_factor;
+}
+
} // namespace overlay
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 5783dcb..87e134a 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -17,6 +17,7 @@
* limitations under the License.
*/
+#include <math.h>
#include "overlayUtils.h"
#include "overlayRotator.h"
@@ -50,10 +51,18 @@
void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
+int MdssRot::getSrcMemId() const {
+ return mRotData.data.memory_id;
+}
+
int MdssRot::getDstMemId() const {
return mRotData.dst_data.memory_id;
}
+uint32_t MdssRot::getSrcOffset() const {
+ return mRotData.data.offset;
+}
+
uint32_t MdssRot::getDstOffset() const {
return mRotData.dst_data.offset;
}
@@ -80,6 +89,19 @@
uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
+void MdssRot::save() {
+ mLSRotInfo = mRotInfo;
+}
+
+bool MdssRot::rotConfChanged() const {
+ // 0 means same
+ if(0 == ::memcmp(&mRotInfo, &mLSRotInfo,
+ sizeof (mdp_overlay))) {
+ return false;
+ }
+ return true;
+}
+
bool MdssRot::init() {
if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
ALOGE("MdssRot failed to init fb0");
@@ -103,7 +125,8 @@
mRotInfo.src_rect.h = crop.h;
}
-void MdssRot::setDownscale(int /*ds*/) {
+void MdssRot::setDownscale(int downscale) {
+ mDownscale = downscale;
}
void MdssRot::setFlags(const utils::eMdpFlags& flags) {
@@ -128,19 +151,25 @@
}
bool MdssRot::commit() {
- if (utils::isYuv(mRotInfo.src.format)) {
- utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w);
- utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h);
- // For interlaced, crop.h should be 4-aligned
- if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and
- (mRotInfo.src_rect.h % 4))
- mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4);
- }
+ Dim adjCrop(mRotInfo.src_rect.x,mRotInfo.src_rect.y,
+ mRotInfo.src_rect.w,mRotInfo.src_rect.h);
+ adjCrop = getFormatAdjustedCrop(adjCrop, mRotInfo.src.format,
+ mRotInfo.flags & utils::OV_MDP_DEINTERLACE);
+ adjCrop = getDownscaleAdjustedCrop(adjCrop, mDownscale);
+
+ mRotInfo.src_rect.x = adjCrop.x;
+ mRotInfo.src_rect.y = adjCrop.y;
+ mRotInfo.src_rect.w = adjCrop.w;
+ mRotInfo.src_rect.h = adjCrop.h;
mRotInfo.dst_rect.x = 0;
mRotInfo.dst_rect.y = 0;
- mRotInfo.dst_rect.w = mRotInfo.src_rect.w;
- mRotInfo.dst_rect.h = mRotInfo.src_rect.h;
+ mRotInfo.dst_rect.w = mDownscale ?
+ mRotInfo.src_rect.w / mDownscale : mRotInfo.src_rect.w;
+ mRotInfo.dst_rect.h = mDownscale ?
+ mRotInfo.src_rect.h / mDownscale : mRotInfo.src_rect.h;
+ //Clear for next round
+ mDownscale = 0;
doTransform();
@@ -156,7 +185,10 @@
}
bool MdssRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled()) {
+ if(enabled() and (not isRotCached(fd,offset))) {
+ int prev_fd = getSrcMemId();
+ uint32_t prev_offset = getSrcOffset();
+
mRotData.data.memory_id = fd;
mRotData.data.offset = offset;
@@ -167,14 +199,17 @@
mRotData.dst_data.offset =
mMem.mRotOffset[mMem.mCurrIndex];
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) {
ALOGE("MdssRot play failed!");
dump();
+ mRotData.data.memory_id = prev_fd;
+ mRotData.data.offset = prev_offset;
return false;
}
+ save();
+ mMem.mCurrIndex =
+ (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
}
return true;
}
@@ -252,12 +287,14 @@
void MdssRot::reset() {
ovutils::memset0(mRotInfo);
+ ovutils::memset0(mLSRotInfo);
ovutils::memset0(mRotData);
mRotData.data.memory_id = -1;
mRotInfo.id = MSMFB_NEW_REQUEST;
ovutils::memset0(mMem.mRotOffset);
mMem.mCurrIndex = 0;
mOrientation = utils::OVERLAY_TRANSFORM_0;
+ mDownscale = 0;
}
void MdssRot::dump() const {
@@ -340,4 +377,54 @@
return bufSize;
}
+int MdssRot::getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced) {
+ if(not srcW or not srcH or not dstW or not dstH or isInterlaced) return 0;
+
+ Dim crop(0, 0, srcW, srcH);
+ Dim adjCrop = getFormatAdjustedCrop(crop, mdpFormat,
+ false /*isInterlaced */);
+
+ uint32_t downscale = min((adjCrop.w / dstW), (adjCrop.h / dstH));
+ //Reduced to a power of 2
+ downscale = (uint32_t) powf(2.0f, floorf(log2f((float)downscale)));
+
+ if(downscale < 2 or downscale > 32) return 0;
+
+ //Allow only 1 line or pixel to be chopped off since the source needs to
+ //be aligned to downscale. Progressively try with smaller downscale to see
+ //if we can satisfy the threshold
+ //For YUV the loop shouldnt be needed, unless in exceptional cases
+ Dim dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
+ while(downscale > 2 and (adjCrop.w > dsAdjCrop.w or
+ adjCrop.h > dsAdjCrop.h)) {
+ downscale /= 2;
+ dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
+ }
+
+ if(not dsAdjCrop.w or not dsAdjCrop.h) return 0;
+ return downscale;
+}
+
+Dim MdssRot::getFormatAdjustedCrop(const Dim& crop,
+ const uint32_t& mdpFormat, const bool& isInterlaced) {
+ Dim adjCrop = crop;
+ if (isYuv(mdpFormat)) {
+ normalizeCrop(adjCrop.x, adjCrop.w);
+ normalizeCrop(adjCrop.y, adjCrop.h);
+ // For interlaced, crop.h should be 4-aligned
+ if (isInterlaced and (adjCrop.h % 4))
+ adjCrop.h = aligndown(adjCrop.h, 4);
+ }
+ return adjCrop;
+}
+
+Dim MdssRot::getDownscaleAdjustedCrop(const Dim& crop,
+ const uint32_t& downscale) {
+ uint32_t alignedSrcW = aligndown(crop.w, downscale * 2);
+ uint32_t alignedSrcH = aligndown(crop.h, downscale * 2);
+ return Dim(crop.x, crop.y, alignedSrcW, alignedSrcH);
+}
+
} // namespace overlay
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 0671b62..b55f06a 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -20,6 +20,7 @@
#include "overlayRotator.h"
#include "overlayUtils.h"
#include "mdp_version.h"
+#include "sync/sync.h"
#include "gr.h"
namespace ovutils = overlay::utils;
@@ -28,6 +29,17 @@
//============Rotator=========================
+Rotator::Rotator() {
+ char property[PROPERTY_VALUE_MAX];
+ mRotCacheDisabled = false;
+ if((property_get("debug.rotcache.disable", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ /* Used in debugging to turnoff rotator caching */
+ mRotCacheDisabled = true;
+ }
+}
+
Rotator::~Rotator() {}
Rotator* Rotator::getRotator() {
@@ -42,6 +54,17 @@
}
}
+int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced) {
+ if(getRotatorHwType() == TYPE_MDSS) {
+ return MdssRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
+ mdpFormat, isInterlaced);
+ }
+ return MdpRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
+ mdpFormat, isInterlaced);
+}
+
uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
//dummy aligned w & h.
int alW = 0, alH = 0;
@@ -58,6 +81,20 @@
return TYPE_MDP;
}
+bool Rotator::isRotCached(int fd, uint32_t offset) const {
+ if(mRotCacheDisabled or rotConfChanged() or rotDataChanged(fd,offset))
+ return false;
+ return true;
+}
+
+bool Rotator::rotDataChanged(int fd, uint32_t offset) const {
+ /* fd and offset are the attributes of the current rotator input buffer.
+ * At this instance, getSrcMemId() and getSrcOffset() return the
+ * attributes of the previous rotator input buffer */
+ if( (fd == getSrcMemId()) and (offset == getSrcOffset()) )
+ return false;
+ return true;
+}
//============RotMem=========================
@@ -86,7 +123,7 @@
}
}
-void RotMem::setReleaseFd(const int& fence) {
+void RotMem::setCurrBufReleaseFd(const int& fence) {
int ret = 0;
if(mRelFence[mCurrIndex] >= 0) {
@@ -104,6 +141,20 @@
mRelFence[mCurrIndex] = fence;
}
+void RotMem::setPrevBufReleaseFd(const int& fence) {
+ uint32_t numRotBufs = mem.numBufs();
+ uint32_t prevIndex = (mCurrIndex + numRotBufs - 1) % (numRotBufs);
+
+ if(mRelFence[prevIndex] >= 0) {
+ /* No need of any wait as nothing will be written into this
+ * buffer by the rotator (this func is called when rotator is
+ * in cache mode) */
+ ::close(mRelFence[prevIndex]);
+ }
+
+ mRelFence[prevIndex] = fence;
+}
+
//============RotMgr=========================
RotMgr * RotMgr::sRotMgr = NULL;
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 64387cd..e045b44 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -35,7 +35,6 @@
#include "mdpWrapper.h"
#include "overlayUtils.h"
#include "overlayMem.h"
-#include "sync/sync.h"
namespace overlay {
@@ -53,7 +52,8 @@
bool close();
bool valid() { return mem.valid(); }
uint32_t size() const { return mem.bufSz(); }
- void setReleaseFd(const int& fence);
+ void setCurrBufReleaseFd(const int& fence);
+ void setPrevBufReleaseFd(const int& fence);
// rotator data info dst offset
uint32_t mRotOffset[ROT_NUM_BUFS];
@@ -73,9 +73,20 @@
virtual void setFlags(const utils::eMdpFlags& flags) = 0;
virtual void setTransform(const utils::eTransform& rot) = 0;
virtual bool commit() = 0;
+ /* return true if the current rotator state is cached */
+ virtual bool isRotCached(int fd, uint32_t offset) const;
+ /* return true if current rotator config is same as the last round*/
+ virtual bool rotConfChanged() const = 0;
+ /* return true if the current rotator input buffer fd and offset
+ * are same as the last round */
+ virtual bool rotDataChanged(int fd, uint32_t offset) const;
virtual void setDownscale(int ds) = 0;
+ /* returns the src buffer of the rotator for the previous/current round,
+ * depending on when it is called(before/after the queuebuffer)*/
+ virtual int getSrcMemId() const = 0;
//Mem id and offset should be retrieved only after rotator kickoff
virtual int getDstMemId() const = 0;
+ virtual uint32_t getSrcOffset() const = 0;
virtual uint32_t getDstOffset() const = 0;
//Destination width, height, format, position should be retrieved only after
//rotator configuration is committed via commit API
@@ -86,16 +97,29 @@
virtual bool queueBuffer(int fd, uint32_t offset) = 0;
virtual void dump() const = 0;
virtual void getDump(char *buf, size_t len) const = 0;
- void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
+ inline void setCurrBufReleaseFd(const int& fence) {
+ mMem.setCurrBufReleaseFd(fence);
+ }
+ inline void setPrevBufReleaseFd(const int& fence) {
+ mMem.setPrevBufReleaseFd(fence);
+ }
static Rotator *getRotator();
+ /* Returns downscale by successfully applying constraints
+ * Returns 0 if target doesnt support rotator downscaling
+ * or if any of the constraints are not met
+ */
+ static int getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced);
protected:
/* Rotator memory manager */
RotMem mMem;
- explicit Rotator() {}
+ Rotator();
static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
private:
+ bool mRotCacheDisabled;
/*Returns rotator h/w type */
static int getRotatorHwType();
friend class RotMgr;
@@ -113,8 +137,11 @@
virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot);
virtual bool commit();
+ virtual bool rotConfChanged() const;
virtual void setDownscale(int ds);
+ virtual int getSrcMemId() const;
virtual int getDstMemId() const;
+ virtual uint32_t getSrcOffset() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
virtual utils::Whf getDstWhf() const;
@@ -137,15 +164,22 @@
void doTransform();
/* reset underlying data, basically memset 0 */
void reset();
- /* return true if current rotator config is different
- * than last known config */
- bool rotConfChanged() const;
/* save mRotImgInfo to be last known good config*/
void save();
/* Calculates the rotator's o/p buffer size post the transform calcs and
* knowing the o/p format depending on whether fastYuv is enabled or not */
uint32_t calcOutputBufSize();
+ /* Applies downscale by taking areas
+ * Returns a log(downscale)
+ * Constraints applied:
+ * - downscale should be a power of 2
+ * - Max downscale is 1/8
+ */
+ static int getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced);
+
/* rot info*/
msm_rotator_img_info mRotImgInfo;
/* Last saved rot info*/
@@ -158,6 +192,9 @@
OvFD mFd;
friend Rotator* Rotator::getRotator();
+ friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced);
};
/*
@@ -172,8 +209,11 @@
virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot);
virtual bool commit();
+ virtual bool rotConfChanged() const;
virtual void setDownscale(int ds);
+ virtual int getSrcMemId() const;
virtual int getDstMemId() const;
+ virtual uint32_t getSrcOffset() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
virtual utils::Whf getDstWhf() const;
@@ -196,14 +236,37 @@
void doTransform();
/* reset underlying data, basically memset 0 */
void reset();
+ /* save mRotInfo to be last known good config*/
+ void save();
/* Calculates the rotator's o/p buffer size post the transform calcs and
* knowing the o/p format depending on whether fastYuv is enabled or not */
uint32_t calcOutputBufSize();
// Calculate the compressed o/p buffer size for BWC
uint32_t calcCompressedBufSize(const utils::Whf& destWhf);
+ /* Caller's responsibility to swap srcW, srcH if there is a 90 transform
+ * Returns actual downscale (not a log value)
+ * Constraints applied:
+ * - downscale should be a power of 2
+ * - Max downscale is 1/32
+ * - Equal downscale is applied in both directions
+ * - {srcW, srcH} mod downscale = 0
+ * - Interlaced content is not supported
+ */
+ static int getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced);
+
+ static utils::Dim getFormatAdjustedCrop(const utils::Dim& crop,
+ const uint32_t& mdpFormat, const bool& isInterlaced);
+
+ static utils::Dim getDownscaleAdjustedCrop(const utils::Dim& crop,
+ const uint32_t& downscale);
+
/* MdssRot info structure */
- mdp_overlay mRotInfo;
+ mdp_overlay mRotInfo;
+ /* Last saved MdssRot info structure*/
+ mdp_overlay mLSRotInfo;
/* MdssRot data structure */
msmfb_overlay_data mRotData;
/* Orientation */
@@ -212,8 +275,12 @@
OvFD mFd;
/* Enable/Disable Mdss Rot*/
bool mEnabled;
+ int mDownscale;
friend Rotator* Rotator::getRotator();
+ friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+ const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+ const bool& isInterlaced);
};
// Holder of rotator objects. Manages lifetimes
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 0e063ab..f9ee326 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -248,36 +248,6 @@
return retTrans;
}
-int getDownscaleFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h) {
- int dscale_factor = utils::ROT_DS_NONE;
- // We need this check to engage the rotator whenever possible to assist MDP
- // in performing video downscale.
- // This saves bandwidth and avoids causing the driver to make too many panel
- // -mode switches between BLT (writeback) and non-BLT (Direct) modes.
- // Use-case: Video playback [with downscaling and rotation].
- if (dst_w && dst_h)
- {
- float fDscale = (float)(src_w * src_h) / (float)(dst_w * dst_h);
- uint32_t dscale = (int)sqrtf(fDscale);
-
- if(dscale < 2) {
- // Down-scale to > 50% of orig.
- dscale_factor = utils::ROT_DS_NONE;
- } else if(dscale < 4) {
- // Down-scale to between > 25% to <= 50% of orig.
- dscale_factor = utils::ROT_DS_HALF;
- } else if(dscale < 8) {
- // Down-scale to between > 12.5% to <= 25% of orig.
- dscale_factor = utils::ROT_DS_FOURTH;
- } else {
- // Down-scale to <= 12.5% of orig.
- dscale_factor = utils::ROT_DS_EIGHTH;
- }
- }
- return dscale_factor;
-}
-
void getDecimationFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h, uint8_t& horzDeci,
uint8_t& vertDeci) {
@@ -285,15 +255,16 @@
vertDeci = 0;
float horDscale = ceilf((float)src_w / (float)dst_w);
float verDscale = ceilf((float)src_h / (float)dst_h);
+ qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
//Next power of 2, if not already
horDscale = powf(2.0f, ceilf(log2f(horDscale)));
verDscale = powf(2.0f, ceilf(log2f(verDscale)));
- //Since MDP can do 1/4 dscale and has better quality, split the task
+ //Since MDP can do downscale and has better quality, split the task
//between decimator and MDP downscale
- horDscale /= 4.0f;
- verDscale /= 4.0f;
+ horDscale /= (float)mdpHw.getMaxMDPDownscale();
+ verDscale /= (float)mdpHw.getMaxMDPDownscale();
if((int)horDscale)
horzDeci = (uint8_t)log2f(horDscale);
@@ -301,7 +272,7 @@
if((int)verDscale)
vertDeci = (uint8_t)log2f(verDscale);
- if(src_w > 2048) {
+ if(src_w > mdpHw.getMaxMixerWidth()) {
//If the client sends us something > what a layer mixer supports
//then it means it doesn't want to use split-pipe but wants us to
//decimate. A minimum decimation of 2 will ensure that the width is
@@ -338,9 +309,9 @@
const mdp_overlay& ov) {
char str[256] = {'\0'};
snprintf(str, 256,
- "%s id=%d z=%d fg=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
+ "%s id=%d z=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
"V.Deci=%d\n",
- prefix, ov.id, ov.z_order, ov.is_fg, ov.alpha,
+ prefix, ov.id, ov.z_order, ov.alpha,
ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
strlcat(buf, str, len);
getDump(buf, len, "\tsrc", ov.src);
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 530377b..2b8e303 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -210,15 +210,6 @@
ROT_DS_EIGHTH = 3,
};
-/* The values for is_fg flag for control alpha and transp
- * IS_FG_OFF means is_fg = 0
- * IS_FG_SET means is_fg = 1
- */
-enum eIsFg {
- IS_FG_OFF = 0,
- IS_FG_SET = 1
-};
-
/*
* Various mdp flags like PIPE SHARE, DEINTERLACE etc...
* kernel/common/linux/msm_mdp.h
@@ -321,19 +312,17 @@
struct PipeArgs {
PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
zorder(Z_SYSTEM_ALLOC),
- isFg(IS_FG_OFF),
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, eRotFlags r,
int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
mdpFlags(f),
whf(_whf),
zorder(z),
- isFg(fg),
rotFlags(r),
planeAlpha(pA),
blending(b){
@@ -342,7 +331,6 @@
eMdpFlags mdpFlags; // for mdp_overlay flags
Whf whf;
eZorder zorder; // stage number
- eIsFg isFg; // control alpha & transp
eRotFlags rotFlags;
int planeAlpha;
eBlending blending;
@@ -379,8 +367,6 @@
int getMdpFormat(int format);
int getMdpFormat(int format, bool tileEnabled);
int getHALFormat(int mdpFormat);
-int getDownscaleFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h);
void getDecimationFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h, uint8_t& horzDeci,
uint8_t& vertDeci);
@@ -399,6 +385,10 @@
T c(a); a=b; b=c;
}
+template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
+
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
inline int alignup(int value, int a) {
//if align = 0, return the value. Else, do alignment.
return a ? ((((value - 1) / a) + 1) * a) : value;
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index 08af00f..de18e55 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -101,8 +101,12 @@
bool Writeback::stopSession() {
if(mFd.valid()) {
+ if(!Overlay::displayCommit(mFd.getFD())) {
+ ALOGE("%s: displayCommit failed", __func__);
+ return false;
+ }
if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
- ALOGE("%s failed", __func__);
+ ALOGE("%s: wbStopTerminate failed", __func__);
return false;
}
} else {
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index a064317..108313b 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -89,8 +89,8 @@
mVGPipes = 0;
mDMAPipes = 0;
mFeatures = 0;
- mMDPUpscale = 0;
- mMDPDownscale = 0;
+ mMDPUpscale = 1;
+ mMDPDownscale = 1;
mMacroTileEnabled = false;
mLowBw = 0;
mHighBw = 0;
@@ -321,6 +321,10 @@
fclose(sysfsFd);
}
+ if(mMDPVersion >= qdutils::MDP_V4_2 and mMDPVersion < qdutils::MDSS_V5) {
+ mRotDownscale = true;
+ }
+
if(mSourceSplit) {
memset(sysfsPath, 0, sizeof(sysfsPath));
snprintf(sysfsPath , sizeof(sysfsPath),