Merge "hwc: Derive view frame for external display."
diff --git a/common.mk b/common.mk
index 47c455f..ae4ea61 100644
--- a/common.mk
+++ b/common.mk
@@ -36,8 +36,7 @@
common_flags += -DMDSS_TARGET
endif
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
- #XXX: Replace with check from MDP when available
+ifeq ($(call is-board-platform-in-list, mpq8092), true)
common_flags += -DVPU_TARGET
endif
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index d905e0d..1268b0f 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -175,6 +175,7 @@
int 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];
@@ -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);
}
@@ -493,7 +494,6 @@
void ExternalDisplay::setResolution(int ID)
{
- struct fb_var_screeninfo info;
int ret = 0;
ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
if(ret < 0) {
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index dc5f6ae..723267b 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -46,6 +46,9 @@
#define VENUS_BUFFER_SIZE(args...) 0
#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;
@@ -123,10 +126,12 @@
void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
int tile_enabled, int& aligned_w, int& aligned_h)
{
- aligned_w = ALIGN(width, 32);
- aligned_h = ALIGN(height, 32);
+ aligned_w = width;
+ aligned_h = height;
// Currently surface padding is only computed for RGB* surfaces.
if (format <= HAL_PIXEL_FORMAT_sRGB_X_8888) {
+ aligned_w = ALIGN(width, 32);
+ aligned_h = ALIGN(height, 32);
// Don't add any additional padding if debug.gralloc.map_fb_memory
// is enabled
char property[PROPERTY_VALUE_MAX];
@@ -192,12 +197,83 @@
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+ aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
break;
case HAL_PIXEL_FORMAT_BLOB:
- aligned_w = width;
break;
case HAL_PIXEL_FORMAT_NV21_ZSL:
aligned_w = ALIGN(width, 64);
+ aligned_h = ALIGN(height, 64);
+ 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);
break;
default: break;
}
@@ -335,9 +411,9 @@
}
// helper function
-size_t getSize(int format, int width, int height, int alignedw, int alignedh)
-{
- size_t size;
+size_t getSize(int format, int width, int height, const int alignedw,
+ const int alignedh) {
+ size_t size = 0;
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
@@ -370,16 +446,14 @@
case HAL_PIXEL_FORMAT_YV12:
if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
ALOGE("w or h is odd for the YV12 format");
- return -EINVAL;
+ return 0;
}
- alignedh = height;
size = alignedw*alignedh +
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
size = ALIGN(size, 4096);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- alignedh = height;
size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2 + 1, 4096);
break;
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
@@ -388,33 +462,58 @@
case HAL_PIXEL_FORMAT_YCrCb_422_I:
if(width & 1) {
ALOGE("width is odd for the YUV422_SP format");
- return -EINVAL;
+ return 0;
}
- alignedh = height;
size = ALIGN(alignedw * alignedh * 2, 4096);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
- alignedh = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
break;
case HAL_PIXEL_FORMAT_BLOB:
if(height != 1) {
ALOGE("%s: Buffers with format HAL_PIXEL_FORMAT_BLOB \
must have height==1 ", __FUNCTION__);
- return -EINVAL;
+ return 0;
}
- alignedh = height;
- alignedw = width;
size = width;
break;
case HAL_PIXEL_FORMAT_NV21_ZSL:
- alignedh = ALIGN(height, 64);
size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2, 4096);
break;
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+ break;
default:
ALOGE("unrecognized pixel format: 0x%x", format);
- return -EINVAL;
+ return 0;
}
return size;
}
@@ -467,9 +566,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 da179f9..bb7060b 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -282,13 +282,9 @@
grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
- }
-
- if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
- (usage & GRALLOC_USAGE_HW_COMPOSER )) {
- //XXX: If we still haven't set a format, default to
- //RGBA8888
- grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+ //XXX: If we still haven't set a format, default to RGBA8888
+ grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
}
getGrallocInformationFromFormat(grallocFormat, &bufferType);
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 66a67d3..c56eca9 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -117,6 +117,36 @@
//v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
//format reduces the memory access bandwidth
HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED = 0x43574259,
+
+ //Khronos ASTC formats
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC,
+ HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC,
+ HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD,
};
/* possible formats for 3D content*/
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 72e064e..9749c69 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -25,10 +25,8 @@
hwc_dump_layers.cpp \
hwc_ad.cpp \
hwc_virtual.cpp
-
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
+ifeq ($(call is-board-platform-in-list, mpq8092), true)
LOCAL_SRC_FILES += hwc_vpuclient.cpp
endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index dcad00b..1de864a 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -105,17 +105,40 @@
//Helper
static void reset(hwc_context_t *ctx, int numDisplays,
hwc_display_contents_1_t** displays) {
- for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+
+ ctx->numActiveDisplays = 0;
+ ctx->isPaddingRound = false;
+
+ for(int i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t *list = displays[i];
// XXX:SurfaceFlinger no longer guarantees that this
// value is reset on every prepare. However, for the layer
// cache we need to reset it.
// We can probably rethink that later on
- if (LIKELY(list && list->numHwLayers > 1)) {
+ if (LIKELY(list && list->numHwLayers > 0)) {
for(uint32_t j = 0; j < list->numHwLayers; j++) {
if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
}
+
+ /* For display devices like SSD and screenrecord, we cannot
+ * rely on isActive and connected attributes of dpyAttr to
+ * determine if the displaydevice is active. Hence in case if
+ * the layer-list is non-null and numHwLayers > 0, we assume
+ * the display device to be active.
+ */
+ ctx->numActiveDisplays += 1;
+
+ if((ctx->mPrevHwLayerCount[i] == 1) and (list->numHwLayers > 1)) {
+ /* If the previous cycle for dpy 'i' has 0 AppLayers and the
+ * current cycle has atleast 1 AppLayer, padding round needs
+ * to be invoked on current cycle to free up the resources.
+ */
+ ctx->isPaddingRound = true;
+ }
+ ctx->mPrevHwLayerCount[i] = list->numHwLayers;
+ } else {
+ ctx->mPrevHwLayerCount[i] = 0;
}
if(ctx->mFBUpdate[i])
@@ -132,22 +155,65 @@
ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
}
+bool isEqual(float f1, float f2) {
+ return ((int)(f1*100) == (int)(f2*100)) ? true : false;
+}
+
+static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
+ hwc_display_contents_1_t *list) {
+ float origXres = ctx->dpyAttr[dpy].xres_orig;
+ float origYres = ctx->dpyAttr[dpy].yres_orig;
+ float fakeXres = ctx->dpyAttr[dpy].xres;
+ float fakeYres = ctx->dpyAttr[dpy].yres;
+ float xresRatio = origXres / fakeXres;
+ float yresRatio = origYres / fakeYres;
+ for (size_t i = 0; i < list->numHwLayers; i++) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ hwc_rect_t& displayFrame = layer->displayFrame;
+ hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+ float layerWidth = displayFrame.right - displayFrame.left;
+ float layerHeight = displayFrame.bottom - displayFrame.top;
+ float sourceWidth = sourceCrop.right - sourceCrop.left;
+ float sourceHeight = sourceCrop.bottom - sourceCrop.top;
+
+ if (isEqual(layerWidth / sourceWidth, xresRatio) &&
+ isEqual(layerHeight / sourceHeight, yresRatio))
+ break;
+
+ displayFrame.left = xresRatio * displayFrame.left;
+ displayFrame.top = yresRatio * displayFrame.top;
+ displayFrame.right = displayFrame.left + layerWidth * xresRatio;
+ displayFrame.bottom = displayFrame.top + layerHeight * yresRatio;
+ }
+}
+
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) {
ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY;
+ bool fbComp = false;
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive) {
+
+ if (ctx->dpyAttr[dpy].customFBSize)
+ scaleDisplayFrame(ctx, dpy, list);
+
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
setListStats(ctx, list, dpy);
+
+ if (ctx->mVPUClient == NULL)
+ fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
#ifdef VPU_TARGET
- ctx->mVPUClient->prepare(ctx, list);
+ else
+ fbComp = (ctx->mVPUClient->prepare(ctx, dpy, list) < 0);
#endif
- if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+
+ if (fbComp) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+ ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
}
+
if (ctx->mMDP.version < qdutils::MDP_V4_0) {
if(ctx->mCopyBit[dpy])
ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
@@ -171,7 +237,7 @@
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+ ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
}
} else {
/* External Display is in Pause state.
@@ -206,7 +272,7 @@
ctx->mRotMgr->configBegin();
overlay::Writeback::configBegin();
- for (int32_t i = numDisplays; i >= 0; i--) {
+ for (int32_t i = (numDisplays-1); i >= 0; i--) {
hwc_display_contents_1_t *list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
@@ -287,7 +353,11 @@
ctx->mOverlay->configBegin();
ctx->mOverlay->configDone();
ctx->mRotMgr->clear();
- overlay::Writeback::clear();
+ // If VDS is connected, do not clear WB object as it
+ // will end up detaching IOMMU. This is required
+ // to send black frame to WFD sink on power suspend.
+ // Note: With this change, we keep the WriteBack object
+ // alive on power suspend for AD use case.
}
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
@@ -414,6 +484,9 @@
case HWC_COLOR_FILL:
value[0] = 1;
break;
+ case HWC_MAX_WRITEBACK_WIDTH:
+ value[0] = qdutils::MAX_DISPLAY_DIM;
+ break;
default:
return -EINVAL;
}
@@ -440,13 +513,15 @@
if(ctx->mHwcDebug[dpy])
ctx->mHwcDebug[dpy]->dumpLayers(list);
- if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+ if (ctx->mVPUClient != NULL) {
+#ifdef VPU_TARGET
+ ctx->mVPUClient->predraw(ctx, dpy, list);
+#endif
+ }
+ else if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1;
}
-#ifdef VPU_TARGET
- ctx->mVPUClient->draw(ctx, list);
-#endif
//TODO We dont check for SKIP flag on this layer because we need PAN
//always. Last layer is always FB
@@ -467,6 +542,11 @@
ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
+
+#ifdef VPU_TARGET
+ if (ctx->mVPUClient != NULL)
+ ctx->mVPUClient->draw(ctx, dpy, list);
+#endif
}
closeAcquireFds(list);
@@ -538,7 +618,7 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- for (uint32_t i = 0; i <= numDisplays; i++) {
+ for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
@@ -599,7 +679,7 @@
}
int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
- uint32_t config, const uint32_t* attributes, int32_t* values) {
+ uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
disp = getDpyforExternalDisplay(ctx, disp);
@@ -697,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_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 929ccc4..236093b 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-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
@@ -249,6 +249,14 @@
adWrite(on);
}
}
+
+ if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
+ mWbFd)) {
+ ALOGE("%s: Failed to validate and set overlay for dpy %d"
+ ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+ return false;
+ }
+
return true;
}
@@ -270,12 +278,12 @@
return true;
}
-int AssertiveDisplay::getDstFd(hwc_context_t *ctx) const {
+int AssertiveDisplay::getDstFd() const {
overlay::Writeback *wb = overlay::Writeback::getInstance();
return wb->getDstFd();
}
-uint32_t AssertiveDisplay::getDstOffset(hwc_context_t *ctx) const {
+uint32_t AssertiveDisplay::getDstOffset() const {
overlay::Writeback *wb = overlay::Writeback::getInstance();
return wb->getOffset();
}
diff --git a/libhwcomposer/hwc_ad.h b/libhwcomposer/hwc_ad.h
index c745b15..3bfde17 100644
--- a/libhwcomposer/hwc_ad.h
+++ b/libhwcomposer/hwc_ad.h
@@ -51,8 +51,8 @@
}
bool isDoable() const { return mDoable; }
bool isModeOn() const { return (mWbFd >= 0); }
- int getDstFd(hwc_context_t *ctx) const;
- uint32_t getDstOffset(hwc_context_t *ctx) const;
+ int getDstFd() const;
+ uint32_t getDstOffset() const;
private:
//State of feature turned on and off
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 86cad8f..d47853a 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution.
*
@@ -162,8 +162,6 @@
bool useCopybitForYUV = canUseCopybitForYUV(ctx);
bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
LayerProp *layerProp = ctx->layerProp[dpy];
- size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
- hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
// Following are MDP3 limitations for which we
// need to fallback to GPU composition:
@@ -326,7 +324,7 @@
list->hwLayers[i].acquireFenceFd = -1;
}
retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
- renderBuffer, dpy, !i);
+ renderBuffer, !i);
copybitLayerCount++;
if(retVal < 0) {
ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
@@ -347,7 +345,7 @@
}
int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, int dpy, bool isFG)
+ private_handle_t *renderBuffer, bool isFG)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
int err = 0, acquireFd;
@@ -519,7 +517,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_copybit.h b/libhwcomposer/hwc_copybit.h
index 4d8123c..f7be644 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -54,7 +54,7 @@
struct copybit_device_t *mEngine;
// Helper functions for copybit composition
int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- private_handle_t *renderBuffer, int dpy, bool isFG);
+ private_handle_t *renderBuffer, bool isFG);
int fillColorUsingCopybit(hwc_layer_1_t *layer,
private_handle_t *renderBuffer);
bool canUseCopybitForYUV (hwc_context_t *ctx);
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index aeaac08..bebcc18 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -38,6 +38,9 @@
#include <comptype.h>
#include <SkBitmap.h>
#include <SkImageEncoder.h>
+#ifdef STDC_FORMAT_MACROS
+#include <inttypes.h>
+#endif
namespace qhwc {
@@ -58,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"))) {
@@ -110,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)",
@@ -119,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,
@@ -140,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)",
@@ -149,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,
@@ -274,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);
}
@@ -308,7 +314,8 @@
char dumpFilename[PATH_MAX];
SkBitmap *tempSkBmp = new SkBitmap();
SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
- sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%s.png", mDumpDirPng,
+ snprintf(dumpFilename, sizeof(dumpFilename),
+ "%s/sfdump%03d.layer%d.%s.png", mDumpDirPng,
mDumpCntrPng, layerIndex, mDisplayName);
switch (hnd->format) {
@@ -344,7 +351,8 @@
if (needDumpRaw && hnd->base) {
char dumpFilename[PATH_MAX];
bool bResult = false;
- sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%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);
@@ -366,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 6bc2e75..78a05e9 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -45,7 +45,7 @@
}
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,
@@ -60,6 +60,12 @@
mRot = NULL;
}
+bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
+ hwc_display_contents_1 *list, int fbZorder) {
+ return prepare(ctx, list, fbZorder) &&
+ ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
+}
+
//================= Low res====================================
FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
IFBUpdate(ctx, dpy) {}
@@ -167,12 +173,12 @@
// Dont do wormhole calculation when extDownscale is enabled on External
if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
sourceCrop = layer->displayFrame;
- displayFrame = sourceCrop;
} else if((!mDpy ||
- (mDpy && !extOrient
- && !ctx->dpyAttr[mDpy].mDownScaleMode))
- && (extOnlyLayerIndex == -1)) {
- if(!qdutils::MDPVersion::getInstance().is8x26()) {
+ (mDpy && !extOrient
+ && !ctx->dpyAttr[mDpy].mDownScaleMode))
+ && (extOnlyLayerIndex == -1)) {
+ if(!qdutils::MDPVersion::getInstance().is8x26() &&
+ !ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
displayFrame = sourceCrop;
}
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 4b449c8..da4cdfc 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -39,7 +39,9 @@
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;
+ int fbZorder) = 0;
+ virtual bool prepareAndValidate(hwc_context_t *ctx,
+ hwc_display_contents_1 *list, int fbZorder);
// Draws layer
virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
//Reset values
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8008d39..6ff1aa3 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
*
@@ -233,7 +233,7 @@
fbCount = numLayers;
mdpCount = 0;
needsRedraw = true;
- fbZ = 0;
+ fbZ = -1;
}
void MDPComp::FrameInfo::map() {
@@ -300,7 +300,6 @@
}
bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
- const int dpy = HWC_DISPLAY_PRIMARY;
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(!hnd) {
@@ -316,9 +315,6 @@
if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
return false;
- int hw_w = ctx->dpyAttr[mDpy].xres;
- int hw_h = ctx->dpyAttr[mDpy].yres;
-
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t dst = layer->displayFrame;
int crop_w = crop.right - crop.left;
@@ -407,7 +403,6 @@
bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
bool ret = true;
- const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
@@ -424,8 +419,8 @@
__FUNCTION__);
ret = false;
} else if(ctx->isPaddingRound) {
- ctx->isPaddingRound = false;
- ALOGD_IF(isDebug(), "%s: padding round",__FUNCTION__);
+ ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+ __FUNCTION__,mDpy);
ret = false;
}
return ret;
@@ -451,13 +446,13 @@
if(!isValidRect(visibleRect)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
+ continue;
}
const hwc_layer_1_t* layer = &list->hwLayers[i];
hwc_rect_t dstRect = layer->displayFrame;
hwc_rect_t srcRect = integerizeSourceCrop(layer->sourceCropf);
- int transform = layer->transform;
hwc_rect_t res = getIntersection(visibleRect, dstRect);
@@ -472,17 +467,17 @@
}else {
/* Reset frame ROI when any layer which needs scaling also needs ROI
* cropping */
- if((res_w != dst_w || res_h != dst_h) &&
- needsScaling (layer)) {
+ if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
return false;
}
- }
- if (layer->blending == HWC_BLENDING_NONE)
- visibleRect = deductRect(visibleRect, res);
+ /* deduct any opaque region from visibleRect */
+ if (layer->blending == HWC_BLENDING_NONE)
+ visibleRect = deductRect(visibleRect, res);
+ }
}
return true;
}
@@ -514,7 +509,6 @@
hwc_rect_t dstRect = list->hwLayers[index].displayFrame;
hwc_rect_t srcRect = integerizeSourceCrop(
list->hwLayers[index].sourceCropf);
- int transform = list->hwLayers[index].transform;
/* Intersect against display boundaries */
roi = getUnion(roi, dstRect);
@@ -636,7 +630,6 @@
}
mCurrentFrame.fbCount = 0;
- mCurrentFrame.fbZ = -1;
memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
sizeof(mCurrentFrame.isFBComposed));
mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
@@ -728,7 +721,7 @@
bool MDPComp::loadBasedCompPreferGPU(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- if(not isLoadBasedCompDoable(ctx, list)) {
+ if(not isLoadBasedCompDoable(ctx)) {
return false;
}
@@ -738,7 +731,8 @@
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 - (stagesForMDP - 1); //1 for FB
+ const int batchSize = (numAppLayers - mCurrentFrame.dropCount) -
+ (stagesForMDP - 1); //1 for FB
if(batchSize <= 0) {
ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
@@ -746,20 +740,50 @@
}
int minBatchStart = -1;
+ int minBatchEnd = -1;
size_t minBatchPixelCount = SIZE_MAX;
- for(int i = 0; i <= numAppLayers - batchSize; i++) {
+ /* 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;
- for(int j = i; j < i + batchSize; j++) {
- hwc_layer_1_t* layer = &list->hwLayers[j];
- hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
- batchPixelCount += (crop.right - crop.left) *
+ 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--;
+ }
}
- if(batchPixelCount < minBatchPixelCount) {
+ /* we dont want to program any batch of size lesser than batchSize */
+ if(!batchCount && (batchPixelCount < minBatchPixelCount)) {
minBatchPixelCount = batchPixelCount;
minBatchStart = i;
+ minBatchEnd = j-1;
}
}
@@ -769,8 +793,10 @@
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 >= minBatchStart + batchSize) {
+ 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",
@@ -784,10 +810,12 @@
mCurrentFrame.fbZ = minBatchStart;
mCurrentFrame.fbCount = batchSize;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+ mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
+ mCurrentFrame.dropCount;
- ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
- __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+ ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d fbStart: %d fbEnd: %d",
+ __FUNCTION__, mCurrentFrame.fbZ, batchSize, minBatchStart,
+ minBatchEnd);
if(sEnable4k2kYUVSplit){
adjustForSourceSplit(ctx, list);
@@ -804,7 +832,7 @@
bool MDPComp::loadBasedCompPreferMDP(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
- if(not isLoadBasedCompDoable(ctx, list)) {
+ if(not isLoadBasedCompDoable(ctx)) {
return false;
}
@@ -821,7 +849,9 @@
const int fullScreenLayers = bwLeft * 1000000000 / (ctx->dpyAttr[mDpy].xres
* ctx->dpyAttr[mDpy].yres * bpp * panelRefRate);
- const int fbBatchSize = numAppLayers - (fullScreenLayers - 1);
+ 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.
@@ -830,28 +860,43 @@
return false;
}
- //Top-most layers constitute FB batch
- const int fbBatchStart = numAppLayers - fbBatchSize;
+ //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])
+ continue;
- //Bottom-most layers constitute MDP batch
- for(int i = 0; i < fbBatchStart; 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;
+ if(fbEnd < 0)
+ fbEnd = i;
+
+ if(!(--batchCount)) {
+ fbStart = i;
+ break;
}
- mCurrentFrame.isFBComposed[i] = false;
}
- mCurrentFrame.fbZ = fbBatchStart;
- mCurrentFrame.fbCount = fbBatchSize;
- mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
+ //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: FB Z %d, num app layers %d, MDP Batch Size %d",
- __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
- numAppLayers - fbBatchSize);
+ 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);
@@ -866,8 +911,7 @@
return true;
}
-bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
+bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
if(mDpy or isSecurePresent(ctx, mDpy) or
isYuvPresent(ctx, mDpy)) {
return false;
@@ -1075,14 +1119,14 @@
int maxBatchCount = 0;
int fbZ = -1;
- /* All or Nothing is cached. No batching needed */
- if(!mCurrentFrame.fbCount) {
- mCurrentFrame.fbZ = -1;
+ /* Nothing is cached. No batching needed */
+ if(mCurrentFrame.fbCount == 0) {
return true;
}
- if(!mCurrentFrame.mdpCount) {
- mCurrentFrame.fbZ = 0;
- return true;
+
+ /* No MDP comp layers, try to use other comp modes */
+ if(mCurrentFrame.mdpCount == 0) {
+ return false;
}
fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
@@ -1121,7 +1165,6 @@
int fbCount = 0;
for(int i = 0; i < numAppLayers; i++) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
if(!mCurrentFrame.drop[i])
fbCount++;
@@ -1235,6 +1278,12 @@
}
}
+ if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
+ ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
+ ,__FUNCTION__, mDpy);
+ return false;
+ }
+
setRedraw(ctx, list);
return true;
}
@@ -1247,10 +1296,6 @@
return false;
}
- if(!arePipesAvailable(ctx, list)) {
- return false;
- }
-
double size = calcMDPBytesRead(ctx, list);
if(!bandwidthCheck(ctx, size)) {
ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
@@ -1360,11 +1405,10 @@
const int numLayers = ctx->listStats[mDpy].numAppLayers;
MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
- //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
- //do not cache the information for next draw cycle.
- if(numLayers > MAX_NUM_APP_LAYERS) {
- ALOGI("%s: Number of App layers exceeded the limit ",
- __FUNCTION__);
+ //Do not cache the information for next draw cycle.
+ if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
+ ALOGI("%s: Unsupported layer count for mdp composition",
+ __FUNCTION__);
mCachedFrame.reset();
return -1;
}
@@ -1431,12 +1475,9 @@
return ret;
}
-bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, int index) {
+bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index) {
bool bRet = true;
- hwc_layer_1_t* layer = &list->hwLayers[index];
- private_handle_t *hnd = (private_handle_t *)layer->handle;
int mdpIndex = mCurrentFrame.layerToMDP[index];
PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
info.pipeInfo = new MdpYUVPipeInfo;
@@ -1461,10 +1502,10 @@
}
return bRet;
}
-//=============MDPCompNonSplit===================================================
+//=============MDPCompNonSplit==================================================
void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t* list){
+ hwc_display_contents_1_t*) {
//As we split 4kx2k yuv layer and program to 2 VG pipes
//(if available) increase mdpcount accordingly
mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
@@ -1504,58 +1545,6 @@
&PipeLayerPair.rot);
}
-bool MDPCompNonSplit::arePipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- overlay::Overlay& ov = *ctx->mOverlay;
- int numPipesNeeded = mCurrentFrame.mdpCount;
- int availPipes = ov.availablePipes(mDpy, Overlay::MIXER_DEFAULT);
-
- //Reserve pipe for FB
- if(mCurrentFrame.fbCount)
- availPipes -= 1;
-
- if(numPipesNeeded > availPipes) {
- ALOGD_IF(isDebug(), "%s: Insufficient pipes, dpy %d needed %d, avail %d",
- __FUNCTION__, mDpy, numPipesNeeded, availPipes);
- return false;
- }
-
- if(not areVGPipesAvailable(ctx, list)) {
- return false;
- }
-
- return true;
-}
-
-bool MDPCompNonSplit::areVGPipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- overlay::Overlay& ov = *ctx->mOverlay;
- int pipesNeeded = 0;
- for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
- if(!mCurrentFrame.isFBComposed[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dst = layer->displayFrame;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
- pipesNeeded = pipesNeeded + 2;
- }
- else if(isYuvBuffer(hnd)) {
- pipesNeeded++;
- }
- }
- }
-
- int availableVGPipes = ov.availablePipes(mDpy, ovutils::OV_MDP_PIPE_VG);
- if(pipesNeeded > availableVGPipes) {
- ALOGD_IF(isDebug(), "%s: Insufficient VG pipes for video layers"
- "dpy %d needed %d, avail %d",
- __FUNCTION__, mDpy, pipesNeeded, availableVGPipes);
- return false;
- }
-
- return true;
-}
-
bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
for(int index = 0; index < mCurrentFrame.layerCount; index++) {
@@ -1565,7 +1554,7 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
- if(allocSplitVGPipesfor4k2k(ctx, list, index)){
+ if(allocSplitVGPipesfor4k2k(ctx, index)){
continue;
}
}
@@ -1579,6 +1568,10 @@
if(isYuvBuffer(hnd)) {
type = MDPCOMP_OV_VG;
+ } else if(qdutils::MDPVersion::getInstance().is8x26() &&
+ (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024)) {
+ if(qhwc::needsScaling(layer))
+ type = MDPCOMP_OV_RGB;
} else if(!qhwc::needsScaling(layer)
&& Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
&& ctx->mMDP.version >= qdutils::MDSS_V5) {
@@ -1749,110 +1742,9 @@
}
}
-int MDPCompSplit::pipesNeeded(hwc_context_t *ctx,
- hwc_display_contents_1_t* list,
- int mixer) {
- int pipesNeeded = 0;
- const int xres = ctx->dpyAttr[mDpy].xres;
-
- const int lSplit = getLeftSplit(ctx, mDpy);
-
- for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
- if(!mCurrentFrame.isFBComposed[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dst = layer->displayFrame;
- if(mixer == Overlay::MIXER_LEFT && dst.left < lSplit) {
- pipesNeeded++;
- } else if(mixer == Overlay::MIXER_RIGHT && dst.right > lSplit) {
- pipesNeeded++;
- }
- }
- }
- return pipesNeeded;
-}
-
-bool MDPCompSplit::arePipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- overlay::Overlay& ov = *ctx->mOverlay;
- int totalPipesNeeded = 0;
-
- for(int i = 0; i < Overlay::MIXER_MAX; i++) {
- int numPipesNeeded = pipesNeeded(ctx, list, i);
- int availPipes = ov.availablePipes(mDpy, i);
-
- //Reserve pipe(s)for FB
- if(mCurrentFrame.fbCount)
- numPipesNeeded += 1;
-
- totalPipesNeeded += numPipesNeeded;
-
- //Per mixer check.
- if(numPipesNeeded > availPipes) {
- ALOGD_IF(isDebug(), "%s: Insufficient pipes for "
- "dpy %d mixer %d needed %d, avail %d",
- __FUNCTION__, mDpy, i, numPipesNeeded, availPipes);
- return false;
- }
- }
-
- //Per display check, since unused pipes can get counted twice.
- int totalPipesAvailable = ov.availablePipes(mDpy);
- if(totalPipesNeeded > totalPipesAvailable) {
- ALOGD_IF(isDebug(), "%s: Insufficient pipes for "
- "dpy %d needed %d, avail %d",
- __FUNCTION__, mDpy, totalPipesNeeded, totalPipesAvailable);
- return false;
- }
-
- if(not areVGPipesAvailable(ctx, list)) {
- return false;
- }
-
- return true;
-}
-
-bool MDPCompSplit::areVGPipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- overlay::Overlay& ov = *ctx->mOverlay;
- int pipesNeeded = 0;
- const int lSplit = getLeftSplit(ctx, mDpy);
- for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
- if(!mCurrentFrame.isFBComposed[i]) {
- hwc_layer_1_t* layer = &list->hwLayers[i];
- hwc_rect_t dst = layer->displayFrame;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
- if((dst.left > lSplit)||(dst.right < lSplit)){
- pipesNeeded = pipesNeeded + 2;
- continue;
- }
- }
- if(isYuvBuffer(hnd)) {
- if(dst.left < lSplit) {
- pipesNeeded++;
- }
- if(dst.right > lSplit) {
- pipesNeeded++;
- }
- }
- }
- }
-
- int availableVGPipes = ov.availablePipes(mDpy, ovutils::OV_MDP_PIPE_VG);
- if(pipesNeeded > availableVGPipes) {
- ALOGD_IF(isDebug(), "%s: Insufficient VG pipes for video layers"
- "dpy %d needed %d, avail %d",
- __FUNCTION__, mDpy, pipesNeeded, availableVGPipes);
- return false;
- }
-
- return true;
-}
-
bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
MdpPipeInfoSplit& pipe_info,
ePipeType type) {
- const int xres = ctx->dpyAttr[mDpy].xres;
const int lSplit = getLeftSplit(ctx, mDpy);
hwc_rect_t dst = layer->displayFrame;
@@ -1886,7 +1778,7 @@
const int lSplit = getLeftSplit(ctx, mDpy);
if(is4kx2kYuvBuffer(hnd) && sEnable4k2kYUVSplit){
if((dst.left > lSplit)||(dst.right < lSplit)){
- if(allocSplitVGPipesfor4k2k(ctx, list, index)){
+ if(allocSplitVGPipesfor4k2k(ctx, index)){
continue;
}
}
@@ -2047,8 +1939,8 @@
if(ctx->mAD->isModeOn()) {
if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd(ctx);
- offset = ctx->mAD->getDstOffset(ctx);
+ fd = ctx->mAD->getDstFd();
+ offset = ctx->mAD->getDstOffset();
}
}
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index bc41bd9..f2a8eda 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -136,9 +136,6 @@
/* configures MPD pipes */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& pipeLayerPair) = 0;
- /* Checks for pipes needed versus pipes available */
- virtual bool arePipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) = 0;
/* 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,
@@ -172,8 +169,7 @@
bool loadBasedCompPreferMDP(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,
- hwc_display_contents_1_t* list);
+ bool isLoadBasedCompDoable(hwc_context_t *ctx);
/* checks for conditions where only video can be bypassed */
bool tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
@@ -246,8 +242,7 @@
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
static bool sEnable4k2kYUVSplit;
- bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, int index);
+ bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
};
class MDPCompNonSplit : public MDPComp {
@@ -270,18 +265,10 @@
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* Checks for pipes needed versus pipes available */
- virtual bool arePipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* Checks for video pipes needed versus pipes available */
- virtual bool areVGPipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
/* 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,
- hwc_display_contents_1_t* list);
+ hwc_display_contents_1_t* list);
/* configures 4kx2k yuv layer to 2 VG pipes*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -311,14 +298,6 @@
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
- /* Checks for pipes needed versus pipes available */
- virtual bool arePipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* Checks for video pipes needed versus pipes available */
- virtual bool areVGPipesAvailable(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
/* 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,
@@ -327,9 +306,6 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair);
-
- int pipesNeeded(hwc_context_t *ctx, hwc_display_contents_1_t* list,
- int mixer);
};
}; //namespace
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 8c99d64..2320bc0 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -31,6 +31,7 @@
#include <IQService.h>
#include <hwc_utils.h>
#include <hwc_vpuclient.h>
+#include <mdp_version.h>
#define QCLIENT_DEBUG 0
@@ -94,16 +95,19 @@
return result;
}
+#ifdef VPU_TARGET
static android::status_t vpuCommand(hwc_context_t *ctx,
uint32_t command,
const Parcel* inParcel,
Parcel* outParcel) {
status_t result = NO_INIT;
-#ifdef VPU_TARGET
- result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
+#ifdef QCOM_BSP
+ if(qdutils::MDPVersion::getInstance().is8092())
+ result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
#endif
return result;
}
+#endif
static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
ctx->mExtOrientation = orientation;
@@ -126,8 +130,9 @@
//XXX: Need to check what to return for HDMI
outParcel->writeInt32(ctx->mMDP.panel);
}
-static void setHSIC(hwc_context_t* ctx, const Parcel* inParcel) {
+static void setHSIC(const Parcel* inParcel) {
int dpy = inParcel->readInt32();
+ ALOGD_IF(0, "In %s: dpy = %d", __FUNCTION__, dpy);
HSICData_t hsic_data;
hsic_data.hue = inParcel->readInt32();
hsic_data.saturation = inParcel->readFloat();
@@ -181,11 +186,12 @@
Parcel* outParcel) {
status_t ret = NO_ERROR;
+#ifdef VPU_TARGET
if (command > IQService::VPU_COMMAND_LIST_START &&
command < IQService::VPU_COMMAND_LIST_END) {
return vpuCommand(mHwcContext, command, inParcel, outParcel);
}
-
+#endif
switch(command) {
case IQService::SECURING:
securing(mHwcContext, inParcel->readInt32());
@@ -213,7 +219,7 @@
getDisplayAttributes(mHwcContext, inParcel, outParcel);
break;
case IQService::SET_HSIC_DATA:
- setHSIC(mHwcContext, inParcel);
+ setHSIC(inParcel);
case IQService::PAUSE_WFD:
pauseWFD(mHwcContext, inParcel->readInt32());
break;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 5692ef1..d2104ed 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -54,6 +54,34 @@
namespace qhwc {
+bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
+{
+ return !((xres > qdutils::MAX_DISPLAY_DIM &&
+ !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
+ (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
+}
+
+void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig) {
+ //Store original display resolution.
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_orig = xres_orig;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_orig = yres_orig;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
+
+ char property[PROPERTY_VALUE_MAX] = {'\0'};
+ char *yptr = NULL;
+ if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+ yptr = strcasestr(property,"x");
+ int xres = atoi(property);
+ int yres = atoi(yptr + 1);
+ if (isValidResolution(ctx,xres,yres) &&
+ xres != xres_orig && yres != yres_orig) {
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = xres;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = yres;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+ }
+ }
+}
+
static int openFramebufferDevice(hwc_context_t *ctx)
{
struct fb_fix_screeninfo finfo;
@@ -117,6 +145,9 @@
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
+ //To change resolution of primary display
+ changeResolution(ctx, info.xres, info.yres);
+
//Unblank primary on first boot
if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
ALOGE("%s: Failed to unblank display", __FUNCTION__);
@@ -182,12 +213,17 @@
ctx->dpyAttr[i].mAsHeightRatio = 0;
}
+ for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ ctx->mPrevHwLayerCount[i] = 0;
+ }
+
MDPComp::init(ctx);
ctx->mAD = new AssertiveDisplay(ctx);
ctx->vstate.enable = false;
ctx->vstate.fakevsync = false;
ctx->mExtOrientation = 0;
+ ctx->numActiveDisplays = 1;
//Right now hwc starts the service but anybody could do it, or it could be
//independent process as well.
@@ -200,8 +236,11 @@
// Initialize device orientation to its default orientation
ctx->deviceOrientation = 0;
ctx->mBufferMirrorMode = false;
+ ctx->mVPUClient = NULL;
+
#ifdef VPU_TARGET
- ctx->mVPUClient = new VPUClient();
+ if(qdutils::MDPVersion::getInstance().is8092())
+ ctx->mVPUClient = new VPUClient(ctx);
#endif
ALOGI("Initializing Qualcomm Hardware Composer");
@@ -238,9 +277,8 @@
}
#ifdef VPU_TARGET
- if(ctx->mVPUClient) {
+ if(ctx->mVPUClient != NULL)
delete ctx->mVPUClient;
- }
#endif
for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
@@ -452,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
@@ -460,7 +498,6 @@
getAspectRatioPosition(width, height, width, height, r);
xPos = r.left;
yPos = r.top;
- float tempWidth = r.right - r.left;
float tempHeight = r.bottom - r.top;
yRatio = yPos/height;
wRatio = outPos.w/width;
@@ -787,7 +824,7 @@
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
trimList(ctx, list, dpy);
- optimizeLayerRects(ctx, list, dpy);
+ optimizeLayerRects(list);
// Calculate view frame of ext display from primary resolution
// and primary device orientation.
@@ -887,6 +924,7 @@
if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
ctx->mVideoTransFlag = true;
}
+
if(dpy == HWC_DISPLAY_PRIMARY) {
ctx->mAD->markDoable(ctx, list);
}
@@ -998,8 +1036,6 @@
const int& sci_t = scissor.top;
const int& sci_r = scissor.right;
const int& sci_b = scissor.bottom;
- int sci_w = abs(sci_r - sci_l);
- int sci_h = abs(sci_b - sci_t);
double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
bottomCutRatio = 0.0;
@@ -1106,14 +1142,12 @@
return res;
}
-void optimizeLayerRects(hwc_context_t *ctx,
- const hwc_display_contents_1_t *list, const int& dpy) {
+void optimizeLayerRects(const hwc_display_contents_1_t *list) {
int i=list->numHwLayers-2;
- hwc_rect_t irect;
while(i > 0) {
-
//see if there is no blending required.
- //If it is opaque see if we can substract this region from below layers.
+ //If it is opaque see if we can substract this region from below
+ //layers.
if(list->hwLayers[i].blending == HWC_BLENDING_NONE) {
int j= i-1;
hwc_rect_t& topframe =
@@ -1199,7 +1233,6 @@
int retireFd = -1;
int fbFd = -1;
bool swapzero = false;
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
struct mdp_buf_sync data;
memset(&data, 0, sizeof(data));
@@ -1222,38 +1255,42 @@
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;
}
}
- //Accumulate acquireFenceFds for MDP
+ //Accumulate acquireFenceFds for MDP Overlays
if(list->outbufAcquireFenceFd >= 0) {
//Writeback output buffer
acquireFd[count++] = list->outbufAcquireFenceFd;
}
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
- list->hwLayers[i].compositionType == HWC_BLIT) &&
+ if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
list->hwLayers[i].acquireFenceFd >= 0) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
@@ -1293,6 +1330,7 @@
dpy, list->numHwLayers);
}
+ LayerProp *layerProp = ctx->layerProp[dpy];
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
list->hwLayers[i].compositionType == HWC_BLIT ||
@@ -1304,9 +1342,17 @@
// Release all the app layer fds immediately,
// if animation is in progress.
list->hwLayers[i].releaseFenceFd = -1;
- } else if(list->hwLayers[i].releaseFenceFd < 0) {
- //If rotator has not already populated this field.
- list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ } else if(list->hwLayers[i].releaseFenceFd < 0 &&
+ !(layerProp[i].mFlags & HWC_VPUCOMP)) {
+ //If rotator has not already populated this field
+ // & if it's a not VPU layer
+ if(list->hwLayers[i].compositionType == HWC_BLIT) {
+ //For Blit, the app layers should be released when the Blit is
+ //complete. This fd was passed from copybit->draw
+ list->hwLayers[i].releaseFenceFd = dup(fd);
+ } else {
+ list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ }
}
}
}
@@ -1343,13 +1389,19 @@
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
+ if (layer->flags & HWC_VPU_PIPE) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_VPU_PIPE);
+ }
+
if(isYuvBuffer(hnd)) {
if(isSecureBuffer(hnd)) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
}
+ // in mpq, deinterlacing is done in vpu
if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
- metadata->interlaced) {
+ metadata->interlaced &&
+ (!qdutils::MDPVersion::getInstance().is8092())) {
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_DEINTERLACE);
}
@@ -1537,6 +1589,16 @@
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+#ifdef VPU_TARGET
+ if(ctx->mVPUClient != NULL &&
+ ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
+ whf.format = getMdpFormat(
+ ctx->mVPUClient->getLayerFormat(dpy, layer));
+ whf.w = ctx->mVPUClient->getWidth(dpy, layer);
+ whf.h = ctx->mVPUClient->getHeight(dpy, layer);
+ }
+#endif
+
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -1566,7 +1628,7 @@
*rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1;
if(!dpy)
- BwcPM::setBwc(ctx, crop, dst, transform, mdpFlags);
+ BwcPM::setBwc(crop, dst, transform, mdpFlags);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -1644,6 +1706,16 @@
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+#ifdef VPU_TARGET
+ if(ctx->mVPUClient != NULL &&
+ ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
+ whf.format = getMdpFormat(
+ ctx->mVPUClient->getLayerFormat(dpy, layer));
+ whf.w = ctx->mVPUClient->getWidth(dpy, layer);
+ whf.h = ctx->mVPUClient->getHeight(dpy, layer);
+ }
+#endif
+
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -1773,8 +1845,6 @@
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
- int hw_w = ctx->dpyAttr[dpy].xres;
- int hw_h = ctx->dpyAttr[dpy].yres;
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform;
@@ -1796,7 +1866,7 @@
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
if(!dpy)
- BwcPM::setBwc(ctx, crop, dst, transform, mdpFlagsL);
+ BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -1930,7 +2000,33 @@
ctx->layerProp[dpy] = new LayerProp[numAppLayers];
}
-void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
+/* Since we fake non-Hybrid WFD solution as external display, this
+ * function helps us in determining the priority between external
+ * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
+ * screenrecord). This can be removed once wfd-client migrates to
+ * using virtual-display api's.
+ */
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+ const hwc_display_contents_1_t *list) {
+
+ /* We rely on the fact that for pure virtual display solution
+ * list->outbuf will be a non-NULL handle.
+ *
+ * If there are three active displays (which means there is one
+ * primary, one external and one virtual active display)
+ * we give mdss/mdp hw resources(pipes,smp,etc) for external
+ * display(hdmi/non-Hybrid WFD display) rather than for virtual
+ * display(SSD/screenrecord)
+ */
+
+ if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
+ return false;
+ }
+
+ return true;
+}
+
+void BwcPM::setBwc(const hwc_rect_t& crop,
const hwc_rect_t& dst, const int& transform,
ovutils::eMdpFlags& mdpFlags) {
//Target doesnt support Bwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 2b889f5..8293505 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -35,6 +35,8 @@
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
#define MAX_NUM_APP_LAYERS 32
+#define MIN_DISPLAY_XRES 200
+#define MIN_DISPLAY_YRES 200
//Fwrd decls
struct hwc_context_t;
@@ -95,6 +97,13 @@
bool mActionSafePresent;
int mAsWidthRatio;
int mAsHeightRatio;
+
+ //If property fbsize set via adb shell debug.hwc.fbsize = XRESxYRES
+ //following fields are used.
+ bool customFBSize;
+ uint32_t xres_orig;
+ uint32_t yres_orig;
+
};
struct ListStats {
@@ -127,7 +136,7 @@
};
struct BwcPM {
- static void setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
+ static void setBwc(const hwc_rect_t& crop,
const hwc_rect_t& dst, const int& transform,
ovutils::eMdpFlags& mdpFlags);
};
@@ -136,12 +145,14 @@
enum {
HWC_MDPCOMP = 0x00000001,
HWC_COPYBIT = 0x00000002,
+ HWC_VPUCOMP = 0x00000004,
};
// HAL specific features
enum {
HWC_COLOR_FILL = 0x00000008,
HWC_FORMAT_RB_SWAP = 0x00000040,
+ HWC_VPU_PIPE = 0x00000200,
};
class LayerRotMap {
@@ -230,6 +241,9 @@
bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+ const hwc_display_contents_1_t *list);
+
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -238,8 +252,7 @@
hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
-void optimizeLayerRects(hwc_context_t *ctx,
- const hwc_display_contents_1_t *list, const int& dpy);
+void optimizeLayerRects(const hwc_display_contents_1_t *list);
bool areLayersIntersecting(const hwc_layer_1_t* layer1,
const hwc_layer_1_t* layer2);
@@ -386,7 +399,7 @@
static inline int getWidth(const private_handle_t* hnd) {
if(isYuvBuffer(hnd)) {
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
return metadata->bufferDim.sliceWidth;
}
@@ -396,7 +409,7 @@
static inline int getHeight(const private_handle_t* hnd) {
if(isYuvBuffer(hnd)) {
- MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
return metadata->bufferDim.sliceHeight;
}
@@ -475,6 +488,10 @@
eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
qhwc::HWCVirtualBase *mHWCVirtual;
+ // stores the #numHwLayers of the previous frame
+ // for each display device
+ int mPrevHwLayerCount[HWC_NUM_DISPLAY_TYPES];
+
// stores the primary device orientation
int deviceOrientation;
//Securing in progress indicator
@@ -491,15 +508,14 @@
int mExtOrientation;
//Flags the transition of a video session
bool mVideoTransFlag;
-
//Used for SideSync feature
//which overrides the mExtOrientation
bool mBufferMirrorMode;
-
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
-
// Panel reset flag will be set if BTA check fails
bool mPanelResetStatus;
+ // number of active Displays
+ int numActiveDisplays;
};
namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 51ade32..cc29d45 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -62,14 +62,12 @@
ctx->mMDPComp[dpy]->reset();
}
-void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t numDisplays,
+void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
hwc_display_contents_1_t** displays) {
int dpy = HWC_DISPLAY_VIRTUAL;
//Cleanup virtual display objs, since there is no explicit disconnect
- if(ctx->dpyAttr[dpy].connected &&
- (numDisplays <= HWC_NUM_PHYSICAL_DISPLAY_TYPES ||
- displays[dpy] == NULL)) {
+ if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
ctx->dpyAttr[dpy].connected = false;
if(ctx->mFBUpdate[dpy]) {
@@ -80,6 +78,11 @@
delete ctx->mMDPComp[dpy];
ctx->mMDPComp[dpy] = NULL;
}
+ // We reset the WB session to non-secure when the virtual display
+ // has been disconnected.
+ if(!Writeback::getInstance()->setSecure(false)) {
+ ALOGE("Failure while attempting to reset WB session.");
+ }
}
}
@@ -101,9 +104,14 @@
if(ctx->dpyAttr[dpy].connected == false) {
ctx->dpyAttr[dpy].connected = true;
+ // We set the vsync period to the primary refresh rate, leaving
+ // it up to the consumer to decide how fast to consume frames.
+ ctx->dpyAttr[dpy].vsync_period
+ = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
init(ctx);
- //First round, just setup and return so primary can free pipes
- return 0;
+ // XXX: for architectures with limited resources we would normally
+ // allow one padding round to free up resources but this breaks
+ // certain use cases.
}
ctx->dpyAttr[dpy].isConfiguring = false;
@@ -114,7 +122,7 @@
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+ ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
}
}
return 0;
@@ -129,11 +137,22 @@
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- if(fbLayer->handle && !isSecondaryConfiguring(ctx) &&
- !ctx->mMDPComp[dpy]->isGLESOnlyComp()) {
+ if(ctx->dpyAttr[dpy].connected) {
private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+ int format = ohnd->format;
+ if (format == HAL_PIXEL_FORMAT_RGBA_8888)
+ format = HAL_PIXEL_FORMAT_RGBX_8888;
Writeback::getInstance()->setOutputFormat(
- utils::getMdpFormat(ohnd->format));
+ utils::getMdpFormat(format));
+
+ // Configure WB as secure if the output buffer handle is secure.
+ if(isSecureBuffer(ohnd)){
+ if(! Writeback::getInstance()->setSecure(true))
+ {
+ ALOGE("Failed to set WB as secure for virtual display");
+ return false;
+ }
+ }
int fd = -1; //FenceFD from the Copybit
hwc_sync(ctx, list, dpy, fd);
@@ -142,7 +161,13 @@
ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1;
}
- if (!ctx->mFBUpdate[dpy]->draw(ctx,
+ // We need an FB layer handle check to cater for this usecase:
+ // Video is playing in landscape on primary, then launch
+ // ScreenRecord app.
+ // In this scenario, the first VDS draw call will have HWC
+ // composition and VDS does nit involve GPU to get eglSwapBuffer
+ // to get valid fb handle.
+ if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
(private_handle_t *)fbLayer->handle)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
@@ -180,14 +205,15 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected) {
+ ctx->dpyAttr[dpy].connected &&
+ canUseMDPforVirtualDisplay(ctx,list)) {
reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
if(!ctx->dpyAttr[dpy].isPause) {
ctx->dpyAttr[dpy].isConfiguring = false;
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+ ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
}
} else {
/* Virtual Display is in Pause state.
@@ -211,7 +237,8 @@
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected &&
- !ctx->dpyAttr[dpy].isPause) {
+ (!ctx->dpyAttr[dpy].isPause) &&
+ canUseMDPforVirtualDisplay(ctx,list)) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
@@ -257,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/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h
index 502aa3b..26f401f 100644
--- a/libhwcomposer/hwc_virtual.h
+++ b/libhwcomposer/hwc_virtual.h
@@ -75,11 +75,11 @@
// instantiates mdpcomp, copybit and fbupdate objects and initialize those
// objects for virtual display during virtual display connect. This function
// is no-op for V4L2 design
- virtual void init(hwc_context_t *ctx) {};
+ virtual void init(hwc_context_t *) {};
// Destroys mdpcomp, copybit and fbupdate objects and for virtual display
// during virtual display disconnect. This function is no-op for V4L2 design
- virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
- hwc_display_contents_1_t** displays){};
+ virtual void destroy(hwc_context_t *, size_t ,
+ hwc_display_contents_1_t** ) {};
};
}; //namespace
diff --git a/libhwcomposer/hwc_vpuclient.cpp b/libhwcomposer/hwc_vpuclient.cpp
index 23c6841..6904efc 100644
--- a/libhwcomposer/hwc_vpuclient.cpp
+++ b/libhwcomposer/hwc_vpuclient.cpp
@@ -1,93 +1,964 @@
/*
-* Copyright (c) 2013 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
-* met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 2013-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
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. INNO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING INANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include <dlfcn.h>
#include "hwc_vpuclient.h"
-#include "hwc_utils.h"
-#include <vpu/vpu.h>
#include <binder/Parcel.h>
-
+#include "hwc_fbupdate.h"
+#include <vpu/vpu.h>
using namespace vpu;
using namespace android;
+using namespace overlay::utils;
+namespace ovutils = overlay::utils;
+
namespace qhwc {
-VPUClient::VPUClient()
+VPUClient::VPUClient(hwc_context_t *ctx)
{
mVPULib = dlopen("libvpu.so", RTLD_NOW);
- VPU* (*init)();
- *(void **) &init = dlsym(mVPULib, "getObject");
- if(init)
- mVPU = init();
- else
- mVPU = NULL;
+ VPU* (*getObject)();
+
+ mVPU = NULL;
+ if (mVPULib == NULL) {
+ ALOGE("%s: Cannot open libvpu.so object", __FUNCTION__);
+ return;
+ }
+
+ *(void **) &getObject = dlsym(mVPULib, "getObject");
+ if (getObject) {
+ mVPU = getObject();
+ ALOGI("Initializing VPU client..");
+
+ // calling vpu init
+ if (mVPU->init() == NO_ERROR) {
+ // passing display attributes to libvpu
+ ALOGD_IF(isDebug(), "%s: VFM init successful!", __FUNCTION__);
+
+ DispAttr_t attr;
+ attr.width = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+ attr.height = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+ attr.fp100s = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period) ?
+ 1000000000/(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period/100):0;
+ mVPU->setDisplayAttr((DISPLAY_ID)HWC_DISPLAY_PRIMARY, attr);
+
+ ALOGD_IF(isDebug(),"%s: Display attr: width:%d height:%d fp100s:%d",
+ __FUNCTION__, attr.width, attr.height, attr.fp100s);
+
+ // memsetting the pipe structure to 0
+ memset(mProp, 0, sizeof(mProp));
+
+ mDebugLogs = 0;
+ // enable logs
+ char property[PROPERTY_VALUE_MAX];
+ if ( property_get("debug.vpuclient.logs", property, NULL) > 0 )
+ mDebugLogs = atoi(property);
+
+ // allocating memory for LayerList
+ for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i)
+ vList[i] = (LayerList*) malloc(sizeof(LayerList));
+ }
+ else {
+ ALOGE("Error: VPU init failed!");
+ mVPU = NULL;
+ }
+ }
}
VPUClient::~VPUClient()
{
+ // freeing LayerList
+ for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i) {
+ if (vList[i])
+ free(vList[i]);
+ }
+
void (*destroy) (VPU*);
*(void **) &destroy = dlsym(mVPULib, "deleteObject");
dlclose(mVPULib);
}
-int VPUClient::prepare(hwc_context_t *ctx,
- hwc_display_contents_1_t* list)
+void setLayer(hwc_layer_1_t *layer, Layer *vLayer)
{
- int err = 0;
- if(!mVPU)
- return err;
- // * Check VPU status
- // * Check session availability
- // * Other individual checks
- // Do not pass hwc context/list
- // Mark buffers to be drawn for VPU
- return err;
+ // setting handle info in vLayer
+ vLayer->handle = (private_handle_t *)(layer->handle);
+
+ if (vLayer->handle) {
+ vLayer->srcStride.width = getWidth(vLayer->handle);
+ vLayer->srcStride.height = getHeight(vLayer->handle);
+ }
+
+ // setting source crop
+ hwc_rect_t sourceRect = integerizeSourceCrop(layer->sourceCropf);
+ vLayer->srcRect.left = sourceRect.left;
+ vLayer->srcRect.top = sourceRect.top;
+ vLayer->srcRect.right = sourceRect.right;
+ vLayer->srcRect.bottom = sourceRect.bottom;
+
+ // setting destination crop
+ vLayer->tgtRect.left = layer->displayFrame.left;
+ vLayer->tgtRect.top = layer->displayFrame.top;
+ vLayer->tgtRect.right = layer->displayFrame.right;
+ vLayer->tgtRect.bottom = layer->displayFrame.bottom;
+
+ if (layer->flags & HWC_GEOMETRY_CHANGED)
+ vLayer->inFlags |= GEOMETRY_CHANGED;
+
+ vLayer->acquireFenceFd = layer->acquireFenceFd;
+
+ if (layer->compositionType == HWC_FRAMEBUFFER_TARGET || isSkipLayer(layer))
+ vLayer->inFlags |= SKIP_LAYER;
}
-int VPUClient::draw(hwc_context_t *ctx,
- hwc_display_contents_1_t* list)
+int VPUClient::setupVpuSession(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list)
+{
+ memset(vList[display], 0, sizeof(LayerList));
+ memset(mProp, 0, sizeof(mProp));
+ mNumVpuLayers = 0;
+
+ // setting up the layer
+ LayerList *vpuList = vList[display];
+ vpuList->numLayers = list->numHwLayers;
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ Layer *vLayer = &vpuList->layers[i];
+ VpuLayerProp* prop = &mProp[display][i];
+
+ // Storing the sourceCropf, as it's going to be changed for overlay Set
+ // will be restored after overlay set in prepare.
+ prop->sourceCropf = layer->sourceCropf;
+
+ // filling up the vpu list
+ setLayer(layer, vLayer);
+ ALOGD_IF(isDebug2(), "%s:Done setting lyr:%d for VFM", __FUNCTION__, i);
+ }
+
+ if (mVPU->setupVpuSession((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+ //error in vpu prepare
+ ALOGE("%s: ERROR in VPU::setupVpuSession", __FUNCTION__);
+ return -1;
+ }
+ ALOGD_IF(isDebug2(), "%s: Done VFM: setupVpuSession", __FUNCTION__);
+
+ mGpuFallback = true;
+ LayerProp *layerProp = ctx->layerProp[display];
+ // check if the pipeID is already set for this layer, then will need to
+ // ensure that it is reserved in overlay
+ for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ Layer *vLayer = &vpuList->layers[i];
+ VpuLayerProp* prop = &mProp[display][i];
+
+ if (vLayer->outFlags & VPU_LAYER) {
+ ALOGD_IF(isDebug(), "%s: VPU supported layer:%d", __FUNCTION__, i);
+
+ mNumVpuLayers++;
+ mGpuFallback = false;
+ // Reserving the pipe used in last iteration for the same layer
+ if ((vLayer->outFlags & RESERVE_PREV_PIPES) &&
+ vLayer->sDestPipes.numPipes > 0) {
+ prop->pipeCount = vLayer->sDestPipes.numPipes;
+ if (prop->pipeCount == 1) {
+ setPipeId(prop, vLayer->sDestPipes.pipe[0]);
+ ALOGD_IF(isDebug(), "%s: VPU: Reserved pipe:%d",
+ __FUNCTION__, prop->pipeID[0]);
+ }
+ else if (prop->pipeCount == 2) {
+ setPipeId(prop, vLayer->sDestPipes.pipe[0],
+ vLayer->sDestPipes.pipe[1]);
+ ALOGD_IF(isDebug(), "%s: VPU: Reserved lpipe:%d, rpipe:%d",
+ __FUNCTION__, prop->pipeID[0], prop->pipeID[1]);
+ }
+ else {
+ ALOGE("%s: Invalid pipeCount for resevation", __FUNCTION__);
+ }
+ }
+ else {
+ ALOGD_IF(isDebug(), "%s: 1st vid frame for VPU", __FUNCTION__);
+ prop->firstBuffer = true;
+ }
+
+ // marking the layer pipes for vpu.
+ prop->vpuLayer = true;
+ prop->layer = layer;
+ layer->flags |= HWC_VPU_PIPE;
+
+ // getting image width and height
+ prop->width = layer->displayFrame.right - layer->displayFrame.left;
+ prop->height = layer->displayFrame.bottom - layer->displayFrame.top;
+
+ //setting source crop = dest crop (only for layers drawn by vpu,
+ // since we know it will be scaled up/down by vpu)
+ layer->sourceCropf.left = 0.0;
+ layer->sourceCropf.top = 0.0;
+ layer->sourceCropf.right = (float) prop->width;
+ layer->sourceCropf.bottom = (float) prop->height;
+
+ // setting the flag so that mdpComp wont recognize it as the MDPCOMP
+ layerProp[i].mFlags |= HWC_VPUCOMP;
+
+ // TODO: need to get the proper solution for color fill
+
+ // storing locally the vpu supported format from VFM
+ prop->format = vLayer->vpuOutPixFmt;
+ ALOGD_IF(isDebug(), "%s: MDP: sourceCropf: w:%d h:%d format:%d",
+ __FUNCTION__, prop->width, prop->height, prop->format);
+ }
+ }
+ return 0;
+}
+
+bool VPUClient::allocResLayerPipes(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ overlay::Overlay& ov = *ctx->mOverlay;
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ int pipeid = -1;
+ VpuLayerProp* prop = &mProp[dpy][i];
+
+ // checking if there is already a reserved pipe for this layer
+ // then use the same allocated pipe for this layer
+ getPipeId(prop, pipeid);
+
+ if (pipeid != -1) {
+ // there is a reserved pipe for this layer.
+ ovutils::eDest dest = ov.reservePipe(pipeid);
+ if (dest == ovutils::OV_INVALID) {
+ ALOGE("%s: Unable to get reserved pipe: layer#%d",
+ __FUNCTION__, i);
+ return false;
+ }
+
+ // setting dest locally
+ setDest(prop, dest);
+ ALOGD_IF(isDebug(), "%s: Reserving pipe:%d, dest:%d ", __FUNCTION__,
+ pipeid, dest);
+ }
+ else {
+ ALOGD_IF(isDebug2(), "%s: No reserved pipe for layer:%d",
+ __FUNCTION__, i);
+ }
+ }
+ return true;
+}
+
+bool VPUClient::allocLayerPipes(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ // checking if the pipes are reserved for any layer,
+ // if yes, then updating the index of the pipes
+ if (!allocResLayerPipes(ctx, dpy, list)) {
+ ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
+ return false;
+ }
+
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ VpuLayerProp* prop = &mProp[dpy][i];
+ int pipe = -1;
+ overlay::Overlay& ov = *ctx->mOverlay;
+
+ // only care about the layers supported by VPU
+ if (!prop->vpuLayer)
+ continue;
+
+ // continue if this layer has reserved pipe
+ getPipeId(prop, pipe);
+ if (pipe != -1)
+ continue;
+
+ ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+ overlay::Overlay::MIXER_DEFAULT);
+ if (dest == ovutils::OV_INVALID) {
+ ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+ return false;
+ }
+
+ // setting dest locally
+ setDest(prop, dest);
+ ALOGD_IF(isDebug(), "%s: Newly allocated pipe_dest:%d", __FUNCTION__,
+ dest);
+ }
+ return true;
+}
+
+bool VPUClient::allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ overlay::Overlay& ov = *ctx->mOverlay;
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ int lpipeid = -1;
+ int rpipeid = -1;
+ VpuLayerProp* prop = &mProp[dpy][i];
+
+ // checking if there is already a reserved pipe for this layer
+ // then use the same allocated pipe for this layer
+ getPipeId(prop, lpipeid, rpipeid);
+
+ if (lpipeid != -1 && rpipeid != -1) {
+ ovutils::eDest ldest = ov.reservePipe(lpipeid);
+ if (ldest == ovutils::OV_INVALID) {
+ ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-lsplit: "
+ "layer#%d", __FUNCTION__, i);
+ return false;
+ }
+
+ ovutils::eDest rdest = ov.reservePipe(rpipeid);
+ if (rdest == ovutils::OV_INVALID) {
+ ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-rsplit: "
+ "layer#%d", __FUNCTION__, i);
+ return false;
+ }
+
+ setDest(prop, ldest, rdest);
+ ALOGD_IF(isDebug(), "%s: Reserve lpipe:%d, ldest:%d, rpipe:%d, "
+ "rdest:%d", __FUNCTION__, lpipeid, ldest, rpipeid, rdest);
+ }
+ else if (lpipeid != -1 || rpipeid != -1) {
+ ALOGE("%s: Bug: only one pipe reserved!", __FUNCTION__);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VPUClient::allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ // checking if the pipes are reserved for any layer,
+ // if yes, then updating the index of the pipes
+ if (!allocResLayerPipesSplit(ctx, dpy, list)) {
+ ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
+ return false;
+ }
+
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ VpuLayerProp* prop = &mProp[dpy][i];
+ int lpipe, rpipe;
+ overlay::Overlay& ov = *ctx->mOverlay;
+
+ // only care about the layers supported by VPU
+ if (!prop->vpuLayer)
+ continue;
+
+ // only care about the layers supported by VPU
+ getPipeId(prop, lpipe, rpipe);
+ if (lpipe != -1 && rpipe != -1)
+ continue;
+
+ ovutils::eDest ldest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+ overlay::Overlay::MIXER_LEFT);
+ if (ldest == ovutils::OV_INVALID) {
+ ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+ return false;
+ }
+
+ ovutils::eDest rdest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+ overlay::Overlay::MIXER_RIGHT);
+ if (rdest == ovutils::OV_INVALID) {
+ ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+ return false;
+ }
+
+ // setting dests locally
+ setDest(prop, ldest, rdest);
+ ALOGD_IF(isDebug(), "%s: Newly allocated ldest:%d rdest:%d",
+ __FUNCTION__, ldest, rdest);
+ }
+ return true;
+}
+
+bool VPUClient::configureLayers(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ VpuLayerProp* prop = &mProp[dpy][i];
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+
+ if (!prop->vpuLayer)
+ continue;
+
+ eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+ eZorder zOrder = static_cast<eZorder>(i);
+ eIsFg isFg = IS_FG_OFF;
+ setPipeCount(prop, 1);
+ eDest dest = (eDest) getDest(prop, 0);
+
+ ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipe:%d",
+ __FUNCTION__, layer, zOrder, dest);
+
+ if (configureNonSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg,
+ dest, NULL)) {
+ ALOGE("%s: Failed to configure overlay for layer %d",
+ __FUNCTION__, i);
+ return false;
+ }
+ ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
+
+ // Pipe is successfully allocated for this layer; retrieving it from
+ // overlay
+ int pipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
+ setPipeId(prop, pipeId);
+
+ ALOGD_IF(isDebug(), "%s: allocated pipe:%d layer:%d", __FUNCTION__,
+ pipeId, i);
+ }
+ return true;
+}
+
+bool VPUClient::configureLayersSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ VpuLayerProp* prop = &mProp[dpy][i];
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+
+ if (!prop->vpuLayer)
+ continue;
+
+ eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+ eZorder zOrder = static_cast<eZorder>(i);
+ eIsFg isFg = IS_FG_OFF;
+ setPipeCount(prop, 2);
+ eDest ldest = (eDest) getDest(prop, 0);
+ eDest rdest = (eDest) getDest(prop, 1);
+
+ ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipeL:%d"
+ "dest_pipeR:%d",__FUNCTION__, layer, zOrder, ldest, rdest);
+
+ if (configureSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg, ldest,
+ rdest, NULL)) {
+ ALOGE("%s: Failed to configure overlay for layer %d",
+ __FUNCTION__, i);
+ return false;
+ }
+ ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
+
+ // Pipe is successfully allocated for this layer; retrieving it from
+ // overlay
+ int lpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
+ int rpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 1));
+ setPipeId(prop, lpipeId, rpipeId);
+
+ ALOGD_IF(isDebug(), "%s: allocated l-pipe:%d - r-pipe:%d for layer:%d",
+ __FUNCTION__, lpipeId, rpipeId, i);
+ }
+ return true;
+}
+
+void VPUClient::setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
+ hwc_display_contents_1_t* list)
+{
+ LayerProp *layerProp = ctx->layerProp[dpy];
+
+ // disableGpu only disables gpu for video layer. The expected behavior is to
+ // show a blank screen in case VPU doesnt support a video layer, and gpu
+ // fallback is disabled by the user.
+ bool disableGpu = false;
+ char property[PROPERTY_VALUE_MAX];
+ if ((property_get("persist.hwc.noGpuFallback", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ ALOGD_IF(isDebug(), "%s: GPU fallback is disabled through prop",
+ __FUNCTION__);
+ disableGpu = true;
+ }
+
+ // no layers are supported by vpu
+ if (mGpuFallback && !disableGpu) {
+ ALOGD_IF(isDebug(), "%s: No VPU supported layers - Falling back to GPU",
+ __FUNCTION__);
+ return;
+ }
+
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ hwc_layer_1_t* layer = &(list->hwLayers[i]);
+ VpuLayerProp* prop = &mProp[dpy][i];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+ // mark vpu layers as HWC_OVERLAY, and those video layers that
+ // are not supported by vpu and gpu fallback is disabled by the
+ // user.
+ if (prop->vpuLayer || (isYuvBuffer(hnd) && disableGpu)) {
+ layer->compositionType = HWC_OVERLAY;
+ layer->hints |= HWC_HINT_CLEAR_FB;
+ ALOGD_IF(isDebug(), "%s: Marking layer:%d as overlay",
+ __FUNCTION__, i);
+ }
+ }
+}
+
+int VPUClient::prepare(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ const int numLayers = ctx->listStats[display].numAppLayers;
+ //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+ //do not cache the information for next draw cycle.
+ if (numLayers > MAX_NUM_APP_LAYERS) {
+ ALOGE("%s: Number of App layers exceeded the limit ",__FUNCTION__);
+ return -1;
+ }
+
+ if (setupVpuSession(ctx, display, list)) {
+ ALOGD_IF(isDebug(), "%s: Vpu session setup failed! ",__FUNCTION__);
+ return -1;
+ }
+
+ LayerProp *layerProp = ctx->layerProp[display];
+ bool isSplit = isDisplaySplit(ctx, display);
+ ALOGD_IF(isDebug2(), "%s: Split Pipe:%d ", __FUNCTION__,
+ isSplit ? 1 : 0);
+
+ // setting up the layer
+ LayerList *vpuList = vList[display];
+ vpuList->numLayers = list->numHwLayers;
+
+ // Prepare FB Update at z-0
+ if (numLayers > mNumVpuLayers) {
+ if (!ctx->mFBUpdate[display]->prepare(ctx, list, mNumVpuLayers)) {
+ ALOGD_IF(isDebug(), "%s configure framebuffer failed",
+ __FUNCTION__);
+ return -1;
+ }
+ }
+
+ // Allocate pipe for layers
+ if (!isSplit ? !allocLayerPipes(ctx, display, list) :
+ !allocLayerPipesSplit(ctx, display, list)) {
+ ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
+ return -1;
+ }
+
+ // Configure layers
+ if (!isSplit ? !configureLayers(ctx, display, list) :
+ !configureLayersSplit(ctx, display, list)) {
+ ALOGD_IF(isDebug(), "%s: Unable to configure MDP pipes", __FUNCTION__);
+ return -1;
+ }
+
+ // Set layer flags for MDP/VPU composition
+ setMDPCompLayerFlags(ctx, display, list);
+
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ VpuLayerProp* prop = &mProp[display][i];
+
+ if (!prop->vpuLayer)
+ continue;
+
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ Layer *vLayer = &vpuList->layers[i];
+
+ // re-storing the sourceCropf, as it was changed in setVpuSession for
+ // overlay set
+ layer->sourceCropf = prop->sourceCropf;
+
+ // updating the pipe info inside vfm list
+ if ( prop->pipeCount > 0 && prop->pipeCount <= MAX_PIPES_PER_LAYER ) {
+ vLayer->sDestPipes.numPipes = prop->pipeCount;
+
+ for (int j=0; j < prop->pipeCount; ++j) {
+ // Setting pipe for VPU
+ vLayer->sDestPipes.pipe[j] = prop->pipeID[j];
+ }
+ }
+ }
+
+ if (mVPU->prepare((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+ //error in vpu prepare
+ ALOGE("%s: ERROR in VPU::prepare", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+bool VPUClient::queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
+ private_handle_t* hnd)
+{
+ overlay::Overlay& ov = *ctx->mOverlay;
+ ovutils::eDest dest = (eDest) getDest(prop, 0);
+
+ int fd = hnd->fd;
+ uint32_t offset = hnd->offset;
+
+ if (dest != ovutils::OV_INVALID) {
+ if (!ov.queueBuffer(fd, offset, dest)) {
+ ALOGE("%s: queueBuffer failed", __FUNCTION__);
+ return false;
+ }
+ else {
+ ALOGD_IF(isDebug(), "%s: Queue handle successful: hnd:0x%x "
+ "dest:%d", __FUNCTION__, (unsigned int) hnd, dest);
+ }
+ }
+ else {
+ ALOGE("%s: Invalid Dest: dest:%d", __FUNCTION__, dest);
+ return false;
+ }
+ return true;
+}
+
+bool VPUClient::queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
+ private_handle_t* hnd)
+{
+ overlay::Overlay& ov = *ctx->mOverlay;
+ ovutils::eDest ldest = (eDest) getDest(prop, 0);
+ ovutils::eDest rdest = (eDest) getDest(prop, 1);
+
+ int fd = hnd->fd;
+ uint32_t offset = hnd->offset;
+
+ // play left mixer
+ if (ldest != ovutils::OV_INVALID) {
+ ALOGD_IF(isDebug(), "%s: Queuing left mixer", __FUNCTION__);
+ if (!ov.queueBuffer(fd, offset, ldest)) {
+ ALOGE("%s: queueBuffer failed for left mixer ", __FUNCTION__);
+ return false;
+ }
+ else {
+ ALOGD_IF(isDebug(), "%s: Queue left-handle successful: hnd:0x%x "
+ "ldest:%d", __FUNCTION__, (unsigned int) hnd, ldest);
+ }
+ }
+ else {
+ ALOGE("%s: Invalid l-Split Dest", __FUNCTION__);
+ return false;
+ }
+
+ // play right mixer
+ if (rdest != ovutils::OV_INVALID) {
+ ALOGD_IF(isDebug(), "%s: Queuing right mixer", __FUNCTION__);
+ if (!ov.queueBuffer(fd, offset, rdest)) {
+ ALOGE("%s: queueBuffer failed for right mixer ", __FUNCTION__);
+ return false;
+ }
+ else {
+ ALOGD_IF(isDebug(), "%s: Queue right-handle successful: hnd:0x%x "
+ "rdest:%d", __FUNCTION__, (unsigned int) hnd, rdest);
+ }
+ }
+ else {
+ ALOGE("%s: Invalid r-Split Dest", __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+
+bool VPUClient::drawDummyLayers(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list)
{
int err = 0;
- if(!mVPU)
- return err;
- // Queue buffers to VPU
- return err;
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ VpuLayerProp* prop = &mProp[dpy][i];
+
+ if (!prop->vpuLayer)
+ continue;
+
+ // displaying blank screen for the first frame
+ if (prop->firstBuffer) {
+ ALOGD_IF(isDebug(), "%s: Displaying first (blank) frame",
+ __FUNCTION__);
+ prop->firstBuffer = false;
+
+ if (mHnd[dpy][i] != NULL)
+ free_buffer(mHnd[dpy][i]);
+
+ // TO-FIX: out dummy buffer is currently allocated based on
+ // RGB888 format
+ err = alloc_buffer(&mHnd[dpy][i], prop->width, prop->height,
+ HAL_PIXEL_FORMAT_RGB_888, GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+ if (err == -1) {
+ ALOGE("%s: Dummy buffer allocation failed!", __FUNCTION__);
+ return false;
+ }
+
+ private_handle_t* hnd = mHnd[dpy][i];
+ if (prop->format == HAL_PIXEL_FORMAT_RGB_888) {
+ ALOGD_IF(isDebug(), "%s: Format: RGB888", __FUNCTION__);
+ memset((void*)hnd->base, 0x0, hnd->size);
+ }
+ else if (prop->format ==
+ HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED) {
+ ALOGD_IF(isDebug(), "%s: Format: 10BIT_BWC", __FUNCTION__);
+ memset((void*)hnd->base, 0xaa, hnd->size);
+ }
+ else {
+ ALOGE("%s: Error! Wrong VPU out format - layer:%d",
+ __FUNCTION__, i);
+ return false;
+ }
+
+ bool isSplit = isDisplaySplit(ctx, dpy);
+ if (!isSplit ? !queueHandle(ctx, prop, hnd) :
+ !queueHandleSplit(ctx, prop, hnd)) {
+ ALOGD_IF(isDebug(), "%s: Error in queue handle: layer:%d",
+ __FUNCTION__, i);
+ return false;
+ }
+ else {
+ ALOGD_IF(isDebug(), "%s: queue handle successful: hnd:0x%x "
+ "layer:%d", __FUNCTION__, (unsigned int) hnd, i);
+ }
+ }
+ }
+ return true;
+}
+
+int VPUClient::predraw(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ if (!ctx || !list) {
+ ALOGE("%s: invalid contxt or list",__FUNCTION__);
+ return -1;
+ }
+
+ if (ctx->listStats[display].numAppLayers > MAX_NUM_APP_LAYERS) {
+ ALOGE("%s: Exceeding max layer count", __FUNCTION__);
+ return -1;
+ }
+
+ // Although all the video layers are composed through VPU, but still need to
+ // queue the first buffer (blank screen) to mdp in order to initialize the
+ // settings
+ if (!drawDummyLayers(ctx, display, list)) {
+ ALOGE("%s: Failed to draw the first layer through overlay",
+ __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+
+int VPUClient::draw(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ LayerList *vpuList = vList[display];
+ vpuList->numLayers = list->numHwLayers;
+
+ for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ Layer *vLayer = &vpuList->layers[i];
+
+ // setting layer info again for the update content.
+ setLayer(layer, vLayer);
+ }
+
+ // queuing the buffer to VPU
+ if (mVPU->draw((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+ //error in vpu draw
+ ALOGE("%s: ERROR in VPU::draw", __func__);
+ return -1;
+ }
+
+ ALOGD_IF(isDebug2(), "%s: Done VFM draw", __FUNCTION__);
+
+ LayerProp *layerProp = ctx->layerProp[display];
+ // setting releaseFenceFd for the vpu layer
+ for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
+
+ VpuLayerProp* prop = &mProp[display][i];
+ if (!prop->vpuLayer)
+ continue;
+
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ Layer *vLayer = &vpuList->layers[i];
+
+ // TODO: Fix properly once the releaseFenceFd is implemented
+ layer->releaseFenceFd = vLayer->releaseFenceFd;
+ ALOGD_IF(isDebug(), "%s: releaseFd:%d for layer:%d", __FUNCTION__,
+ layer->releaseFenceFd, i);
+ }
+ return 0;
+}
+
+int VPUClient::getLayerIdx(int dpy, hwc_layer_1_t *layer)
+{
+ for (int i=0; i < MAX_NUM_APP_LAYERS; ++i) {
+ VpuLayerProp* prop = &mProp[dpy][i];
+
+ if (!prop->vpuLayer)
+ continue;
+
+ if (prop->layer == layer) {
+ ALOGD_IF(isDebug2(), "%s: OUT - dpy:%d", __FUNCTION__, dpy);
+ return i;
+ }
+ }
+ return -1;
+}
+
+int VPUClient::getLayerFormat(int dpy, hwc_layer_1_t *layer)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ int idx = -1;
+ if ((idx = getLayerIdx(dpy, layer)) == -1) {
+ ALOGE("%s: Layer not found!", __FUNCTION__);
+ return -1;
+ }
+
+ VpuLayerProp* prop = &mProp[dpy][idx];
+ ALOGD_IF(isDebug(), "%s: layer:%d format:0x%x", __FUNCTION__, idx,
+ (unsigned int) prop->format);
+
+ return prop->format;
+}
+
+int VPUClient::getWidth(int dpy, hwc_layer_1_t *layer)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ int idx = -1;
+ if ((idx = getLayerIdx(dpy, layer)) == -1) {
+ ALOGE("%s: Layer not found!", __FUNCTION__);
+ return -1;
+ }
+
+ VpuLayerProp* prop = &mProp[dpy][idx];
+ ALOGD_IF(isDebug(), "%s: layer:%d width:%d", __FUNCTION__, idx,
+ prop->width);
+
+ return prop->width;
+}
+
+int VPUClient::getHeight(int dpy, hwc_layer_1_t *layer)
+{
+ if (!mVPU) {
+ return -1;
+ }
+
+ int idx = -1;
+ if ((idx = getLayerIdx(dpy, layer)) == -1) {
+ ALOGE("%s: Layer not found!", __FUNCTION__);
+ return -1;
+ }
+
+ VpuLayerProp* prop = &mProp[dpy][idx];
+ ALOGD_IF(isDebug(), "%s: layer:%d height:%d", __FUNCTION__, idx,
+ prop->height);
+
+ return prop->height;
+}
+
+// TODO: getter function has side-effect. Need to cleanup
+void VPUClient::getPipeId(VpuLayerProp* prop, int &pipe)
+{
+ pipe = (prop->pipeCount == 1) ? (prop->pipeID[0]) : -1;
+}
+
+void VPUClient::getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe)
+{
+ lPipe = (prop->pipeCount == 2) ? (prop->pipeID[0]) : -1;
+ rPipe = (prop->pipeCount == 2) ? (prop->pipeID[1]) : -1;
+}
+
+int VPUClient::getDest(VpuLayerProp* prop, int pipenum)
+{
+ return (prop->pipeCount > 0) ? (prop->dest[pipenum]) : -1;
+}
+
+void VPUClient::setPipeCount(VpuLayerProp* prop, int count)
+{
+ prop->pipeCount = count;
+}
+
+void VPUClient::setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId)
+{
+ prop->pipeCount = 2;
+ prop->pipeID[0] = lPipeId;
+ prop->pipeID[1] = rPipeId;
+}
+
+void VPUClient::setPipeId(VpuLayerProp* prop, int pipeId)
+{
+ prop->pipeCount = 1;
+ prop->pipeID[0] = pipeId;
+}
+
+void VPUClient::setDest(VpuLayerProp* prop, int lDest, int rDest)
+{
+ prop->dest[0] = lDest;
+ prop->dest[1] = rDest;
+}
+
+void VPUClient::setDest(VpuLayerProp* prop, int dest)
+{
+ prop->dest[0] = dest;
+}
+
+bool VPUClient::supportedVPULayer(VpuLayerProp* prop)
+{
+ if (!prop->vpuLayer)
+ return false;
+
+ return true;
+}
+
+bool VPUClient::supportedVPULayer(int dpy, hwc_layer_1_t *layer)
+{
+ if (!mVPU) {
+ return false;
+ }
+
+ int idx = -1;
+ if ((idx = getLayerIdx(dpy, layer)) == -1) {
+ ALOGD_IF(isDebug(), "%s: Layer not found!", __FUNCTION__);
+ return false;
+ }
+ return true;
}
int VPUClient::processCommand(uint32_t command,
- const Parcel* inParcel, Parcel* outParcel)
+ const Parcel* inParcel, Parcel* outParcel)
{
- if(!mVPU)
+ if (!mVPU)
return 0;
- //XXX: Enable when VPU enables it
- //return mVPU->processCommand(command, inParcel, outParcel);
- return 0;
+
+ return mVPU->processCommand(command, inParcel, outParcel);
}
}; // namespace qhwc
diff --git a/libhwcomposer/hwc_vpuclient.h b/libhwcomposer/hwc_vpuclient.h
index 9985517..bb2a4b6 100644
--- a/libhwcomposer/hwc_vpuclient.h
+++ b/libhwcomposer/hwc_vpuclient.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-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
@@ -31,13 +31,20 @@
#define HWC_VPU_H
#include <sys/types.h>
+#include "hwc_utils.h"
+
+#define MAX_PIPES_PER_LAYER 2
//Forward declarations
struct hwc_display_contents_1;
typedef struct hwc_display_contents_1 hwc_display_contents_1_t;
+struct hwc_layer_1;
+typedef struct hwc_layer_1 hwc_layer_1_t;
struct hwc_context_t;
+
namespace vpu {
class VPU;
+struct LayerList;
};
namespace android {
class Parcel;
@@ -47,21 +54,91 @@
class VPUClient {
public:
- VPUClient();
+ VPUClient(hwc_context_t *ctx);
~VPUClient();
- int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
- int draw(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
+ int setupVpuSession(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list);
+ int prepare(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list);
+ int predraw(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list);
+ int draw(hwc_context_t *ctx, int display,
+ hwc_display_contents_1_t* list);
int processCommand(uint32_t command,
- const android::Parcel* inParcel, android::Parcel* outParcel);
+ const android::Parcel* inParcel, android::Parcel* outParcel);
+ int getLayerFormat(int dpy, hwc_layer_1_t *layer);
+ int getWidth(int dpy, hwc_layer_1_t *layer);
+ int getHeight(int dpy, hwc_layer_1_t *layer);
+ bool supportedVPULayer(int dpy, hwc_layer_1_t *layer);
private:
vpu::VPU *mVPU;
void* mVPULib;
+ /* VpuLayerProp struct:
+ * This struct corresponds to only one layer
+ * pipeCount: number of pipes required for a layer
+ * pipeID[]: pipe ids corresponding to the layer
+ */
+ struct VpuLayerProp {
+ int format;
+ int width;
+ int height;
+ int pipeCount;
+ bool vpuLayer;
+ bool firstBuffer;
+ hwc_frect_t sourceCropf;
+ hwc_layer_1_t *layer;
+ int pipeID[MAX_PIPES_PER_LAYER];
+ int dest[MAX_PIPES_PER_LAYER];
+ };
+ int mNumVpuLayers; /* total num of vpu supported layers */
+ int mGpuFallback; /* all layers are not supported by vpu */
+
+ VpuLayerProp mProp[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
+ int mDebugLogs;
+ private_handle_t *mHnd[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
+ vpu::LayerList *vList[HWC_NUM_DISPLAY_TYPES];
+
+ /* Private debug functions */
+ int32_t isDebug() { return (mDebugLogs >= 1); }
+ int32_t isDebug2() { return (mDebugLogs >= 2); }
+
+ /* Private Get/Set functions */
+ int getLayerIdx(int dpy, hwc_layer_1_t *layer);
+ void getPipeId(VpuLayerProp* prop, int &pipe);
+ void getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe);
+ int getDest(VpuLayerProp* prop, int pipenum);
+ void setPipeCount(VpuLayerProp* prop, int count);
+ void setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId);
+ void setPipeId(VpuLayerProp* prop, int pipeId);
+ void setDest(VpuLayerProp* prop, int lDest, int rDest);
+ void setDest(VpuLayerProp* prop, int dest);
+
+ /* Private implementations */
+ bool supportedVPULayer(VpuLayerProp* prop);
+ bool allocResLayerPipes(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool allocLayerPipes(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool configureLayers(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool configureLayersSplit(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ void setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool drawDummyLayers(hwc_context_t* ctx, int dpy,
+ hwc_display_contents_1_t* list);
+ bool queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
+ private_handle_t* hnd);
+ bool queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
+ private_handle_t* hnd);
}; // class VPU
}; // namespace qhwc
#endif /* end of include guard: HWC_VPU_H */
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 595b7f2..3729f21 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -30,6 +30,8 @@
#include "string.h"
#include "external.h"
#include "overlay.h"
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
namespace qhwc {
@@ -133,8 +135,8 @@
}
// send timestamp to SurfaceFlinger
ALOGD_IF (logvsync,
- "%s: timestamp %llu sent to SF for dpy=%d",
- __FUNCTION__, timestamp[dpy], dpy);
+ "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
+ __FUNCTION__, timestamp[dpy], dpy);
ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
}
}
diff --git a/liblight/lights.c b/liblight/lights.c
index ccfbe10..229777a 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 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.
@@ -115,6 +116,9 @@
{
int err = 0;
int brightness = rgb_to_brightness(state);
+ if(!dev) {
+ return -1;
+ }
pthread_mutex_lock(&g_lock);
err = write_int(LCD_FILE, brightness);
pthread_mutex_unlock(&g_lock);
@@ -125,12 +129,15 @@
set_speaker_light_locked(struct light_device_t* dev,
struct light_state_t const* state)
{
- int len;
- int alpha, red, green, blue;
+ int red, green, blue;
int blink;
int onMS, offMS;
unsigned int colorRGB;
+ if(!dev) {
+ return -1;
+ }
+
switch (state->flashMode) {
case LIGHT_FLASH_TIMED:
onMS = state->flashOnMS;
@@ -217,6 +224,9 @@
struct light_state_t const* state)
{
int err = 0;
+ if(!dev) {
+ return -1;
+ }
pthread_mutex_lock(&g_lock);
err = write_int(BUTTON_FILE, state->color & 0xFF);
pthread_mutex_unlock(&g_lock);
diff --git a/libmemtrack/memtrack_msm.c b/libmemtrack/memtrack_msm.c
index ac93f44..8adff96 100644
--- a/libmemtrack/memtrack_msm.c
+++ b/libmemtrack/memtrack_msm.c
@@ -22,6 +22,8 @@
int msm_memtrack_init(const struct memtrack_module *module)
{
+ if(!module)
+ return -1;
return 0;
}
@@ -31,6 +33,8 @@
struct memtrack_record *records,
size_t *num_records)
{
+ if(!module)
+ return -1;
if (type == MEMTRACK_TYPE_GL || type == MEMTRACK_TYPE_GRAPHICS) {
return kgsl_memtrack_get_memory(pid, type, records, num_records);
}
diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h
index d96317c..1bfa058 100644
--- a/liboverlay/mdpWrapper.h
+++ b/liboverlay/mdpWrapper.h
@@ -42,6 +42,8 @@
#include <errno.h>
#include "overlayUtils.h"
+#define IOCTL_DEBUG 0
+
namespace overlay{
namespace mdp_wrapper{
@@ -63,6 +65,9 @@
/* MSMFB_OVERLAY_SET */
bool setOverlay(int fd, mdp_overlay& ov);
+/* MSMFB_OVERLAY_PREPARE */
+bool validateAndSet(const int& fd, mdp_overlay_list& list);
+
/* MSM_ROTATOR_IOCTL_FINISH */
bool endRotator(int fd, int sessionId);
@@ -167,6 +172,15 @@
return true;
}
+inline bool validateAndSet(const int& fd, mdp_overlay_list& list) {
+ if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
+ ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
+ "err=%s", strerror(errno));
+ return false;
+ }
+ return true;
+}
+
inline bool endRotator(int fd, uint32_t sessionId) {
if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index ad23e84..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();
}
@@ -69,13 +70,6 @@
PipeBook::resetAllocation(i);
}
mDumpStr[0] = '\0';
-
-#ifdef USES_QSEED_SCALAR
- Scale *scalar = getScalar();
- if(scalar) {
- scalar->configBegin();
- }
-#endif
}
void Overlay::configDone() {
@@ -86,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();
@@ -98,13 +92,6 @@
}
dump();
PipeBook::save();
-
-#ifdef USES_QSEED_SCALAR
- Scale *scalar = getScalar();
- if(scalar) {
- scalar->configDone();
- }
-#endif
}
int Overlay::getPipeId(utils::eDest dest) {
@@ -160,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 {
@@ -410,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) {
@@ -435,6 +422,22 @@
}
}
+bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
+ GenericPipe* pipeArray[PipeBook::NUM_PIPES];
+ memset(&pipeArray, 0, sizeof(pipeArray));
+
+ int num = 0;
+ for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+ if(PipeBook::isUsed(i) && mPipeBook[i].valid() &&
+ mPipeBook[i].mDisplay == dpy) {
+ pipeArray[num++] = mPipeBook[i].mPipe;
+ }
+ }
+
+ //Protect against misbehaving clients
+ return num ? GenericPipe::validateAndSet(pipeArray, num, fbFd) : true;
+}
+
void Overlay::initScalar() {
#ifdef USES_QSEED_SCALAR
if(sLibScaleHandle == NULL) {
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index fe855c1..d8615cd 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -120,6 +120,8 @@
void getDump(char *buf, size_t len);
/* Reset usage and allocation bits on all pipes for given display */
void clear(int dpy);
+ /* Validate the set of pipes for a display and set them in driver */
+ bool validateAndSet(const int& dpy, const int& fbFd);
/* Closes open pipes, called during startup */
static int initOverlay();
@@ -131,8 +133,6 @@
static int getFbForDpy(const int& dpy);
static bool displayCommit(const int& fd, const utils::Dim& roi);
static bool displayCommit(const int& fd);
- /* Returns the scalar object */
- static scale::Scale *getScalar();
private:
/* Ctor setup */
@@ -141,6 +141,8 @@
void validate(int index);
static void setDMAMultiplexingSupported();
void dump() const;
+ /* Returns the scalar object */
+ static scale::Scale *getScalar();
/* Creates a scalar object using libscale.so */
static void initScalar();
/* Destroys the scalar object using libscale.so */
@@ -212,6 +214,8 @@
static bool sDMAMultiplexingSupported;
static void *sLibScaleHandle;
static scale::Scale *sScale;
+
+ friend class MdpCtrl;
};
inline void Overlay::validate(int index) {
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index dbf328a..26202ec 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -84,6 +84,8 @@
/* Return the dump in the specified buffer */
void getDump(char *buf, size_t len);
+ static bool validateAndSet(Ctrl* ctrlArray[], const int& count,
+ const int& fbFd);
private:
// mdp ctrl struct(info e.g.)
MdpCtrl *mMdp;
@@ -181,6 +183,19 @@
mMdp->updateSrcFormat(rotDstFmt);
}
+inline bool Ctrl::validateAndSet(Ctrl* ctrlArray[], const int& count,
+ const int& fbFd) {
+ MdpCtrl* mdpCtrlArray[count];
+ memset(&mdpCtrlArray, 0, sizeof(mdpCtrlArray));
+
+ for(int i = 0; i < count; i++) {
+ mdpCtrlArray[i] = ctrlArray[i]->mMdp;
+ }
+
+ bool ret = MdpCtrl::validateAndSet(mdpCtrlArray, count, fbFd);
+ return ret;
+}
+
inline utils::Dim Ctrl::getCrop() const {
return mMdp->getSrcRectDim();
}
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index b278ce4..a25dc5e 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
-* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+* Copyright (c) 2010-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.
@@ -206,35 +206,6 @@
}
doDownscale();
-
- if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
- ALOGE("MdpCtrl failed to setOverlay");
- mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
-#ifdef USES_QSEED_SCALAR
- if(Overlay::getScalar()) {
- Overlay::getScalar()->configAbort(mDpy);
- }
-#endif
- return false;
- }
-
-#ifdef USES_QSEED_SCALAR
- if(Overlay::getScalar()) {
- Overlay::getScalar()->configSet(mOVInfo, mDpy, mFd.getFD());
- }
-#endif
-
- return true;
-}
-
-bool MdpCtrl::get() {
- mdp_overlay ov;
- ov.id = mOVInfo.id;
- if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) {
- ALOGE("MdpCtrl get failed");
- return false;
- }
- mOVInfo = ov;
return true;
}
@@ -274,8 +245,9 @@
}
bool MdpCtrl::setVisualParams(const MetaData_t& data) {
- bool needUpdate = false;
+ ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
#ifdef USES_POST_PROCESSING
+ bool needUpdate = false;
/* calculate the data */
if (data.operation & PP_PARAM_HSIC) {
if (mParams.params.pa_params.hue != data.hsicData.hue) {
@@ -388,6 +360,38 @@
return true;
}
+bool MdpCtrl::validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+ const int& fbFd) {
+ mdp_overlay* ovArray[count];
+ memset(&ovArray, 0, sizeof(ovArray));
+
+ for(int i = 0; i < count; i++) {
+ ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+ }
+
+ struct mdp_overlay_list list;
+ memset(&list, 0, sizeof(struct mdp_overlay_list));
+ list.num_overlays = count;
+ list.overlay_list = ovArray;
+
+#ifdef USES_QSEED_SCALAR
+ Scale *scalar = Overlay::getScalar();
+ if(scalar) {
+ scalar->applyScale(&list);
+ }
+#endif
+
+ if(!mdp_wrapper::validateAndSet(fbFd, list)) {
+ if(list.processed_overlays < list.num_overlays) {
+ mdp_wrapper::dump("Bad ov dump: ",
+ *list.overlay_list[list.processed_overlays]);
+ }
+ return false;
+ }
+
+ return true;
+}
+
//// MdpData ////////////
bool MdpData::init(const int& dpy) {
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index daaeaf2..843556b 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -72,7 +72,6 @@
void dump() const;
/* Return the dump in the specified buffer */
void getDump(char *buf, size_t len);
-
/* returns session id */
int getPipeId() const;
/* returns the fd associated to ctrl*/
@@ -84,14 +83,14 @@
/* setVisualParam */
bool setVisualParams(const MetaData_t& data);
+ static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+ const int& fbFd);
private:
/* Perform transformation calculations */
void doTransform();
void doDownscale();
/* get orient / user_data[0] */
- int getOrient() const;
- /* overlay get */
- bool get();
+ int getOrient() const;
/* returns flags from mdp structure */
int getFlags() const;
/* set flags to mdp structure */
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index ce2ef5b..38b0a92 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
*
@@ -94,7 +94,7 @@
mRotImgInfo.dst.height = whf.h;
}
-void MdpRot::setCrop(const utils::Dim& crop) {
+void MdpRot::setCrop(const utils::Dim& /*crop*/) {
// NO-OP for non-mdss rotator due to possible h/w limitations
}
@@ -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 c6d5332..ce9d9d5 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
*
@@ -92,7 +92,8 @@
mRotInfo.dst_rect.h = crop.h;
}
-void MdssRot::setDownscale(int ds) {}
+void MdssRot::setDownscale(int /*ds*/) {
+}
void MdssRot::setFlags(const utils::eMdpFlags& flags) {
mRotInfo.flags = flags;
@@ -133,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;
}
@@ -178,7 +170,7 @@
mRotData.dst_data.memory_id = mem.getFD();
mRotData.dst_data.offset = 0;
- mMem.curr().m = mem;
+ mMem.mem = mem;
return true;
}
@@ -186,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;
}
@@ -233,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 30de1db..41efc48 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-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
@@ -417,7 +417,7 @@
"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);
@@ -430,7 +430,7 @@
"%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,
@@ -439,7 +439,7 @@
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,7 +448,7 @@
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);
}
@@ -458,7 +458,7 @@
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 +467,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 +479,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 33802e5..400d96a 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-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
@@ -272,6 +272,7 @@
OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+ OV_MDP_VPU_PIPE = MDP_VPU_PIPE,
};
enum eZorder {
@@ -423,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 )
{
@@ -815,7 +816,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/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index 394a56e..9e57223 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -137,4 +137,16 @@
return mCtrl->getPipeId();
}
+bool GenericPipe::validateAndSet(GenericPipe* pipeArray[], const int& count,
+ const int& fbFd) {
+ Ctrl* ctrlArray[count];
+ memset(&ctrlArray, 0, sizeof(ctrlArray));
+
+ for(int i = 0; i < count; i++) {
+ ctrlArray[i] = pipeArray[i]->mCtrl;
+ }
+
+ return Ctrl::validateAndSet(ctrlArray, count, fbFd);
+}
+
} //namespace overlay
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index 57e1758..813a2b3 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -75,6 +75,8 @@
void getDump(char *buf, size_t len);
int getPipeId();
+ static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
+ const int& fbFd);
private:
/* set Closed pipe */
bool setClosed();
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 45b0211..60f1f68 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-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
@@ -37,7 +37,7 @@
int isExternalConnected(void) {
int ret;
- status_t err = FAILED_TRANSACTION;
+ status_t err = (status_t) FAILED_TRANSACTION;
sp<IQService> binder = getBinder();
Parcel inParcel, outParcel;
if(binder != NULL) {
@@ -54,7 +54,7 @@
}
int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
- status_t err = FAILED_TRANSACTION;
+ status_t err = (status_t) FAILED_TRANSACTION;
sp<IQService> binder = getBinder();
Parcel inParcel, outParcel;
inParcel.writeInt32(dpy);
@@ -76,7 +76,7 @@
}
int setHSIC(int dpy, const HSICData_t& hsic_data) {
- status_t err = FAILED_TRANSACTION;
+ status_t err = (status_t) FAILED_TRANSACTION;
sp<IQService> binder = getBinder();
Parcel inParcel, outParcel;
inParcel.writeInt32(dpy);
@@ -93,7 +93,7 @@
}
int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
- status_t err = FAILED_TRANSACTION;
+ status_t err = (status_t) FAILED_TRANSACTION;
sp<IQService> binder = getBinder();
Parcel inParcel, outParcel;
inParcel.writeInt32(dpy);
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index b743d7a..c341dfa 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -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
@@ -99,7 +99,7 @@
char* tokenStr[], int *idx) {
char *tmp_token = NULL;
char *temp_ptr;
- int ret = 0, index = 0;
+ int index = 0;
if (!inputParams) {
return -1;
}
@@ -149,7 +149,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 +172,7 @@
__FUNCTION__, sysfsPath);
return false;
} else {
+ line = (char *) malloc(len);
while((read = getline(&line, &len, sysfsFd)) != -1) {
int index=0;
char *tokens[10];
@@ -221,9 +222,8 @@
}
}
}
- free(line);
- line = NULL;
}
+ free(line);
fclose(sysfsFd);
}
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
@@ -246,6 +246,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, " ");
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index f39eef9..ecbf873 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -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
@@ -31,6 +31,8 @@
#include <sys/mman.h>
#include <cutils/log.h>
#include <gralloc_priv.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
#include "qdMetaData.h"
int setMetaData(private_handle_t *handle, DispParamType paramType,
@@ -106,7 +108,7 @@
break;
}
if(munmap(base, size))
- ALOGE("%s: failed to unmap ptr 0x%x, err %d", __func__, (int)base,
+ ALOGE("%s: failed to unmap ptr 0x%"PRIdPTR", err %d", __func__, (intptr_t)base,
errno);
return 0;
}
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 5a457d0..0698b33 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -31,7 +31,6 @@
#define MAX_FRAME_BUFFER_NAME_SIZE (80)
-#define MAX_DISPLAY_DEVICES (3)
int getHDMINode(void)
{
@@ -40,7 +39,7 @@
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int j = 0;
- for(j = 0; j < MAX_DISPLAY_DEVICES; j++) {
+ for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
snprintf (msmFbTypePath, sizeof(msmFbTypePath),
"/sys/class/graphics/fb%d/msm_fb_type", j);
displayDeviceFP = fopen(msmFbTypePath, "r");
@@ -58,7 +57,7 @@
}
}
- if (j < MAX_DISPLAY_DEVICES)
+ if (j < HWC_NUM_DISPLAY_TYPES)
return j;
else
ALOGE("%s: Failed to find HDMI node", __func__);
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index cca55d5..db6d367 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -42,6 +42,7 @@
#include <sys/poll.h>
#include <sys/resource.h>
#include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
#define EDID_RAW_DATA_SIZE 640
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index d2180bb..f0d7576 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -55,7 +55,7 @@
virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel);
- status_t err = android::FAILED_TRANSACTION;
+ status_t err = (status_t) android::FAILED_TRANSACTION;
Parcel data;
Parcel *reply = outParcel;
data.writeInterfaceToken(IQService::getInterfaceDescriptor());
@@ -80,7 +80,7 @@
IPCThreadState* ipc = IPCThreadState::self();
const int callerPid = ipc->getCallingPid();
const int callerUid = ipc->getCallingUid();
- const size_t MAX_BUF_SIZE = 1024;
+ const int MAX_BUF_SIZE = 1024;
char callingProcName[MAX_BUF_SIZE] = {0};
getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
@@ -123,7 +123,7 @@
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;
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index aac5788..e4af422 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -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
@@ -54,7 +54,7 @@
status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
- status_t err = FAILED_TRANSACTION;
+ status_t err = (status_t) FAILED_TRANSACTION;
if (mClient.get()) {
ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
err = mClient->notifyCallback(command, inParcel, outParcel);
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index 2817429..699164d 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -49,7 +49,7 @@
}
inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
- android::status_t err = android::FAILED_TRANSACTION;
+ android::status_t err = (android::status_t) android::FAILED_TRANSACTION;
android::sp<qService::IQService> binder = getBinder();
android::Parcel inParcel, outParcel;
inParcel.writeInt32(value);
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) {