Merge "hwc: Fix external display position calculation"
diff --git a/common.mk b/common.mk
index ae4ea61..d8ea260 100644
--- a/common.mk
+++ b/common.mk
@@ -18,13 +18,10 @@
#Common libraries external to display HAL
common_libs := liblog libutils libcutils libhardware
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
- common_libs += libmm-abl
-endif
-
#Common C flags
common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
-common_flags += -Werror
+#TODO: Add -Werror back once all the current warnings are fixed
+common_flags += -Wconversion -Wall
ifeq ($(ARCH_ARM_HAVE_NEON),true)
common_flags += -D__ARM_HAVE_NEON
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index e6395fb..370a7b2 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -113,7 +113,7 @@
* Used to show QCOM 8974 instead of Input 1 for example
*/
void ExternalDisplay::setSPDInfo(const char* node, const char* property) {
- int err = -1;
+ ssize_t err = -1;
char info[PROPERTY_VALUE_MAX];
char sysFsSPDFilePath[MAX_SYSFS_FILE_PATH];
memset(sysFsSPDFilePath, 0, sizeof(sysFsSPDFilePath));
@@ -172,9 +172,10 @@
void ExternalDisplay::readCEUnderscanInfo()
{
int hdmiScanInfoFile = -1;
- int len = -1;
+ ssize_t len = -1;
char scanInfo[17];
char *ce_info_str = NULL;
+ char *save_ptr;
const char token[] = ", \n";
int ce_info = -1;
char sysFsScanInfoFilePath[MAX_SYSFS_FILE_PATH];
@@ -190,7 +191,7 @@
return;
} else {
len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
- ALOGD("%s: Scan Info string: %s length = %d",
+ ALOGD("%s: Scan Info string: %s length = %zu",
__FUNCTION__, scanInfo, len);
if (len <= 0) {
close(hdmiScanInfoFile);
@@ -199,8 +200,8 @@
return;
}
scanInfo[len] = '\0'; /* null terminate the string */
+ close(hdmiScanInfoFile);
}
- close(hdmiScanInfoFile);
/*
* The scan_info contains the three fields
@@ -210,13 +211,13 @@
*/
/* PT */
- ce_info_str = strtok(scanInfo, token);
+ ce_info_str = strtok_r(scanInfo, token, &save_ptr);
if (ce_info_str) {
/* IT */
- ce_info_str = strtok(NULL, token);
+ ce_info_str = strtok_r(NULL, token, &save_ptr);
if (ce_info_str) {
/* CE */
- ce_info_str = strtok(NULL, token);
+ ce_info_str = strtok_r(NULL, token, &save_ptr);
if (ce_info_str)
ce_info = atoi(ce_info_str);
}
@@ -303,7 +304,7 @@
"/sys/devices/virtual/graphics/fb%d/edid_modes", mFbNum);
int hdmiEDIDFile = open(sysFsEDIDFilePath, O_RDONLY, 0);
- int len = -1;
+ ssize_t len = -1;
char edidStr[128] = {'\0'};
if (hdmiEDIDFile < 0) {
@@ -312,7 +313,7 @@
return false;
} else {
len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
- ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d",
+ ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
__FUNCTION__, edidStr, len);
if ( len <= 0) {
ALOGE("%s: edid_modes file empty '%s'",
@@ -325,8 +326,8 @@
}
edidStr[len] = '\0';
}
+ close(hdmiEDIDFile);
}
- close(hdmiEDIDFile);
if(len > 0) {
// Get EDID modes from the EDID strings
mModeCount = parseResolution(edidStr, mEDIDModes);
@@ -557,7 +558,7 @@
__FUNCTION__, sysFsHPDFilePath, hdmiHPDFile, strerror(errno));
ret = false;
} else {
- int err = -1;
+ ssize_t err = -1;
ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption);
if(userOption)
err = write(hdmiHPDFile, "1", 2);
@@ -606,7 +607,7 @@
}
}
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
- 1000000000l / fps;
+ (int) 1000000000l / fps;
}
}
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 42f3c77..88b9b00 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -393,6 +393,7 @@
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
{
tileEnabled = true;
// check the usage flags
@@ -566,9 +567,7 @@
tileEnabled,
alignedw,
alignedh);
-
- if(size)
- size = getSize(format, width, height, alignedw, alignedh);
+ size = getSize(format, width, height, alignedw, alignedh);
}
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index 3109303..a7a58dc 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -134,12 +134,16 @@
memset(&module->commit, 0, sizeof(struct mdp_display_commit));
struct fb_fix_screeninfo finfo;
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ close(fd);
return -errno;
+ }
struct fb_var_screeninfo info;
- if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+ close(fd);
return -errno;
+ }
info.reserved[0] = 0;
info.reserved[1] = 0;
@@ -232,8 +236,10 @@
info.yres_virtual, info.yres*2);
}
- if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+ close(fd);
return -errno;
+ }
if (int(info.width) <= 0 || int(info.height) <= 0) {
// the driver doesn't return that information
@@ -250,6 +256,7 @@
metadata.op = metadata_op_frame_rate;
if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
ALOGE("Error retrieving panel frame rate");
+ close(fd);
return -errno;
}
float fps = metadata.data.panel_frame_rate;
@@ -289,11 +296,15 @@
);
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ close(fd);
return -errno;
+ }
- if (finfo.smem_len <= 0)
+ if (finfo.smem_len <= 0) {
+ close(fd);
return -errno;
+ }
module->flags = flags;
module->info = info;
@@ -322,6 +333,7 @@
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;
}
module->framebuffer->base = intptr_t(vaddr);
@@ -373,6 +385,10 @@
/* initialize our state here */
fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
+ if(dev == NULL) {
+ gralloc_close(gralloc_device);
+ return status;
+ }
memset(dev, 0, sizeof(*dev));
/* initialize the procs */
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index bb7060b..b6253cd 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -95,13 +95,6 @@
if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
- //The EXTERNAL_BLOCK flag is always an add-on
- if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
- flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
- }
- if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
- flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
- }
}
if (bufferType == BUFFER_TYPE_VIDEO) {
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index c56eca9..89f1a88 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,13 +60,8 @@
/* Buffer content should be displayed on an external display only */
GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x08000000,
- /* Only this buffer content should be displayed on external, even if
- * other EXTERNAL_ONLY buffers are available. Used during suspend.
- */
- GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00100000,
-
- /* Close Caption displayed on an external display only */
- GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x00200000,
+ /* This flag is set for WFD usecase */
+ GRALLOC_USAGE_PRIVATE_WFD = 0x00200000,
/* CAMERA heap is a carveout heap for camera, is not secured*/
GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x00400000,
@@ -85,6 +80,7 @@
GRALLOC_MODULE_PERFORM_GET_STRIDE,
GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
+ GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
};
#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
@@ -194,10 +190,6 @@
PRIV_FLAGS_NOT_MAPPED = 0x00001000,
// Display on external only
PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
- // Display only this buffer on external
- PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000,
- // Display this buffer on external as close caption
- PRIV_FLAGS_EXTERNAL_CC = 0x00008000,
PRIV_FLAGS_VIDEO_ENCODER = 0x00010000,
PRIV_FLAGS_CAMERA_WRITE = 0x00020000,
PRIV_FLAGS_CAMERA_READ = 0x00040000,
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 109c141..df9f7e4 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -368,6 +368,19 @@
res = 0;
} break;
+ case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ int *color_space = va_arg(args, int *);
+ if (private_handle_t::validate(hnd)) {
+ return res;
+ }
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
+ *color_space = metadata->colorSpace;
+ res = 0;
+ }
+ } break;
default:
break;
}
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index db456bc..15b9da4 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -437,8 +437,11 @@
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- if (!ctx->mPanelResetStatus)
+ if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+ ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
+ ctx->mPanelResetStatus = false;
return;
+ }
ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
@@ -484,9 +487,6 @@
case HWC_COLOR_FILL:
value[0] = 1;
break;
- case HWC_MAX_WRITEBACK_WIDTH:
- value[0] = qdutils::MAX_DISPLAY_DIM;
- break;
default:
return -EINVAL;
}
@@ -777,6 +777,8 @@
if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
struct hwc_context_t *dev;
dev = (hwc_context_t*)malloc(sizeof(*dev));
+ if(dev == NULL)
+ return status;
memset(dev, 0, sizeof(*dev));
//Initialize hwc context
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 8c83469..3a4bada 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -26,6 +26,7 @@
#include "gr.h"
#include "cb_utils.h"
#include "cb_swap_rect.h"
+#include "math.h"
using namespace qdutils;
namespace qhwc {
@@ -488,12 +489,6 @@
dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
src_crop_width,src_crop_height);
- //Driver makes width and height as even
- //that may cause wrong calculation of the ratio
- //in display and crop.Hence we make
- //crop width and height as even.
- src_crop_width = (src_crop_width/2)*2;
- src_crop_height = (src_crop_height/2)*2;
int tmp_w = src_crop_width;
int tmp_h = src_crop_height;
@@ -502,10 +497,11 @@
tmp_w = src_crop_width*copybitsMaxScale;
tmp_h = src_crop_height*copybitsMaxScale;
}else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
- tmp_w = src_crop_width/copybitsMinScale;
- tmp_h = src_crop_height/copybitsMinScale;
- tmp_w = (tmp_w/2)*2;
- tmp_h = (tmp_h/2)*2;
+ // ceil the tmp_w and tmp_h value to maintain proper ratio
+ // b/w src and dst (should not cross the desired scale limit
+ // due to float -> int )
+ tmp_w = ceil(src_crop_width/copybitsMinScale);
+ tmp_h = ceil(src_crop_height/copybitsMinScale);
}
ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
@@ -517,7 +513,7 @@
src.format != HAL_PIXEL_FORMAT_RGBA_8888) {
format = HAL_PIXEL_FORMAT_RGBX_8888;
}
- if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, format, usage)){
+ if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, format, usage) && tmpHnd) {
copybit_image_t tmp_dst;
copybit_rect_t tmp_rect;
tmp_dst.w = tmp_w;
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index 6df8ce3..bebcc18 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -61,11 +61,12 @@
mDpy(dpy) {
char dumpPropStr[PROPERTY_VALUE_MAX];
if(mDpy) {
- strncpy(mDisplayName, "external", strlen("external"));
+ strlcpy(mDisplayName, "external", sizeof(mDisplayName));
} else {
- strncpy(mDisplayName, "primary", strlen("primary"));
+ strlcpy(mDisplayName, "primary", sizeof(mDisplayName));
}
- sprintf(mDumpPropKeyDisplayType, "debug.sf.dump.%s", (char *)mDisplayName);
+ snprintf(mDumpPropKeyDisplayType, sizeof(mDumpPropKeyDisplayType),
+ "debug.sf.dump.%s", (char *)mDisplayName);
if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
if(!strncmp(dumpPropStr, "true", strlen("true"))) {
@@ -113,7 +114,7 @@
if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
(strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
// Strings exist & not equal implies it has changed, so trigger a dump
- strncpy(mDumpPropStrPng, dumpPropStr, PROPERTY_VALUE_MAX - 1);
+ strlcpy(mDumpPropStrPng, dumpPropStr, sizeof(mDumpPropStrPng));
mDumpCntLimPng = atoi(dumpPropStr);
if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
@@ -122,7 +123,7 @@
}
mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
if (mDumpCntLimPng) {
- sprintf(mDumpDirPng,
+ snprintf(mDumpDirPng, sizeof(mDumpDirPng),
"/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
dumpTime.tm_mday, dumpTime.tm_hour,
@@ -143,7 +144,7 @@
if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
(strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
// Strings exist & not equal implies it has changed, so trigger a dump
- strncpy(mDumpPropStrRaw, dumpPropStr, PROPERTY_VALUE_MAX - 1);
+ strlcpy(mDumpPropStrRaw, dumpPropStr, sizeof(mDumpPropStrRaw));
mDumpCntLimRaw = atoi(dumpPropStr);
if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
ALOGW("Warning: Using debug.sf.dump %d (= max)",
@@ -152,7 +153,7 @@
}
mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
if (mDumpCntLimRaw) {
- sprintf(mDumpDirRaw,
+ snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
"/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
dumpTime.tm_mday, dumpTime.tm_hour,
@@ -277,11 +278,13 @@
bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
if (needDumpPng) {
- sprintf(dumpLogStrPng, "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
+ snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
+ "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
mDumpCntLimPng);
}
if (needDumpRaw) {
- sprintf(dumpLogStrRaw, "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
+ snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
+ "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
mDumpCntLimRaw);
}
@@ -311,7 +314,8 @@
char dumpFilename[PATH_MAX];
SkBitmap *tempSkBmp = new SkBitmap();
SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
- sprintf(dumpFilename, "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
+ snprintf(dumpFilename, sizeof(dumpFilename),
+ "%s/sfdump%03d.layer%d.%s.png", mDumpDirPng,
mDumpCntrPng, layerIndex, mDisplayName);
switch (hnd->format) {
@@ -347,7 +351,8 @@
if (needDumpRaw && hnd->base) {
char dumpFilename[PATH_MAX];
bool bResult = false;
- sprintf(dumpFilename, "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
+ snprintf(dumpFilename, sizeof(dumpFilename),
+ "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
mDumpDirRaw, mDumpCntrRaw,
layerIndex, getWidth(hnd), getHeight(hnd),
pixFormatStr, mDisplayName);
@@ -369,65 +374,65 @@
switch(format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
- strcpy(pixFormatStr, "RGBA_8888");
+ strlcpy(pixFormatStr, "RGBA_8888", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
- strcpy(pixFormatStr, "RGBX_8888");
+ strlcpy(pixFormatStr, "RGBX_8888", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_RGB_888:
- strcpy(pixFormatStr, "RGB_888");
+ strlcpy(pixFormatStr, "RGB_888", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_RGB_565:
- strcpy(pixFormatStr, "RGB_565");
+ strlcpy(pixFormatStr, "RGB_565", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
- strcpy(pixFormatStr, "BGRA_8888");
+ strlcpy(pixFormatStr, "BGRA_8888", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YV12:
- strcpy(pixFormatStr, "YV12");
+ strlcpy(pixFormatStr, "YV12", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- strcpy(pixFormatStr, "YCbCr_422_SP_NV16");
+ strlcpy(pixFormatStr, "YCbCr_422_SP_NV16", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- strcpy(pixFormatStr, "YCrCb_420_SP_NV21");
+ strlcpy(pixFormatStr, "YCrCb_420_SP_NV21", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I:
- strcpy(pixFormatStr, "YCbCr_422_I_YUY2");
+ strlcpy(pixFormatStr, "YCbCr_422_I_YUY2", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCrCb_422_I:
- strlcpy(pixFormatStr, "YCrCb_422_I_YVYU",
- sizeof("YCrCb_422_I_YVYU"));
+ strlcpy(pixFormatStr, "YCrCb_422_I_YVYU", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
- strcpy(pixFormatStr, "NV12_ENCODEABLE");
+ strlcpy(pixFormatStr, "NV12_ENCODEABLE", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
- strcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2");
+ strlcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2",
+ sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- strcpy(pixFormatStr, "YCbCr_420_SP");
+ strlcpy(pixFormatStr, "YCbCr_420_SP", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
- strcpy(pixFormatStr, "YCrCb_420_SP_ADRENO");
+ strlcpy(pixFormatStr, "YCrCb_420_SP_ADRENO", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
- strcpy(pixFormatStr, "YCrCb_422_SP");
+ strlcpy(pixFormatStr, "YCrCb_422_SP", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_R_8:
- strcpy(pixFormatStr, "R_8");
+ strlcpy(pixFormatStr, "R_8", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_RG_88:
- strcpy(pixFormatStr, "RG_88");
+ strlcpy(pixFormatStr, "RG_88", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_INTERLACE:
- strcpy(pixFormatStr, "INTERLACE");
+ strlcpy(pixFormatStr, "INTERLACE", sizeof(pixFormatStr));
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
- strcpy(pixFormatStr, "YCbCr_420_SP_VENUS");
+ strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
break;
default:
- sprintf(pixFormatStr, "Unknown0x%X", format);
+ snprintf(pixFormatStr, sizeof(pixFormatStr), "Unknown0x%X", format);
break;
}
}
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index b81494d..27abf6a 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -39,13 +39,16 @@
IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
if(isDisplaySplit(ctx, dpy)) {
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ return new FBSrcSplit(ctx, dpy);
+ }
return new FBUpdateSplit(ctx, dpy);
}
return new FBUpdateNonSplit(ctx, dpy);
}
IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
- size_t size;
+ size_t size = 0;
getBufferAttributes(ctx->dpyAttr[mDpy].xres,
ctx->dpyAttr[mDpy].yres,
HAL_PIXEL_FORMAT_RGBA_8888,
@@ -62,7 +65,8 @@
bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder) {
- return prepare(ctx, list, fbZorder) &&
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+ return prepare(ctx, list, layer->displayFrame, fbZorder) &&
ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
}
@@ -106,19 +110,19 @@
}
bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
- mModeOn = configure(ctx, list, fbZorder);
+ mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
return mModeOn;
}
// Configure
bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
@@ -159,6 +163,15 @@
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t displayFrame = layer->displayFrame;
+
+ // No FB update optimization on (1) Custom FB resolution,
+ // (2) External Mirror mode, (3) External orientation
+ if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+ && !ctx->mExtOrientation) {
+ sourceCrop = fbUpdatingRect;
+ displayFrame = fbUpdatingRect;
+ }
+
int transform = layer->transform;
int rotFlags = ovutils::ROT_FLAGS_NONE;
@@ -251,20 +264,20 @@
}
bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
- mModeOn = configure(ctx, list, fbZorder);
+ mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
return mModeOn;
}
// Configure
bool FBUpdateSplit::configure(hwc_context_t *ctx,
- hwc_display_contents_1 *list, int fbZorder) {
+ hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
@@ -328,8 +341,8 @@
getBlending(layer->blending));
ov.setSource(pargR, destR);
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
+ hwc_rect_t sourceCrop = fbUpdatingRect;
+ hwc_rect_t displayFrame = fbUpdatingRect;
const float xres = ctx->dpyAttr[mDpy].xres;
const int lSplit = getLeftSplit(ctx, mDpy);
@@ -412,5 +425,102 @@
return ret;
}
+//=================FBSrcSplit====================================
+FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
+ FBUpdateSplit(ctx, dpy) {}
+
+bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
+ bool ret = false;
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+ int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
+ // ext only layer present..
+ if(extOnlyLayerIndex != -1) {
+ layer = &list->hwLayers[extOnlyLayerIndex];
+ layer->compositionType = HWC_OVERLAY;
+ }
+ overlay::Overlay& ov = *(ctx->mOverlay);
+
+ ovutils::Whf info(mAlignedFBWidth,
+ mAlignedFBHeight,
+ ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+ mTileEnabled));
+ //Request left pipe, VG first owing to higher prio
+ ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy,
+ Overlay::MIXER_DEFAULT);
+ if(destL == ovutils::OV_INVALID) {
+ destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+ Overlay::MIXER_DEFAULT);
+ if(destL == ovutils::OV_INVALID) {
+ 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_DEFAULT);
+ if(destR == ovutils::OV_INVALID) {
+ ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+ " mixer", __FUNCTION__, mDpy);
+ return false;
+ }
+
+ mDestLeft = destL;
+ mDestRight = destR;
+
+ ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+ ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+
+ ovutils::PipeArgs parg(mdpFlags,
+ info,
+ zOrder,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAGS_NONE,
+ ovutils::DEFAULT_PLANE_ALPHA,
+ (ovutils::eBlending)
+ getBlending(layer->blending));
+ ov.setSource(parg, destL);
+ ov.setSource(parg, destR);
+
+ //Crop and Position are same for FB
+ ovutils::Dim cropPosL(
+ fbUpdatingRect.left,
+ fbUpdatingRect.top,
+ (fbUpdatingRect.right - fbUpdatingRect.left) / 2,
+ fbUpdatingRect.bottom - fbUpdatingRect.top);
+
+ ovutils::Dim cropPosR(
+ cropPosL.x + cropPosL.w,
+ cropPosL.y,
+ cropPosL.w,
+ cropPosL.h);
+
+ ov.setCrop(cropPosL, destL);
+ ov.setCrop(cropPosR, destR);
+ ov.setPosition(cropPosL, destL);
+ ov.setPosition(cropPosR, destR);
+
+ int transform = layer->transform;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+ ov.setTransform(orient, destL);
+ ov.setTransform(orient, destR);
+
+ ret = true;
+ if (!ov.commit(destL)) {
+ ALOGE("%s: commit fails for left", __FUNCTION__);
+ ret = false;
+ }
+ if (!ov.commit(destR)) {
+ ALOGE("%s: commit fails for right", __FUNCTION__);
+ ret = false;
+ }
+ if(ret == false) {
+ ctx->mLayerRotMap[mDpy]->clear();
+ }
+ return ret;
+}
+
//---------------------------------------------------------------------
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index da4cdfc..545f5bd 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -39,7 +39,7 @@
virtual ~IFBUpdate() {};
// Sets up members and prepares overlay if conditions are met
virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) = 0;
+ hwc_rect_t fbUpdatingRect, int fbZorder) = 0;
virtual bool prepareAndValidate(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder);
// Draws layer
@@ -64,12 +64,12 @@
explicit FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy);
virtual ~FBUpdateNonSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
private:
bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool preRotateExtDisplay(hwc_context_t *ctx,
hwc_layer_1_t *layer,
ovutils::Whf &info,
@@ -85,16 +85,27 @@
explicit FBUpdateSplit(hwc_context_t *ctx, const int& dpy);
virtual ~FBUpdateSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
-private:
- bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+
+protected:
+ virtual bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+ hwc_rect_t fbUpdatingRect, int fbZorder);
ovutils::eDest mDestLeft; //left pipe to draw on
ovutils::eDest mDestRight; //right pipe to draw on
};
+//Source Split Handler
+class FBSrcSplit : public FBUpdateSplit {
+public:
+ explicit FBSrcSplit(hwc_context_t *ctx, const int& dpy);
+ virtual ~FBSrcSplit() {};
+private:
+ bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+ hwc_rect_t fbUpdatingRect, int fbZorder);
+};
+
}; //namespace qhwc
#endif //HWC_FBUPDATE_H
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 6ff1aa3..028af47 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -38,17 +38,19 @@
IdleInvalidator *MDPComp::idleInvalidator = NULL;
bool MDPComp::sIdleFallBack = false;
+bool MDPComp::sHandleTimeout = false;
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
bool MDPComp::sEnableMixedMode = true;
bool MDPComp::sEnablePartialFrameUpdate = false;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-double MDPComp::sMaxBw = 0.0;
-double MDPComp::sBwClaimed = 0.0;
bool MDPComp::sEnable4k2kYUVSplit = false;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
if(isDisplaySplit(ctx, dpy)) {
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ return new MDPCompSrcSplit(dpy);
+ }
return new MDPCompSplit(dpy);
}
return new MDPCompNonSplit(dpy);
@@ -114,7 +116,7 @@
sDebugLogs = true;
}
- if(property_get("persist.hwc.partialupdate.enable", property, NULL) > 0) {
+ if(property_get("persist.hwc.partialupdate", property, NULL) > 0) {
if((atoi(property) != 0) && ctx->mMDP.panel == MIPI_CMD_PANEL &&
qdutils::MDPVersion::getInstance().is8x74v2())
sEnablePartialFrameUpdate = true;
@@ -171,7 +173,12 @@
ALOGE("%s: received empty data in timer callback", __FUNCTION__);
return;
}
-
+ Locker::Autolock _l(ctx->mDrawLock);
+ // Handle timeout event only if the previous composition is MDP or MIXED.
+ if(!sHandleTimeout) {
+ ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
+ return;
+ }
if(!ctx->proc) {
ALOGE("%s: HWC proc not registered", __FUNCTION__);
return;
@@ -657,13 +664,11 @@
bool ret = false;
if(list->flags & HWC_GEOMETRY_CHANGED) { //Try load based first
- ret = loadBasedCompPreferGPU(ctx, list) or
- loadBasedCompPreferMDP(ctx, list) or
+ ret = loadBasedComp(ctx, list) or
cacheBasedComp(ctx, list);
} else {
ret = cacheBasedComp(ctx, list) or
- loadBasedCompPreferGPU(ctx, list) or
- loadBasedCompPreferMDP(ctx, list);
+ loadBasedComp(ctx, list);
}
return ret;
@@ -719,196 +724,89 @@
return true;
}
-bool MDPComp::loadBasedCompPreferGPU(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- if(not isLoadBasedCompDoable(ctx)) {
- return false;
- }
-
- int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- mCurrentFrame.reset(numAppLayers);
-
- int stagesForMDP = min(sMaxPipesPerMixer, ctx->mOverlay->availablePipes(
- mDpy, Overlay::MIXER_DEFAULT));
- //If MDP has X possible stages, it can take X layers.
- const int batchSize = (numAppLayers - mCurrentFrame.dropCount) -
- (stagesForMDP - 1); //1 for FB
-
- if(batchSize <= 0) {
- ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
- return false;
- }
-
- int minBatchStart = -1;
- int minBatchEnd = -1;
- size_t minBatchPixelCount = SIZE_MAX;
-
- /* Iterate through the layer list to find out a contigous batch of batchSize
- * non-dropped layers with loweest pixel count */
- for(int i = 0; i <= (numAppLayers - batchSize); i++) {
- if(mCurrentFrame.drop[i])
- continue;
-
- int batchCount = batchSize;
- uint32_t batchPixelCount = 0;
- int j = i;
- for(; j < numAppLayers && batchCount; j++){
- if(!mCurrentFrame.drop[j]) {
- hwc_layer_1_t* layer = &list->hwLayers[j];
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
-
- /* If we have a valid ROI, count pixels only for the MDP fetched
- * region of the buffer */
- if((ctx->listStats[mDpy].roi.w != ctx->dpyAttr[mDpy].xres) ||
- (ctx->listStats[mDpy].roi.h != ctx->dpyAttr[mDpy].yres)) {
- hwc_rect_t roi;
- roi.left = ctx->listStats[mDpy].roi.x;
- roi.top = ctx->listStats[mDpy].roi.y;
- roi.right = roi.left + ctx->listStats[mDpy].roi.w;
- roi.bottom = roi.top + ctx->listStats[mDpy].roi.h;
-
- /* valid ROI means no scaling layer is composed. So check
- * only intersection to find actual fetched pixels */
- crop = getIntersection(roi, dst);
- }
-
- batchPixelCount += (crop.right - crop.left) *
- (crop.bottom - crop.top);
- batchCount--;
- }
- }
-
- /* we dont want to program any batch of size lesser than batchSize */
- if(!batchCount && (batchPixelCount < minBatchPixelCount)) {
- minBatchPixelCount = batchPixelCount;
- minBatchStart = i;
- minBatchEnd = j-1;
- }
- }
-
- if(minBatchStart < 0) {
- ALOGD_IF(isDebug(), "%s: No batch found batchSize %d numAppLayers %d",
- __FUNCTION__, batchSize, numAppLayers);
- return false;
- }
-
- /* non-dropped layers falling ouside the selected batch will be marked for
- * MDP */
- for(int i = 0; i < numAppLayers; i++) {
- if((i < minBatchStart || i > minBatchEnd) && !mCurrentFrame.drop[i] ) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
- __FUNCTION__, i);
- reset(ctx);
- return false;
- }
- mCurrentFrame.isFBComposed[i] = false;
- }
- }
-
- mCurrentFrame.fbZ = minBatchStart;
- mCurrentFrame.fbCount = batchSize;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
- mCurrentFrame.dropCount;
-
- ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d fbStart: %d fbEnd: %d",
- __FUNCTION__, mCurrentFrame.fbZ, batchSize, minBatchStart,
- minBatchEnd);
-
- if(sEnable4k2kYUVSplit){
- adjustForSourceSplit(ctx, list);
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
- return false;
- }
-
- return true;
-}
-
-bool MDPComp::loadBasedCompPreferMDP(hwc_context_t *ctx,
+bool MDPComp::loadBasedComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
if(not isLoadBasedCompDoable(ctx)) {
return false;
}
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
- mCurrentFrame.reset(numAppLayers);
+ const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
+ const int stagesForMDP = min(sMaxPipesPerMixer,
+ ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
- //Full screen is from ib perspective, not actual full screen
- const int bpp = 4;
- double panelRefRate =
- 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
+ int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
+ int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
+ int lastMDPSupportedIndex = numAppLayers;
+ int dropCount = 0;
- double bwLeft = sMaxBw - sBwClaimed;
-
- const int fullScreenLayers = bwLeft * 1000000000 / (ctx->dpyAttr[mDpy].xres
- * ctx->dpyAttr[mDpy].yres * bpp * panelRefRate);
-
- const int fbBatchSize = (numAppLayers - mCurrentFrame.dropCount)
- - (fullScreenLayers - 1);
-
- //If batch size is not at least 2, we aren't really preferring MDP, since
- //only 1 layer going to GPU could actually translate into an entire FB
- //needed to be fetched by MDP, thus needing more b/w rather than less.
- if(fbBatchSize < 2 || fbBatchSize > numAppLayers) {
- ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
- return false;
- }
-
- //Find top fbBatchSize non-dropped layers to get your batch
- int fbStart = -1, fbEnd = -1, batchCount = fbBatchSize;
- for(int i = numAppLayers - 1; i >= 0; i--) {
- if(mCurrentFrame.drop[i])
+ //Find the minimum MDP batch size
+ for(int i = 0; i < numAppLayers;i++) {
+ if(mCurrentFrame.drop[i]) {
+ dropCount++;
continue;
-
- if(fbEnd < 0)
- fbEnd = i;
-
- if(!(--batchCount)) {
- fbStart = i;
+ }
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ if(not isSupportedForMDPComp(ctx, layer)) {
+ lastMDPSupportedIndex = i;
+ mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
+ fbBatchSize = numNonDroppedLayers - mdpBatchSize;
break;
}
}
- //Bottom layers constitute MDP batch
- for(int i = 0; i < fbStart; i++) {
- if((i < fbStart || i > fbEnd) && !mCurrentFrame.drop[i] ) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
- ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
- __FUNCTION__, i);
- reset(ctx);
- return false;
- }
- mCurrentFrame.isFBComposed[i] = false;
- }
+ ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
+ "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
+ mCurrentFrame.dropCount);
+
+ //Start at a point where the fb batch should at least have 2 layers, for
+ //this mode to be justified.
+ while(fbBatchSize < 2) {
+ ++fbBatchSize;
+ --mdpBatchSize;
}
- mCurrentFrame.fbZ = fbStart;
- mCurrentFrame.fbCount = fbBatchSize;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount
- - mCurrentFrame.dropCount;
-
- ALOGD_IF(isDebug(), "%s: FB Z %d, app layers %d, non-dropped layers: %d, "
- "MDP Batch Size %d",__FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
- numAppLayers - mCurrentFrame.dropCount, mCurrentFrame.mdpCount);
-
- if(sEnable4k2kYUVSplit){
- adjustForSourceSplit(ctx, list);
- }
-
- if(!postHeuristicsHandling(ctx, list)) {
- ALOGD_IF(isDebug(), "post heuristic handling failed");
- reset(ctx);
+ //If there are no layers for MDP, this mode doesnt make sense.
+ if(mdpBatchSize < 1) {
+ ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
+ __FUNCTION__);
return false;
}
- return true;
+ mCurrentFrame.reset(numAppLayers);
+
+ //Try with successively smaller mdp batch sizes until we succeed or reach 1
+ while(mdpBatchSize > 0) {
+ //Mark layers for MDP comp
+ int mdpBatchLeft = mdpBatchSize;
+ for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
+ if(mCurrentFrame.drop[i]) {
+ continue;
+ }
+ mCurrentFrame.isFBComposed[i] = false;
+ --mdpBatchLeft;
+ }
+
+ mCurrentFrame.fbZ = mdpBatchSize;
+ mCurrentFrame.fbCount = fbBatchSize;
+ mCurrentFrame.mdpCount = mdpBatchSize;
+
+ ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
+ __FUNCTION__, mdpBatchSize, fbBatchSize,
+ mCurrentFrame.dropCount);
+
+ if(postHeuristicsHandling(ctx, list)) {
+ ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
+ __FUNCTION__);
+ return true;
+ }
+
+ reset(ctx);
+ --mdpBatchSize;
+ ++fbBatchSize;
+ }
+
+ return false;
}
bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
@@ -1212,6 +1110,22 @@
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};
+ hwc_layer_1_t *fbLayer = &list->hwLayers[mCurrentFrame.layerCount];
+
+ /* Update only the region of FB needed for composition */
+ for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
+ if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dst = layer->displayFrame;
+ fbRect = getUnion(fbRect, dst);
+ }
+ }
+ return fbRect;
+}
+
bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
@@ -1229,7 +1143,9 @@
//Configure framebuffer first if applicable
if(mCurrentFrame.fbZ >= 0) {
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
+ hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
+ if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
+ {
ALOGD_IF(isDebug(), "%s configure framebuffer failed",
__FUNCTION__);
return false;
@@ -1295,66 +1211,6 @@
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
return false;
}
-
- double size = calcMDPBytesRead(ctx, list);
- if(!bandwidthCheck(ctx, size)) {
- ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
- return false;
- }
-
- return true;
-}
-
-double MDPComp::calcMDPBytesRead(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- double size = 0;
- const double GIG = 1000000000.0;
-
- //Skip for targets where no device tree value for bw is supplied
- if(sMaxBw <= 0.0) {
- return 0.0;
- }
-
- for (uint32_t i = 0; i < list->numHwLayers - 1; i++) {
- if(!mCurrentFrame.isFBComposed[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if (hnd) {
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t dst = layer->displayFrame;
- float bpp = ((float)hnd->size) / (hnd->width * hnd->height);
- size += (bpp * (crop.right - crop.left) *
- (crop.bottom - crop.top) *
- ctx->dpyAttr[mDpy].yres / (dst.bottom - dst.top)) /
- GIG;
- }
- }
- }
-
- if(mCurrentFrame.fbCount) {
- hwc_layer_1_t* layer = &list->hwLayers[list->numHwLayers - 1];
- int tempw, temph;
- size += (getBufferSizeAndDimensions(
- layer->displayFrame.right - layer->displayFrame.left,
- layer->displayFrame.bottom - layer->displayFrame.top,
- HAL_PIXEL_FORMAT_RGBA_8888,
- tempw, temph)) / GIG;
- }
-
- return size;
-}
-
-bool MDPComp::bandwidthCheck(hwc_context_t *ctx, const double& size) {
- //Skip for targets where no device tree value for bw is supplied
- if(sMaxBw <= 0.0) {
- return true;
- }
-
- double panelRefRate =
- 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
- if((size * panelRefRate) > (sMaxBw - sBwClaimed)) {
- return false;
- }
return true;
}
@@ -1438,13 +1294,6 @@
if(isFrameDoable(ctx)) {
generateROI(ctx, list);
- //Convert from kbps to gbps
- sMaxBw = mdpVersion.getHighBw() / 1000000.0;
- if (ctx->mExtDisplay->isConnected() ||
- ctx->mMDP.panel != MIPI_CMD_PANEL) {
- sMaxBw = mdpVersion.getLowBw() / 1000000.0;
- }
-
if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
setMDPCompLayerFlags(ctx, list);
} else {
@@ -1469,9 +1318,6 @@
mCachedFrame.cacheAll(list);
mCachedFrame.updateCounts(mCurrentFrame);
- double panelRefRate =
- 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
- sBwClaimed += calcMDPBytesRead(ctx, list) * panelRefRate;
return ret;
}
@@ -1619,9 +1465,10 @@
return true;
}
- /* reset Invalidator */
- if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
- idleInvalidator->handleUpdateEvent();
+ // Set the Handle timeout to true for MDP or MIXED composition.
+ if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
+ sHandleTimeout = true;
+ }
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -1865,9 +1712,10 @@
return true;
}
- /* reset Invalidator */
- if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
- idleInvalidator->handleUpdateEvent();
+ // Set the Handle timeout to true for MDP or MIXED composition.
+ if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
+ sHandleTimeout = true;
+ }
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -1980,5 +1828,183 @@
return true;
}
+
+//================MDPCompSrcSplit==============================================
+bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ MdpPipeInfoSplit& pipe_info, ePipeType /*type*/) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ pipe_info.lIndex = ovutils::OV_INVALID;
+ pipe_info.rIndex = ovutils::OV_INVALID;
+
+ //If 2 pipes are staged on a single stage of a mixer, then the left pipe
+ //should have a higher priority than the right one. Pipe priorities are
+ //starting with VG0, VG1 ... , RGB0 ..., DMA1
+ //TODO Currently we acquire VG pipes for left side and RGB/DMA for right to
+ //make sure pipe priorities are satisfied. A better way is to have priority
+ //as part of overlay object and acquire any 2 pipes. Assign the higher
+ //priority one to left side and lower to right side.
+
+ //1 pipe by default for a layer
+ pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_VG, Overlay::MIXER_DEFAULT);
+ if(pipe_info.lIndex == ovutils::OV_INVALID) {
+ if(isYuvBuffer(hnd)) {
+ return false;
+ }
+ pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_ANY,
+ Overlay::MIXER_DEFAULT);
+ if(pipe_info.lIndex == ovutils::OV_INVALID) {
+ return false;
+ }
+ }
+
+ //If layer's crop width or dest width > 2048, use 2 pipes
+ if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
+ (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+ ePipeType rightType = isYuvBuffer(hnd) ?
+ MDPCOMP_OV_VG : MDPCOMP_OV_ANY;
+ pipe_info.rIndex = getMdpPipe(ctx, rightType, Overlay::MIXER_DEFAULT);
+ if(pipe_info.rIndex == ovutils::OV_INVALID) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool MDPCompSrcSplit::allocLayerPipes(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+ if(mCurrentFrame.isFBComposed[index]) continue;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ int mdpIndex = mCurrentFrame.layerToMDP[index];
+ PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+ info.pipeInfo = new MdpPipeInfoSplit;
+ info.rot = NULL;
+ MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+
+ ePipeType type = MDPCOMP_OV_ANY;
+ if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
+ __FUNCTION__, (int) type);
+ return false;
+ }
+ }
+ return true;
+}
+
+int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& PipeLayerPair) {
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(!hnd) {
+ ALOGE("%s: layer handle is NULL", __FUNCTION__);
+ return -1;
+ }
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ MdpPipeInfoSplit& mdp_info =
+ *(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);
+
+ ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
+ "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+
+ // Handle R/B swap
+ if (layer->flags & HWC_FORMAT_RB_SWAP) {
+ if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+ whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+ else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+ whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+ }
+
+ eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+ setMdpFlags(layer, mdpFlagsL, 0, transform);
+ eMdpFlags mdpFlagsR = mdpFlagsL;
+
+ if(lDest != OV_INVALID && rDest != OV_INVALID) {
+ //Enable overfetch
+ setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+ }
+
+ if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ (*rot) = ctx->mRotMgr->getNext();
+ if((*rot) == NULL) return -1;
+ //Configure rotator for pre-rotation
+ if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+ ALOGE("%s: configRotator failed!", __FUNCTION__);
+ return -1;
+ }
+ ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+ whf.format = (*rot)->getDstFormat();
+ updateSource(orient, whf, crop);
+ rotFlags |= ROT_PREROTATED;
+ }
+
+ //If 2 pipes being used, divide layer into half, crop and dst
+ hwc_rect_t cropL = crop;
+ hwc_rect_t cropR = crop;
+ hwc_rect_t dstL = dst;
+ hwc_rect_t dstR = dst;
+ if(lDest != OV_INVALID && rDest != OV_INVALID) {
+ cropL.right = (crop.right + crop.left) / 2;
+ cropR.left = cropL.right;
+ sanitizeSourceCrop(cropL, cropR, hnd);
+
+ //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;
+ }
+
+ dstL.right = (dst.right + dst.left) / 2;
+ dstR.left = dstL.right;
+ }
+
+ //For the mdp, since either we are pre-rotating or MDP does flips
+ orient = OVERLAY_TRANSFORM_0;
+ transform = 0;
+
+ //configure left pipe
+ if(lDest != OV_INVALID) {
+ PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+
+ if(configMdp(ctx->mOverlay, pargL, orient,
+ cropL, dstL, metadata, lDest) < 0) {
+ ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ //configure right pipe
+ if(rDest != OV_INVALID) {
+ PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+ static_cast<eRotFlags>(rotFlags),
+ layer->planeAlpha,
+ (ovutils::eBlending) getBlending(layer->blending));
+ if(configMdp(ctx->mOverlay, pargR, orient,
+ cropR, dstR, metadata, rDest) < 0) {
+ ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
}; //namespace
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index f2a8eda..94199e3 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -52,7 +52,7 @@
/* Initialize MDP comp*/
static bool init(hwc_context_t *ctx);
static void resetIdleFallBack() { sIdleFallBack = false; }
- static void reset() { sBwClaimed = 0.0; };
+ static void reset() { sHandleTimeout = false; };
protected:
enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -158,16 +158,11 @@
bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* Partial MDP comp that uses caching to save power as primary goal */
bool cacheBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- /* Partial MDP comp that prefers GPU perf-wise. Since the GPU's
- * perf is proportional to the pixels it processes, we use the number of
- * pixels as a heuristic */
- bool loadBasedCompPreferGPU(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* Partial MDP comp that prefers MDP perf-wise. Since the MDP's perf is
- * proportional to the bandwidth, overlaps it sees, we use that as a
- * heuristic */
- bool loadBasedCompPreferMDP(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
+ /* Partial MDP comp that balances the load between MDP and GPU such that
+ * MDP is loaded to the max of its capacity. The lower z order layers are
+ * fed to MDP, whereas the upper ones to GPU, because the upper ones have
+ * lower number of pixels and can reduce GPU processing time */
+ bool loadBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* Checks if its worth doing load based partial comp */
bool isLoadBasedCompDoable(hwc_context_t *ctx);
/* checks for conditions where only video can be bypassed */
@@ -176,11 +171,6 @@
bool secureOnly);
/* checks for conditions where YUV layers cannot be bypassed */
bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
- /* calcs bytes read by MDP in gigs for a given frame */
- double calcMDPBytesRead(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- /* checks if the required bandwidth exceeds a certain max */
- bool bandwidthCheck(hwc_context_t *ctx, const double& size);
/* 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);
@@ -223,6 +213,8 @@
void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+ hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
int mDpy;
static bool sEnabled;
@@ -231,12 +223,9 @@
static bool sEnablePartialFrameUpdate;
static bool sDebugLogs;
static bool sIdleFallBack;
+ /* Handles the timeout event from kernel, if the value is set to true */
+ static bool sHandleTimeout;
static int sMaxPipesPerMixer;
- //Max bandwidth. Value is in GBPS. For ex: 2.3 means 2.3GBPS
- static double sMaxBw;
- //Tracks composition bandwidth claimed. Represented as the total
- //w*h*bpp*fps (gigabytes-per-second) going to MDP mixers.
- static double sBwClaimed;
static IdleInvalidator *idleInvalidator;
struct FrameInfo mCurrentFrame;
struct LayerCache mCachedFrame;
@@ -280,14 +269,15 @@
explicit MDPCompSplit(int dpy):MDPComp(dpy){};
virtual ~MDPCompSplit(){};
virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-private:
+
+protected:
struct MdpPipeInfoSplit : public MdpPipeInfo {
ovutils::eDest lIndex;
ovutils::eDest rIndex;
virtual ~MdpPipeInfoSplit() {};
};
- bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
MdpPipeInfoSplit& pipe_info, ePipeType type);
/* configure's overlay pipes for the frame */
@@ -298,6 +288,7 @@
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+private:
/* Increments mdpCount if 4k2k yuv layer split is enabled.
* updates framebuffer z order if fb lies above source-split layer */
virtual void adjustForSourceSplit(hwc_context_t *ctx,
@@ -308,5 +299,20 @@
PipeLayerPair& PipeLayerPair);
};
+class MDPCompSrcSplit : public MDPCompSplit {
+public:
+ explicit MDPCompSrcSplit(int dpy) : MDPCompSplit(dpy){};
+ virtual ~MDPCompSrcSplit(){};
+private:
+ virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+ MdpPipeInfoSplit& pipe_info, ePipeType type);
+
+ virtual bool allocLayerPipes(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+
+ virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ PipeLayerPair& pipeLayerPair);
+};
+
}; //namespace
#endif
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 8d039ba..b8b7740 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -490,7 +490,7 @@
// the position based on the new width and height
if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
isOrientationPortrait(ctx)) {
- hwc_rect_t r;
+ hwc_rect_t r = {0, 0, 0, 0};
//Calculate the position
xRatio = (outPos.x - xPos)/width;
// GetaspectRatio -- tricky to get the correct aspect ratio
@@ -781,6 +781,28 @@
}
}
+hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy) {
+ int dstWidth = ctx->dpyAttr[dpy].xres;
+ int dstHeight = ctx->dpyAttr[dpy].yres;
+ int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+ int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+ // default we assume viewframe as a full frame for primary display
+ hwc_rect outRect = {0, 0, dstWidth, dstHeight};
+ if(dpy) {
+ // swap srcWidth and srcHeight, if the device orientation is 90 or 270.
+ if(ctx->deviceOrientation & 0x1) {
+ swap(srcWidth, srcHeight);
+ }
+ // Get Aspect Ratio for external
+ getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
+ srcHeight, outRect);
+ }
+ ALOGD_IF(HWC_UTILS_DEBUG, "%s: view frame for dpy %d is [%d %d %d %d]",
+ __FUNCTION__, dpy, outRect.left, outRect.top,
+ outRect.right, outRect.bottom);
+ return outRect;
+}
+
void setListStats(hwc_context_t *ctx,
hwc_display_contents_1_t *list, int dpy) {
const int prevYuvCount = ctx->listStats[dpy].yuvCount;
@@ -804,13 +826,14 @@
trimList(ctx, list, dpy);
optimizeLayerRects(list);
+ // Calculate view frame of ext display from primary resolution
+ // and primary device orientation.
+ ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
+
for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
hwc_layer_1_t const* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- // Calculate view frame of each display from the layer displayframe
- ctx->mViewFrame[dpy] = getUnion(ctx->mViewFrame[dpy],
- layer->displayFrame);
#ifdef QCOM_BSP
if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
ctx->listStats[dpy].isDisplayAnimating = true;
@@ -1232,25 +1255,30 @@
for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
int rotFd = ctx->mRotMgr->getRotDevFd();
int rotReleaseFd = -1;
+ overlay::Rotator* currRot = ctx->mLayerRotMap[dpy]->getRot(i);
+ hwc_layer_1_t* currLayer = ctx->mLayerRotMap[dpy]->getLayer(i);
+ if((currRot == NULL) || (currLayer == NULL)) {
+ continue;
+ }
struct mdp_buf_sync rotData;
memset(&rotData, 0, sizeof(rotData));
rotData.acq_fen_fd =
- &ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
+ &currLayer->acquireFenceFd;
rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
- rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
+ rotData.session_id = currRot->getSessId();
int ret = 0;
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));
} else {
- close(ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd);
+ close(currLayer->acquireFenceFd);
//For MDP to wait on.
- ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd =
+ currLayer->acquireFenceFd =
dup(rotReleaseFd);
//A buffer is free to be used by producer as soon as its copied to
//rotator
- ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
+ currLayer->releaseFenceFd =
rotReleaseFd;
}
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 25d1c21..8a45029 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -211,6 +211,11 @@
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_1_t const* l);
+
+// Calculate viewframe for external/primary display from primary resolution and
+// primary device orientation
+hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy);
+
void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
void initContext(hwc_context_t *ctx);
@@ -377,16 +382,6 @@
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
}
-//Return true if buffer is for external display only with a BLOCK flag.
-static inline bool isExtBlock(const private_handle_t* hnd) {
- return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK));
-}
-
-//Return true if buffer is for external display only with a Close Caption flag.
-static inline bool isExtCC(const private_handle_t* hnd) {
- return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
-}
-
//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 28dc991..cc29d45 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -284,7 +284,7 @@
closeAcquireFds(list);
- if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
+ if (list && list->outbuf && (list->retireFenceFd < 0) ) {
// SF assumes HWC waits for the acquire fence and returns a new fence
// that signals when we're done. Since we don't wait, and also don't
// touch the buffer, we can just handle the acquire fence back to SF
diff --git a/liblight/lights.c b/liblight/lights.c
index 229777a..1aa0b58 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -84,7 +84,7 @@
if (fd >= 0) {
char buffer[20];
int bytes = sprintf(buffer, "%d\n", value);
- int amt = write(fd, buffer, bytes);
+ ssize_t amt = write(fd, buffer, (size_t)bytes);
close(fd);
return amt == -1 ? -errno : 0;
} else {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 6feffc4..265aa9f 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -45,7 +45,8 @@
Overlay::Overlay() {
- PipeBook::NUM_PIPES = qdutils::MDPVersion::getInstance().getTotalPipes();
+ int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
+ PipeBook::NUM_PIPES = (numPipes <= utils::OV_MAX)? numPipes : utils::OV_MAX;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
mPipeBook[i].init();
}
@@ -79,11 +80,11 @@
//fds
if(mPipeBook[i].valid()) {
char str[32];
- sprintf(str, "Unset=%s dpy=%d mix=%d; ",
+ snprintf(str, 32, "Unset=%s dpy=%d mix=%d; ",
PipeBook::getDestStr((eDest)i),
mPipeBook[i].mDisplay, mPipeBook[i].mMixer);
#if PIPE_DEBUG
- strncat(mDumpStr, str, strlen(str));
+ strlcat(mDumpStr, str, sizeof(mDumpStr));
#endif
}
mPipeBook[i].destroy();
@@ -146,7 +147,7 @@
snprintf(str, 32, "Set=%s dpy=%d mix=%d; ",
PipeBook::getDestStr(dest), dpy, mixer);
#if PIPE_DEBUG
- strncat(mDumpStr, str, strlen(str));
+ strlcat(mDumpStr, str, sizeof(mDumpStr));
#endif
}
} else {
@@ -396,19 +397,19 @@
void Overlay::getDump(char *buf, size_t len) {
int totalPipes = 0;
const char *str = "\nOverlay State\n\n";
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if(mPipeBook[i].valid()) {
mPipeBook[i].mPipe->getDump(buf, len);
char str[64] = {'\0'};
snprintf(str, 64, "Display=%d\n\n", mPipeBook[i].mDisplay);
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
totalPipes++;
}
}
char str_pipes[64] = {'\0'};
snprintf(str_pipes, 64, "Pipes=%d\n\n", totalPipes);
- strncat(buf, str_pipes, strlen(str_pipes));
+ strlcat(buf, str_pipes, len);
}
void Overlay::clear(int dpy) {
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index 3e549b1..38b0a92 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -156,7 +156,7 @@
mRotDataInfo.dst.memory_id = mem.getFD();
mRotDataInfo.dst.offset = 0;
- mMem.curr().m = mem;
+ mMem.mem = mem;
return true;
}
@@ -184,23 +184,27 @@
bool MdpRot::remap(uint32_t numbufs) {
// if current size changed, remap
uint32_t opBufSize = calcOutputBufSize();
- if(opBufSize == mMem.curr().size()) {
+ if(opBufSize == mMem.size()) {
ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
return true;
}
- ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
- OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
+ if(!mMem.close()) {
+ ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+ return false;
+ }
- // ++mMem will make curr to be prev, and prev will be curr
- ++mMem;
+ ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+
if(!open_i(numbufs, opBufSize)) {
ALOGE("%s Error could not open", __FUNCTION__);
return false;
}
+
for (uint32_t i = 0; i < numbufs; ++i) {
- mMem.curr().mRotOffset[i] = i * opBufSize;
+ mMem.mRotOffset[i] = i * opBufSize;
}
+
return true;
}
@@ -208,10 +212,8 @@
ovutils::memset0(mRotImgInfo);
ovutils::memset0(mLSRotImgInfo);
ovutils::memset0(mRotDataInfo);
- ovutils::memset0(mMem.curr().mRotOffset);
- ovutils::memset0(mMem.prev().mRotOffset);
- mMem.curr().mCurrOffset = 0;
- mMem.prev().mCurrOffset = 0;
+ ovutils::memset0(mMem.mRotOffset);
+ mMem.mCurrIndex = 0;
mOrientation = utils::OVERLAY_TRANSFORM_0;
}
@@ -220,30 +222,21 @@
mRotDataInfo.src.memory_id = fd;
mRotDataInfo.src.offset = offset;
- remap(RotMem::Mem::ROT_NUM_BUFS);
- OVASSERT(mMem.curr().m.numBufs(),
- "queueBuffer numbufs is 0");
+ if(false == remap(RotMem::ROT_NUM_BUFS)) {
+ ALOGE("%s Remap failed, not queueing", __FUNCTION__);
+ return false;
+ }
+
mRotDataInfo.dst.offset =
- mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
- mMem.curr().mCurrOffset =
- (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
+ 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();
return false;
}
-
- // if the prev mem is valid, we need to close
- if(mMem.prev().valid()) {
- // FIXME if no wait for vsync the above
- // play will return immediatly and might cause
- // tearing when prev.close is called.
- if(!mMem.prev().close()) {
- ALOGE("%s error in closing prev rot mem", __FUNCTION__);
- return false;
- }
- }
}
return true;
}
@@ -251,7 +244,7 @@
void MdpRot::dump() const {
ALOGE("== Dump MdpRot start ==");
mFd.dump();
- mMem.curr().m.dump();
+ mMem.mem.dump();
mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
ALOGE("== Dump MdpRot end ==");
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 083e507..ce9d9d5 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -134,30 +134,21 @@
mRotData.data.memory_id = fd;
mRotData.data.offset = offset;
- remap(RotMem::Mem::ROT_NUM_BUFS);
- OVASSERT(mMem.curr().m.numBufs(), "queueBuffer numbufs is 0");
+ if(false == remap(RotMem::ROT_NUM_BUFS)) {
+ ALOGE("%s Remap failed, not queuing", __FUNCTION__);
+ return false;
+ }
mRotData.dst_data.offset =
- mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
- mMem.curr().mCurrOffset =
- (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
+ 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();
return false;
}
-
- // if the prev mem is valid, we need to close
- if(mMem.prev().valid()) {
- // FIXME if no wait for vsync the above
- // play will return immediatly and might cause
- // tearing when prev.close is called.
- if(!mMem.prev().close()) {
- ALOGE("%s error in closing prev rot mem", __FUNCTION__);
- return false;
- }
- }
}
return true;
}
@@ -179,7 +170,7 @@
mRotData.dst_data.memory_id = mem.getFD();
mRotData.dst_data.offset = 0;
- mMem.curr().m = mem;
+ mMem.mem = mem;
return true;
}
@@ -187,23 +178,27 @@
// Calculate the size based on rotator's dst format, w and h.
uint32_t opBufSize = calcOutputBufSize();
// If current size changed, remap
- if(opBufSize == mMem.curr().size()) {
+ if(opBufSize == mMem.size()) {
ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
return true;
}
ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
- OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
- // ++mMem will make curr to be prev, and prev will be curr
- ++mMem;
+ if(!mMem.close()) {
+ ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+ return false;
+ }
+
if(!open_i(numbufs, opBufSize)) {
ALOGE("%s Error could not open", __FUNCTION__);
return false;
}
+
for (uint32_t i = 0; i < numbufs; ++i) {
- mMem.curr().mRotOffset[i] = i * opBufSize;
+ mMem.mRotOffset[i] = i * opBufSize;
}
+
return true;
}
@@ -234,17 +229,15 @@
ovutils::memset0(mRotData);
mRotData.data.memory_id = -1;
mRotInfo.id = MSMFB_NEW_REQUEST;
- ovutils::memset0(mMem.curr().mRotOffset);
- ovutils::memset0(mMem.prev().mRotOffset);
- mMem.curr().mCurrOffset = 0;
- mMem.prev().mCurrOffset = 0;
+ ovutils::memset0(mMem.mRotOffset);
+ mMem.mCurrIndex = 0;
mOrientation = utils::OVERLAY_TRANSFORM_0;
}
void MdssRot::dump() const {
ALOGE("== Dump MdssRot start ==");
mFd.dump();
- mMem.curr().m.dump();
+ mMem.mem.dump();
mdp_wrapper::dump("mRotInfo", mRotInfo);
mdp_wrapper::dump("mRotData", mRotData);
ALOGE("== Dump MdssRot end ==");
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index d912dc7..0e5b0ec 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -63,48 +63,45 @@
bool RotMem::close() {
bool ret = true;
- for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
- // skip current, and if valid, close
- if(m[i].valid()) {
- if(m[i].close() == false) {
- ALOGE("%s error in closing rot mem %d", __FUNCTION__, i);
- ret = false;
- }
+ if(valid()) {
+ if(mem.close() == false) {
+ ALOGE("%s error in closing rot mem", __FUNCTION__);
+ ret = false;
}
}
return ret;
}
-RotMem::Mem::Mem() : mCurrOffset(0) {
+RotMem::RotMem() : mCurrIndex(0) {
utils::memset0(mRotOffset);
for(int i = 0; i < ROT_NUM_BUFS; i++) {
mRelFence[i] = -1;
}
}
-RotMem::Mem::~Mem() {
+RotMem::~RotMem() {
for(int i = 0; i < ROT_NUM_BUFS; i++) {
::close(mRelFence[i]);
mRelFence[i] = -1;
}
}
-void RotMem::Mem::setReleaseFd(const int& fence) {
+void RotMem::setReleaseFd(const int& fence) {
int ret = 0;
- if(mRelFence[mCurrOffset] >= 0) {
+ if(mRelFence[mCurrIndex] >= 0) {
//Wait for previous usage of this buffer to be over.
//Can happen if rotation takes > vsync and a fast producer. i.e queue
//happens in subsequent vsyncs either because content is 60fps or
//because the producer is hasty sometimes.
- ret = sync_wait(mRelFence[mCurrOffset], 1000);
+ ret = sync_wait(mRelFence[mCurrIndex], 1000);
if(ret < 0) {
ALOGE("%s: sync_wait error!! error no = %d err str = %s",
__FUNCTION__, errno, strerror(errno));
}
- ::close(mRelFence[mCurrOffset]);
+ ::close(mRelFence[mCurrIndex]);
}
- mRelFence[mCurrOffset] = fence;
+ mRelFence[mCurrIndex] = fence;
}
//============RotMgr=========================
@@ -178,7 +175,7 @@
}
char str[4] = {'\0'};
snprintf(str, 4, "\n");
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
}
int RotMgr::getRotDevFd() {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 2bbfb91..be0c8bd 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -45,36 +45,21 @@
we don't need this RotMem wrapper. The inner class is sufficient.
*/
struct RotMem {
- // Max rotator memory allocations
- enum { MAX_ROT_MEM = 2};
-
- //Manages the rotator buffer offsets.
- struct Mem {
- Mem();
- ~Mem();
- bool valid() { return m.valid(); }
- bool close() { return m.close(); }
- uint32_t size() const { return m.bufSz(); }
- void setReleaseFd(const int& fence);
- // Max rotator buffers
- enum { ROT_NUM_BUFS = 2 };
- // rotator data info dst offset
- uint32_t mRotOffset[ROT_NUM_BUFS];
- int mRelFence[ROT_NUM_BUFS];
- // current offset slot from mRotOffset
- uint32_t mCurrOffset;
- OvMem m;
- };
-
- RotMem() : _curr(0) {}
- Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
- const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
- Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
- RotMem& operator++() { ++_curr; return *this; }
- void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
+ // Max rotator buffers
+ enum { ROT_NUM_BUFS = 2 };
+ RotMem();
+ ~RotMem();
bool close();
- uint32_t _curr;
- Mem m[MAX_ROT_MEM];
+ bool valid() { return mem.valid(); }
+ uint32_t size() const { return mem.bufSz(); }
+ void setReleaseFd(const int& fence);
+
+ // rotator data info dst offset
+ uint32_t mRotOffset[ROT_NUM_BUFS];
+ int mRelFence[ROT_NUM_BUFS];
+ // current slot being used
+ uint32_t mCurrIndex;
+ OvMem mem;
};
class Rotator
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 5cc4c03..ddba868 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -161,8 +161,7 @@
case HAL_PIXEL_FORMAT_RGBX_8888:
return MDP_RGBX_8888_TILE;
case HAL_PIXEL_FORMAT_RGB_565:
- // Currenty Driver doesnt support 565 tile format
- return MDP_RGB_565;
+ return MDP_RGB_565_TILE;
case HAL_PIXEL_FORMAT_BGRA_8888:
return MDP_BGRA_8888_TILE;
case HAL_PIXEL_FORMAT_BGRX_8888:
@@ -417,29 +416,29 @@
"V.Deci=%d\n",
prefix, ov.id, ov.z_order, ov.is_fg, ov.alpha,
ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
getDump(buf, len, "\tsrc", ov.src);
getDump(buf, len, "\tsrc_rect", ov.src_rect);
getDump(buf, len, "\tdst_rect", ov.dst_rect);
}
-void getDump(char *buf, size_t /*len*/, const char *prefix,
+void getDump(char *buf, size_t len, const char *prefix,
const msmfb_img& ov) {
char str_src[256] = {'\0'};
snprintf(str_src, 256,
"%s w=%d h=%d format=%d %s\n",
prefix, ov.width, ov.height, ov.format,
overlay::utils::getFormatString(ov.format));
- strncat(buf, str_src, strlen(str_src));
+ strlcat(buf, str_src, len);
}
-void getDump(char *buf, size_t /*len*/, const char *prefix,
+void getDump(char *buf, size_t len, const char *prefix,
const mdp_rect& ov) {
char str_rect[256] = {'\0'};
snprintf(str_rect, 256,
"%s x=%d y=%d w=%d h=%d\n",
prefix, ov.x, ov.y, ov.w, ov.h);
- strncat(buf, str_rect, strlen(str_rect));
+ strlcat(buf, str_rect, len);
}
void getDump(char *buf, size_t len, const char *prefix,
@@ -448,17 +447,17 @@
snprintf(str, 256,
"%s id=%d\n",
prefix, ov.id);
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
getDump(buf, len, "\tdata", ov.data);
}
-void getDump(char *buf, size_t /*len*/, const char *prefix,
+void getDump(char *buf, size_t len, const char *prefix,
const msmfb_data& ov) {
char str_data[256] = {'\0'};
snprintf(str_data, 256,
"%s offset=%d memid=%d id=%d flags=0x%x\n",
prefix, ov.offset, ov.memory_id, ov.id, ov.flags);
- strncat(buf, str_data, strlen(str_data));
+ strlcat(buf, str_data, len);
}
void getDump(char *buf, size_t len, const char *prefix,
@@ -467,7 +466,7 @@
snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n",
prefix, rot.session_id, rot.rotations, rot.enable,
rot.downscale_ratio);
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
getDump(buf, len, "\tsrc", rot.src);
getDump(buf, len, "\tdst", rot.dst);
getDump(buf, len, "\tsrc_rect", rot.src_rect);
@@ -479,7 +478,7 @@
snprintf(str, 256,
"%s sessid=%u\n",
prefix, rot.session_id);
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
getDump(buf, len, "\tsrc", rot.src);
getDump(buf, len, "\tdst", rot.dst);
}
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 24fba33..c0066f3 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -424,7 +424,7 @@
const char* getFormatString(int format);
template <class T>
-inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); }
+inline void memset0(T& t) { ::memset(&t, 0, sizeof(t)); }
template <class T> inline void swap ( T& a, T& b )
{
@@ -555,6 +555,7 @@
formats[MDP_XRGB_8888_TILE] = STR(MDP_XRGB_8888_TILE);
formats[MDP_XBGR_8888_TILE] = STR(MDP_XBGR_8888_TILE);
formats[MDP_BGRX_8888_TILE] = STR(MDP_BGRX_8888_TILE);
+ formats[MDP_RGB_565_TILE] = STR(MDP_RGB_565_TILE);
formats[MDP_IMGTYPE_LIMIT] = STR(MDP_IMGTYPE_LIMIT);
if(format < 0 || format >= MDP_IMGTYPE_LIMIT) {
@@ -816,7 +817,7 @@
inline void OvFD::setPath(const char* const dev)
{
- ::strncpy(mPath, dev, utils::MAX_PATH_LEN);
+ ::strlcpy(mPath, dev, sizeof(mPath));
}
inline bool OvFD::close()
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index fdead74..08af00f 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -261,7 +261,7 @@
utils::getDump(buf, len, "WBData", sWb->mFbData);
char str[4] = {'\0'};
snprintf(str, 4, "\n");
- strncat(buf, str, strlen(str));
+ strlcat(buf, str, len);
return true;
}
return false;
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index 3d07c4f..a2b706c 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -43,14 +43,14 @@
int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
hwc_rect_t &clearWormholeRect, LayerProp *layerProp) {
- uint32_t last = list->numHwLayers - 1;
+ size_t last = list->numHwLayers - 1;
hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
Region wormholeRegion(fbFrameRect);
if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
wormholeRegion.set(0,0);
- for(uint32_t i = 0 ; i < last; i++) {
+ for(size_t i = 0 ; i < last; i++) {
if((list->hwLayers[i].blending == HWC_BLENDING_NONE) ||
!(layerProp[i].mFlags & HWC_COPYBIT) ||
(list->hwLayers[i].flags & HWC_SKIP_HWC_COMPOSITION))
@@ -61,7 +61,7 @@
wormholeRegion.set(tmpRect);
}
}else{
- for (uint32_t i = 0 ; i < last; i++) {
+ for (size_t i = 0 ; i < last; i++) {
// need to take care only in per pixel blending.
// Restrict calculation only for copybit layers.
if((list->hwLayers[i].blending != HWC_BLENDING_NONE) ||
diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp
index b53f1a3..d30375e 100644
--- a/libqdutils/idle_invalidator.cpp
+++ b/libqdutils/idle_invalidator.cpp
@@ -29,91 +29,99 @@
#include "idle_invalidator.h"
#include <unistd.h>
+#include <poll.h>
+#include <string.h>
+#include <fcntl.h>
#define II_DEBUG 0
+#define IDLE_NOTIFY_PATH "/sys/devices/virtual/graphics/fb0/idle_notify"
+#define IDLE_TIME_PATH "/sys/devices/virtual/graphics/fb0/idle_time"
-static const char *threadName = "Invalidator";
+
+static const char *threadName = "IdleInvalidator";
InvalidatorHandler IdleInvalidator::mHandler = NULL;
android::sp<IdleInvalidator> IdleInvalidator::sInstance(0);
IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0),
- mSleepAgain(false), mSleepTime(0) {
- ALOGD_IF(II_DEBUG, "%s", __func__);
- }
+ mTimeoutEventFd(-1) {
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+}
int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data,
- unsigned int idleSleepTime) {
- ALOGD_IF(II_DEBUG, "%s", __func__);
-
- Locker::Autolock _l(mLock);
- /* store registered handler */
+ unsigned int idleSleepTime) {
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s idleSleepTime %d",
+ __FUNCTION__, idleSleepTime);
mHandler = reg_handler;
mHwcContext = user_data;
- mSleepTime = idleSleepTime; //Time in millis
+
+ // Open a sysfs node to receive the timeout notification from driver.
+ mTimeoutEventFd = open(IDLE_NOTIFY_PATH, O_RDONLY);
+ if (mTimeoutEventFd < 0) {
+ ALOGE ("%s:not able to open %s node %s",
+ __FUNCTION__, IDLE_NOTIFY_PATH, strerror(errno));
+ return -1;
+ }
+
+ // Open a sysfs node to send the timeout value to driver.
+ int fd = open(IDLE_TIME_PATH, O_WRONLY);
+ if (fd < 0) {
+ ALOGE ("%s:not able to open %s node %s",
+ __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+ close(mTimeoutEventFd);
+ mTimeoutEventFd = -1;
+ return -1;
+ }
+ char strSleepTime[64];
+ snprintf(strSleepTime, sizeof(strSleepTime), "%d", idleSleepTime);
+ // Notify driver about the timeout value
+ ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0);
+ if(len < -1) {
+ ALOGE ("%s:not able to write into %s node %s",
+ __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+ close(mTimeoutEventFd);
+ mTimeoutEventFd = -1;
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ //Triggers the threadLoop to run, if not already running.
+ run(threadName, android::PRIORITY_LOWEST);
return 0;
}
bool IdleInvalidator::threadLoop() {
- struct timeval lastUpdateTime;
- ALOGD_IF(II_DEBUG, "%s", __func__);
-
- {
- //If we are here, update(s) happened, i.e mSleepAgain is set
- Locker::Autolock _l(mLock);
- mSleepAgain = false;
- lastUpdateTime = mLastUpdateTime;
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+ struct pollfd pFd;
+ pFd.fd = mTimeoutEventFd;
+ if (pFd.fd >= 0)
+ pFd.events = POLLPRI | POLLERR;
+ // Poll for an timeout event from driver
+ int err = poll(&pFd, 1, -1);
+ if(err > 0) {
+ if (pFd.revents & POLLPRI) {
+ char data[64];
+ // Consume the node by reading it
+ ssize_t len = pread(pFd.fd, data, 64, 0);
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zu",
+ __FUNCTION__, len);
+ mHandler((void*)mHwcContext);
+ }
}
-
- struct timeval currentTime;
- gettimeofday(¤tTime, NULL);
- int timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
- 1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
- int sleepDurationUs = mSleepTime * 1000 - timeSinceUpdateUs;
-
- //Sleep only if the duration required is > 1ms, otherwise its not worth it.
- if(sleepDurationUs > 1000) {
- usleep(sleepDurationUs);
- ALOGD_IF(II_DEBUG, "Slept for %d ms", sleepDurationUs / 1000);
- }
-
- Locker::Autolock _l(mLock);
- //If an update happened while we were asleep, sleep again
- if(mSleepAgain) {
- //We need to sleep again!
- mSleepAgain = false;
- return true;
- }
-
-#if II_DEBUG
- gettimeofday(¤tTime, NULL);
- timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
- 1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
- ALOGD("Idle refresh after %dms", timeSinceUpdateUs / 1000);
-#endif
-
- mHandler((void*)mHwcContext);
- return false;
+ return true;
}
int IdleInvalidator::readyToRun() {
- ALOGD_IF(II_DEBUG, "%s", __func__);
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
return 0; /*NO_ERROR*/
}
void IdleInvalidator::onFirstRef() {
- ALOGD_IF(II_DEBUG, "%s", __func__);
-}
-
-void IdleInvalidator::handleUpdateEvent() {
- Locker::Autolock _l(mLock);
- gettimeofday(&mLastUpdateTime, NULL);
- mSleepAgain = true;
- //Triggers the threadLoop to run, if not already running.
- run(threadName, android::PRIORITY_AUDIO);
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
}
IdleInvalidator *IdleInvalidator::getInstance() {
- ALOGD_IF(II_DEBUG, "%s", __func__);
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
if(sInstance.get() == NULL)
sInstance = new IdleInvalidator();
return sInstance.get();
diff --git a/libqdutils/idle_invalidator.h b/libqdutils/idle_invalidator.h
index f41c15e..a881c4b 100644
--- a/libqdutils/idle_invalidator.h
+++ b/libqdutils/idle_invalidator.h
@@ -38,19 +38,15 @@
class IdleInvalidator : public android::Thread {
void *mHwcContext;
- struct timeval mLastUpdateTime;
- bool mSleepAgain;
- unsigned int mSleepTime;
+ int mTimeoutEventFd;
static InvalidatorHandler mHandler;
static android::sp<IdleInvalidator> sInstance;
- mutable Locker mLock;
public:
IdleInvalidator();
/* init timer obj */
int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
idleSleepTime);
- void handleUpdateEvent();
/*Overrides*/
virtual bool threadLoop();
virtual int readyToRun();
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 9e36980..ed21b2c 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -70,6 +70,7 @@
mPanelType = NO_PANEL;
mLowBw = 0;
mHighBw = 0;
+ mSourceSplit = false;
if(!updatePanelInfo()) {
ALOGE("Unable to read Primary Panel Information");
@@ -149,7 +150,7 @@
// and parses and updates information accordingly.
bool MDPVersion::updateSysFsInfo() {
FILE *sysfsFd;
- size_t len = 0;
+ size_t len = PAGE_SIZE;
ssize_t read;
char *line = NULL;
char sysfsPath[255];
@@ -172,6 +173,7 @@
__FUNCTION__, sysfsPath);
return false;
} else {
+ line = (char *) malloc(len);
while((read = getline(&line, &len, sysfsFd)) != -1) {
int index=0;
char *tokens[10];
@@ -183,13 +185,13 @@
mMdpRev = atoi(tokens[1]);
}
else if(!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
- mRGBPipes = atoi(tokens[1]);
+ mRGBPipes = (uint8_t)atoi(tokens[1]);
}
else if(!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
- mVGPipes = atoi(tokens[1]);
+ mVGPipes = (uint8_t)atoi(tokens[1]);
}
else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
- mDMAPipes = atoi(tokens[1]);
+ mDMAPipes = (uint8_t)atoi(tokens[1]);
}
else if(!strncmp(tokens[0], "max_downscale_ratio",
strlen("max_downscale_ratio"))) {
@@ -217,13 +219,15 @@
strlen("tile_format"))) {
if(enableMacroTile)
mMacroTileEnabled = true;
+ } else if(!strncmp(tokens[i], "src_split",
+ strlen("src_split"))) {
+ mSourceSplit = true;
}
}
}
}
- free(line);
- line = NULL;
}
+ free(line);
fclose(sysfsFd);
}
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
@@ -246,6 +250,7 @@
if(fp){
//Format "left right" space as delimiter
if(fread(split, sizeof(char), 64, fp)) {
+ split[sizeof(split) - 1] = '\0';
mSplit.mLeft = atoi(split);
ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
char *rght = strpbrk(split, " ");
@@ -286,6 +291,10 @@
return mMacroTileEnabled;
}
+bool MDPVersion::isSrcSplit() const {
+ return mSourceSplit;
+}
+
bool MDPVersion::is8x26() {
return (mMdpRev >= MDSS_MDP_HW_REV_101 and
mMdpRev < MDSS_MDP_HW_REV_102);
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 853b9f5..5e36291 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -100,7 +100,9 @@
int getMDPVersion() {return mMDPVersion;}
char getPanelType() {return mPanelType;}
bool hasOverlay() {return mHasOverlay;}
- uint8_t getTotalPipes() { return (mRGBPipes + mVGPipes + mDMAPipes);}
+ uint8_t getTotalPipes() {
+ return (uint8_t)(mRGBPipes + mVGPipes + mDMAPipes);
+ }
uint8_t getRGBPipes() { return mRGBPipes; }
uint8_t getVGPipes() { return mVGPipes; }
uint8_t getDMAPipes() { return mDMAPipes; }
@@ -113,6 +115,7 @@
int getRightSplit() { return mSplit.right(); }
unsigned long getLowBw() { return mLowBw; }
unsigned long getHighBw() { return mHighBw; }
+ bool isSrcSplit() const;
bool is8x26();
bool is8x74v2();
bool is8084();
@@ -139,6 +142,7 @@
Split mSplit;
unsigned long mLowBw; //kbps
unsigned long mHighBw; //kbps
+ bool mSourceSplit;
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/libqdutils/profiler.cpp b/libqdutils/profiler.cpp
index 997c839..56bb2c6 100644
--- a/libqdutils/profiler.cpp
+++ b/libqdutils/profiler.cpp
@@ -90,7 +90,7 @@
debug_fps_metadata.ignorethresh_us = atoi(prop);
debug_fps_metadata.framearrival_steps =
- (debug_fps_metadata.ignorethresh_us / 16666);
+ (unsigned int)(debug_fps_metadata.ignorethresh_us / 16666);
if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
@@ -106,7 +106,7 @@
debug_fps_metadata.curr_frame = 0;
- ALOGD("period: %d", debug_fps_metadata.period);
+ ALOGD("period: %u", debug_fps_metadata.period);
ALOGD("ignorethresh_us: %"PRId64, debug_fps_metadata.ignorethresh_us);
}
@@ -165,7 +165,8 @@
debug_fps_metadata.curr_frame++;
if (debug_fps_level > 1) {
- unsigned int currstep = (diff + debug_fps_metadata.margin_us) / 16666;
+ unsigned int currstep =
+ (unsigned int)(diff + debug_fps_metadata.margin_us) / 16666;
if (currstep < debug_fps_metadata.framearrival_steps) {
debug_fps_metadata.accum_framearrivals[currstep-1]++;
@@ -178,14 +179,15 @@
nsecs_t sum = 0;
for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
sum += debug_fps_metadata.framearrivals[i];
- print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
+ print_fps(float(float(debug_fps_metadata.period * 1000000) /
+ (float)sum));
}
}
else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
- debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
+ debug_fps_metadata.time_elapsed += (float)((float)diff/1000.0);
if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
- float fps = (1000.0 * debug_fps_metadata.curr_frame)/
- (float)debug_fps_metadata.time_elapsed;
+ float fps = float(1000.0 * debug_fps_metadata.curr_frame/
+ debug_fps_metadata.time_elapsed);
print_fps(fps);
}
}
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index ecbf873..b736478 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -103,12 +103,15 @@
}
}
break;
+ case UPDATE_COLOR_SPACE:
+ data->colorSpace = *((ColorSpace_t *)param);
+ break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
}
if(munmap(base, size))
- ALOGE("%s: failed to unmap ptr 0x%"PRIdPTR", err %d", __func__, (intptr_t)base,
+ ALOGE("%s: failed to unmap ptr %p, err %d", __func__, (void*)base,
errno);
return 0;
}
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 4b6e678..3a0e615 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,6 +30,10 @@
#ifndef _QDMETADATA_H
#define _QDMETADATA_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define MAX_IGC_LUT_ENTRIES 256
#define MAX_VFM_DATA_SIZE 64 //bytes per data buffer
#define MAX_VFM_DATA_COUNT 16 //number of data buffers
@@ -45,6 +49,12 @@
return indx;
}
+enum ColorSpace_t{
+ ITU_R_601,
+ ITU_R_601_FR,
+ ITU_R_709,
+};
+
struct HSICData_t {
int32_t hue;
float saturation;
@@ -78,18 +88,19 @@
struct MetaData_t {
int32_t operation;
int32_t interlaced;
- BufferDim_t bufferDim;
- HSICData_t hsicData;
+ struct BufferDim_t bufferDim;
+ struct HSICData_t hsicData;
int32_t sharpness;
int32_t video_interface;
- IGCData_t igcData;
- Sharp2Data_t Sharp2Data;
+ struct IGCData_t igcData;
+ struct Sharp2Data_t Sharp2Data;
int64_t timestamp;
int32_t vfmDataBitMap;
- VfmData_t vfmData[MAX_VFM_DATA_COUNT];
+ struct VfmData_t vfmData[MAX_VFM_DATA_COUNT];
+ enum ColorSpace_t colorSpace;
};
-typedef enum {
+enum DispParamType {
PP_PARAM_HSIC = 0x0001,
PP_PARAM_SHARPNESS = 0x0002,
PP_PARAM_INTERLACED = 0x0004,
@@ -99,9 +110,16 @@
PP_PARAM_TIMESTAMP = 0x0040,
UPDATE_BUFFER_GEOMETRY = 0x0080,
PP_PARAM_VFM_DATA = 0x0100,
-} DispParamType;
+ UPDATE_COLOR_SPACE = 0x0200,
+};
-int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);
+struct private_handle_t;
+int setMetaData(struct private_handle_t *handle, enum DispParamType paramType,
+ void *param);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* _QDMETADATA_H */
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 0698b33..c27167f 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -87,7 +87,7 @@
return 0;
}
- size = read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
+ size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
close(edidFile);
return size;
}
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index 096444f..eee22f0 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -123,10 +123,12 @@
snprintf(buf, size, "/proc/%d/cmdline", pid);
fd = open(buf, O_RDONLY);
if (fd < 0) {
- strcpy(buf, "Unknown");
+ strlcpy(buf, "Unknown", size);
} else {
- int len = read(fd, buf, size - 1);
- buf[len] = 0;
+ ssize_t len = read(fd, buf, size - 1);
+ if (len >= 0)
+ buf[len] = 0;
+
close(fd);
}
}
diff --git a/libvirtual/virtual.cpp b/libvirtual/virtual.cpp
index 342044c..795d8a1 100644
--- a/libvirtual/virtual.cpp
+++ b/libvirtual/virtual.cpp
@@ -191,7 +191,7 @@
getFbForDpy(HWC_DISPLAY_VIRTUAL);
char strDevPath[MAX_SYSFS_FILE_PATH];
- sprintf(strDevPath,"/dev/graphics/fb%d", fbNum);
+ snprintf(strDevPath,sizeof(strDevPath), "/dev/graphics/fb%d", fbNum);
mFd = open(strDevPath, O_RDWR);
if(mFd < 0) {