Merge "HWC: Use proper typecast to avoid scaling issues"
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 370a7b2..b08c0c1 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -35,6 +35,7 @@
#include "overlayUtils.h"
#include "overlay.h"
#include "mdp_version.h"
+#include "qd_utils.h"
using namespace android;
@@ -585,7 +586,8 @@
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
- if(!qdutils::MDPVersion::getInstance().is8x26()) {
+ if(!qdutils::MDPVersion::getInstance().is8x26()
+ && mHwcContext->mMDPDownscaleEnabled) {
int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
// if primary resolution is more than the hdmi resolution
@@ -594,14 +596,27 @@
// Restrict this upto 1080p resolution max
if(((priW * priH) > (width * height)) &&
((priW * priH) <= SUPPORTED_DOWNSCALE_EXT_AREA)) {
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priW;
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priH;
+ // tmpW and tmpH will hold the primary dimensions before we
+ // update the aspect ratio if necessary.
+ int tmpW = priW;
+ int tmpH = priH;
// HDMI is always in landscape, so always assign the higher
// dimension to hdmi's xres
if(priH > priW) {
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priH;
- mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priW;
+ tmpW = priH;
+ tmpH = priW;
}
+ // The aspect ratios of the external and primary displays
+ // can be different. As a result, directly assigning primary
+ // resolution could lead to an incorrect final image.
+ // We get around this by calculating a new resolution by
+ // keeping aspect ratio intact.
+ hwc_rect r = {0, 0, 0, 0};
+ getAspectRatioPosition(tmpW, tmpH, width, height, r);
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres =
+ r.right - r.left;
+ mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres =
+ r.bottom - r.top;
// Set External Display MDP Downscale mode indicator
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
}
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 88b9b00..878f17c 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -47,7 +47,6 @@
#endif
#define ASTC_BLOCK_SIZE 16
-#define ASTC_IN_UNITS(n, unit_size) (((n) + (unit_size) -1) / (unit_size))
using namespace gralloc;
using namespace qdutils;
@@ -93,6 +92,7 @@
LINK_adreno_compute_aligned_width_and_height = NULL;
LINK_adreno_compute_padding = NULL;
LINK_adreno_isMacroTilingSupportedByGpu = NULL;
+ LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
if (libadreno_utils) {
@@ -102,6 +102,9 @@
::dlsym(libadreno_utils, "compute_surface_padding");
*(void **)&LINK_adreno_isMacroTilingSupportedByGpu =
::dlsym(libadreno_utils, "isMacroTilingSupportedByGpu");
+ *(void **)&LINK_adreno_compute_compressedfmt_aligned_width_and_height =
+ ::dlsym(libadreno_utils,
+ "compute_compressedfmt_aligned_width_and_height");
}
}
@@ -207,73 +210,47 @@
break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
- aligned_w = ASTC_IN_UNITS(width, 4);
- aligned_h = ASTC_IN_UNITS(height, 4);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
- aligned_w = ASTC_IN_UNITS(width, 5);
- aligned_h = ASTC_IN_UNITS(height, 4);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
- aligned_w = ASTC_IN_UNITS(width, 5);
- aligned_h = ASTC_IN_UNITS(height, 5);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
- aligned_w = ASTC_IN_UNITS(width, 6);
- aligned_h = ASTC_IN_UNITS(height, 5);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
- aligned_w = ASTC_IN_UNITS(width, 6);
- aligned_h = ASTC_IN_UNITS(height, 6);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
- aligned_w = ASTC_IN_UNITS(width, 8);
- aligned_h = ASTC_IN_UNITS(height, 5);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
- aligned_w = ASTC_IN_UNITS(width, 8);
- aligned_h = ASTC_IN_UNITS(height, 6);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
- aligned_w = ASTC_IN_UNITS(width, 8);
- aligned_h = ASTC_IN_UNITS(height, 8);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
- aligned_w = ASTC_IN_UNITS(width, 10);
- aligned_h = ASTC_IN_UNITS(height, 5);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
- aligned_w = ASTC_IN_UNITS(width, 10);
- aligned_h = ASTC_IN_UNITS(height, 6);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
- aligned_w = ASTC_IN_UNITS(width, 10);
- aligned_h = ASTC_IN_UNITS(height, 8);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
- aligned_w = ASTC_IN_UNITS(width, 10);
- aligned_h = ASTC_IN_UNITS(height, 10);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
- aligned_w = ASTC_IN_UNITS(width, 12);
- aligned_h = ASTC_IN_UNITS(height, 10);
- break;
case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
- aligned_w = ASTC_IN_UNITS(width, 12);
- aligned_h = ASTC_IN_UNITS(height, 12);
+ if(LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
+ int bytesPerPixel = 0;
+ int raster_mode = 0; //Adreno unknown raster mode.
+ int padding_threshold = 512; //Threshold for padding
+ //surfaces.
+
+ LINK_adreno_compute_compressedfmt_aligned_width_and_height(
+ width, height, format, 0,raster_mode, padding_threshold,
+ &aligned_w, &aligned_h, &bytesPerPixel);
+
+ } else {
+ ALOGW("%s: Warning!! Symbols" \
+ " compute_compressedfmt_aligned_width_and_height" \
+ " not found", __FUNCTION__);
+ }
break;
default: break;
}
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 8c68e16..20b2994 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -120,12 +120,12 @@
// Pointer to the padding library.
void *libadreno_utils;
- // link to the surface padding library.
+ // link(s)to adreno surface padding library.
int (*LINK_adreno_compute_padding) (int width, int bpp,
int surface_tile_height,
int screen_tile_height,
int padding_threshold);
- // link to the surface padding library.
+
void (*LINK_adreno_compute_aligned_width_and_height) (int width,
int height,
int bpp,
@@ -134,8 +134,18 @@
int padding_threshold,
int *aligned_w,
int *aligned_h);
- // link to the surface padding library.
+
int (*LINK_adreno_isMacroTilingSupportedByGpu) (void);
+ void(*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
+ int width,
+ int height,
+ int format,
+ int tile_mode,
+ int raster_mode,
+ int padding_threshold,
+ int *aligned_w,
+ int *aligned_h,
+ int *bpp);
};
#endif /* GR_H_ */
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 27abf6a..678eecb 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -281,121 +281,105 @@
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;
- // ext only layer present..
if(extOnlyLayerIndex != -1) {
layer = &list->hwLayers[extOnlyLayerIndex];
layer->compositionType = HWC_OVERLAY;
}
+ ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
+ ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+ mTileEnabled));
+
overlay::Overlay& ov = *(ctx->mOverlay);
-
- ovutils::Whf info(mAlignedFBWidth,
- mAlignedFBHeight,
- ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
- mTileEnabled));
- //Request left pipe
- ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_LEFT);
- if(destL == ovutils::OV_INVALID) { //None available
- ALOGE("%s: No pipes available to configure fb for dpy %d's left"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
- //Request right pipe
- ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_RIGHT);
- if(destR == ovutils::OV_INVALID) { //None available
- ALOGE("%s: No pipes available to configure fb for dpy %d's right"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- mDestLeft = destL;
- mDestRight = destR;
-
- ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_BLEND_FG_PREMULT;
-
+ ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
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::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
- ov.setSource(pargL, destL);
-
- ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
- ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
- ovutils::PipeArgs pargR(mdpFlagsR,
- info,
- zOrder,
- ovutils::IS_FG_OFF,
- ovutils::ROT_FLAGS_NONE,
- ovutils::DEFAULT_PLANE_ALPHA,
- (ovutils::eBlending)
- getBlending(layer->blending));
- ov.setSource(pargR, destR);
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(layer->transform);
+ const int hw_w = ctx->dpyAttr[mDpy].xres;
+ const int hw_h = ctx->dpyAttr[mDpy].yres;
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ mDestLeft = ovutils::OV_INVALID;
+ mDestRight = ovutils::OV_INVALID;
hwc_rect_t sourceCrop = fbUpdatingRect;
hwc_rect_t displayFrame = fbUpdatingRect;
- const float xres = ctx->dpyAttr[mDpy].xres;
- const int lSplit = getLeftSplit(ctx, mDpy);
- const float lSplitRatio = lSplit / xres;
- const float lCropWidth =
- (sourceCrop.right - sourceCrop.left) * lSplitRatio;
-
- ovutils::Dim dcropL(
- sourceCrop.left,
- sourceCrop.top,
- lCropWidth,
- sourceCrop.bottom - sourceCrop.top);
-
- ovutils::Dim dcropR(
- sourceCrop.left + lCropWidth,
- sourceCrop.top,
- (sourceCrop.right - sourceCrop.left) - lCropWidth,
- sourceCrop.bottom - sourceCrop.top);
-
- ov.setCrop(dcropL, destL);
- ov.setCrop(dcropR, destR);
-
- int transform = layer->transform;
- ovutils::eTransform orient =
- static_cast<ovutils::eTransform>(transform);
- ov.setTransform(orient, destL);
- ov.setTransform(orient, destR);
-
- const int lWidth = (lSplit - displayFrame.left);
- const int rWidth = (displayFrame.right - lSplit);
- const int height = displayFrame.bottom - displayFrame.top;
-
- ovutils::Dim dposL(displayFrame.left,
- displayFrame.top,
- lWidth,
- height);
- ov.setPosition(dposL, destL);
-
- ovutils::Dim dposR(0,
- displayFrame.top,
- rWidth,
- height);
- ov.setPosition(dposR, destR);
-
ret = true;
- if (!ov.commit(destL)) {
- ALOGE("%s: commit fails for left", __FUNCTION__);
- ret = false;
+ /* Configure left pipe */
+ if(displayFrame.left < lSplit) {
+ ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+ Overlay::MIXER_LEFT);
+ if(destL == ovutils::OV_INVALID) { //None available
+ ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+ " mixer", __FUNCTION__, mDpy);
+ return false;
+ }
+
+ mDestLeft = destL;
+
+ //XXX: FB layer plane alpha is currently sent as zero from
+ //surfaceflinger
+ ovutils::PipeArgs pargL(mdpFlags,
+ info,
+ zOrder,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
+ hwc_rect_t cropL = sourceCrop;
+ hwc_rect_t dstL = displayFrame;
+ hwc_rect_t scissorL = {0, 0, lSplit, hw_h };
+ qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
+
+ if (configMdp(ctx->mOverlay, pargL, orient, cropL,
+ dstL, NULL, destL)< 0) {
+ ALOGE("%s: configMdp fails for left FB", __FUNCTION__);
+ ret = false;
+ }
}
- if (!ov.commit(destR)) {
- ALOGE("%s: commit fails for right", __FUNCTION__);
- ret = false;
+
+ /* Configure right pipe */
+ if(displayFrame.right > lSplit) {
+ ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+ Overlay::MIXER_RIGHT);
+ if(destR == ovutils::OV_INVALID) { //None available
+ ALOGE("%s: No pipes available to configure fb for dpy %d's"
+ " right mixer", __FUNCTION__, mDpy);
+ return false;
+ }
+
+ mDestRight = destR;
+ ovutils::eMdpFlags mdpFlagsR = mdpFlags;
+ ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
+
+ //XXX: FB layer plane alpha is currently sent as zero from
+ //surfaceflinger
+ ovutils::PipeArgs pargR(mdpFlagsR,
+ info,
+ zOrder,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
+
+ hwc_rect_t cropR = sourceCrop;
+ hwc_rect_t dstR = displayFrame;
+ hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h };
+ qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
+
+ dstR.left -= lSplit;
+ dstR.right -= lSplit;
+
+ if (configMdp(ctx->mOverlay, pargR, orient, cropR,
+ dstR, NULL, destR) < 0) {
+ ALOGE("%s: configMdp fails for right FB", __FUNCTION__);
+ ret = false;
+ }
}
+
if(ret == false) {
ctx->mLayerRotMap[mDpy]->clear();
}
@@ -410,17 +394,19 @@
}
bool ret = true;
overlay::Overlay& ov = *(ctx->mOverlay);
- ovutils::eDest destL = mDestLeft;
- ovutils::eDest destR = mDestRight;
- if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
- ALOGE("%s: queue failed for left of dpy = %d",
- __FUNCTION__, mDpy);
- ret = false;
+ if(mDestLeft != ovutils::OV_INVALID) {
+ if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestLeft)) {
+ ALOGE("%s: queue failed for left of dpy = %d",
+ __FUNCTION__, mDpy);
+ ret = false;
+ }
}
- if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
- ALOGE("%s: queue failed for right of dpy = %d",
- __FUNCTION__, mDpy);
- ret = false;
+ if(mDestRight != ovutils::OV_INVALID) {
+ if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestRight)) {
+ ALOGE("%s: queue failed for right of dpy = %d",
+ __FUNCTION__, mDpy);
+ ret = false;
+ }
}
return ret;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 146730a..5c36304 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -44,6 +44,7 @@
#include "QService.h"
#include "comptype.h"
#include "hwc_virtual.h"
+#include "qd_utils.h"
using namespace qClient;
using namespace qService;
@@ -238,6 +239,14 @@
ctx->mBufferMirrorMode = false;
ctx->mVPUClient = NULL;
+ // Read the system property to determine if downscale feature is enabled.
+ ctx->mMDPDownscaleEnabled = false;
+ char value[PROPERTY_VALUE_MAX];
+ if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
+ && !strcmp(value, "true")) {
+ ctx->mMDPDownscaleEnabled = true;
+ }
+
#ifdef VPU_TARGET
if(qdutils::MDPVersion::getInstance().is8092())
ctx->mVPUClient = new VPUClient(ctx);
@@ -392,34 +401,6 @@
return;
}
-/* Calculates the aspect ratio for based on src & dest */
-void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
- int srcHeight, hwc_rect_t& rect) {
- int x =0, y =0;
-
- if (srcWidth * destHeight > destWidth * srcHeight) {
- srcHeight = destWidth * srcHeight / srcWidth;
- srcWidth = destWidth;
- } else if (srcWidth * destHeight < destWidth * srcHeight) {
- srcWidth = destHeight * srcWidth / srcHeight;
- srcHeight = destHeight;
- } else {
- srcWidth = destWidth;
- srcHeight = destHeight;
- }
- if (srcWidth > destWidth) srcWidth = destWidth;
- if (srcHeight > destHeight) srcHeight = destHeight;
- x = (destWidth - srcWidth) / 2;
- y = (destHeight - srcHeight) / 2;
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
- __FUNCTION__, x, y, srcWidth , srcHeight);
- // Convert it back to hwc_rect_t
- rect.left = x;
- rect.top = y;
- rect.right = srcWidth + rect.left;
- rect.bottom = srcHeight + rect.top;
-}
-
// This function gets the destination position for Seconday display
// based on the position and aspect ratio with orientation
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
@@ -985,8 +966,14 @@
bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
// if external supports underscan, do nothing
// it will be taken care in the driver
- if(!dpy || ctx->mExtDisplay->isCEUnderscanSupported())
+ // Disable Action safe for 8974 due to HW limitation for downscaling
+ // layers with overlapped region
+ // Disable Actionsafe for non HDMI displays.
+ if(!(dpy == HWC_DISPLAY_EXTERNAL) ||
+ qdutils::MDPVersion::getInstance().is8x74v2() ||
+ ctx->mExtDisplay->isCEUnderscanSupported()) {
return false;
+ }
char value[PROPERTY_VALUE_MAX];
// Read action safe properties
@@ -1724,6 +1711,10 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
+ /* Calculate the external display position based on MDP downscale,
+ ActionSafe, and extorientation features. */
+ calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
+
setMdpFlags(layer, mdpFlagsL, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 8a45029..4aa6410 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -262,9 +262,6 @@
/* Calculates the destination position based on the action safe rectangle */
void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
-void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
- int srcHeight, hwc_rect_t& rect);
-
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
hwc_rect_t& inRect, hwc_rect_t& outRect);
@@ -506,6 +503,9 @@
bool mPanelResetStatus;
// number of active Displays
int numActiveDisplays;
+ // Downscale feature switch, set via system the property
+ // sys.hwc.mdp_downscale_enabled
+ bool mMDPDownscaleEnabled;
};
namespace qhwc {
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index c27167f..f67de52 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -31,6 +31,7 @@
#define MAX_FRAME_BUFFER_NAME_SIZE (80)
+#define QD_UTILS_DEBUG 0
int getHDMINode(void)
{
@@ -92,3 +93,31 @@
return size;
}
+/* Calculates the aspect ratio for based on src & dest */
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+ int srcHeight, hwc_rect_t& rect) {
+ int x =0, y =0;
+
+ if (srcWidth * destHeight > destWidth * srcHeight) {
+ srcHeight = destWidth * srcHeight / srcWidth;
+ srcWidth = destWidth;
+ } else if (srcWidth * destHeight < destWidth * srcHeight) {
+ srcWidth = destHeight * srcWidth / srcHeight;
+ srcHeight = destHeight;
+ } else {
+ srcWidth = destWidth;
+ srcHeight = destHeight;
+ }
+ if (srcWidth > destWidth) srcWidth = destWidth;
+ if (srcHeight > destHeight) srcHeight = destHeight;
+ x = (destWidth - srcWidth) / 2;
+ y = (destHeight - srcHeight) / 2;
+ ALOGD_IF(QD_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
+ __FUNCTION__, x, y, srcWidth , srcHeight);
+ // Convert it back to hwc_rect_t
+ rect.left = x;
+ rect.top = y;
+ rect.right = srcWidth + rect.left;
+ rect.bottom = srcHeight + rect.top;
+}
+
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index db6d367..a35f255 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -48,4 +48,7 @@
int getEdidRawData(char *buffer);
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+ int srcHeight, hwc_rect_t& rect);
+
#endif
diff --git a/libvirtual/virtual.cpp b/libvirtual/virtual.cpp
index 795d8a1..5453e3a 100644
--- a/libvirtual/virtual.cpp
+++ b/libvirtual/virtual.cpp
@@ -48,6 +48,7 @@
#include "overlayUtils.h"
#include "overlay.h"
#include "mdp_version.h"
+#include "qd_utils.h"
using namespace android;
@@ -127,14 +128,25 @@
// by SUPPORTED_VIRTUAL_AREA).
if((maxArea == (priW * priH))
&& (maxArea <= SUPPORTED_VIRTUAL_AREA)) {
- extW = priW;
- extH = priH;
+ // tmpW and tmpH will hold the primary dimensions before we
+ // update the aspect ratio if necessary.
+ uint32_t tmpW = priW;
+ uint32_t tmpH = priH;
// If WFD is in landscape, assign the higher dimension
// to WFD's xres.
if(priH > priW) {
- extW = priH;
- extH = priW;
+ tmpW = priH;
+ tmpH = priW;
}
+ // The aspect ratios of the external and primary displays
+ // can be different. As a result, directly assigning primary
+ // resolution could lead to an incorrect final image.
+ // We get around this by calculating a new resolution by
+ // keeping aspect ratio intact.
+ hwc_rect r = {0, 0, 0, 0};
+ getAspectRatioPosition(tmpW, tmpH, extW, extH, r);
+ extW = r.right - r.left;
+ extH = r.bottom - r.top;
}
}
@@ -167,7 +179,13 @@
initResolution(extW, extH);
- if(!qdutils::MDPVersion::getInstance().is8x26()) {
+ // Dynamic Resolution Change depends on MDP downscaling.
+ // MDP downscale property will be ignored to exercise DRC use case.
+ // If DRC is in progress, ext WxH will have non-zero values.
+ bool isDRC = (extW > 0) && (extH > 0);
+
+ if(!qdutils::MDPVersion::getInstance().is8x26()
+ && (mHwcContext->mMDPDownscaleEnabled || isDRC)) {
// maxArea represents the maximum resolution between
// primary and virtual display.