Merge "libgralloc: Add support for custom buffer size."
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index 55d421b..73bfa86 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 The Android Open Source Project
+# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index b9abc31..1a41775 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -86,9 +86,16 @@
if(mFd == -1)
return -1;
readResolution();
- //Get the best mode and set
// TODO: Move this to activate
- setResolution(getBestMode());
+ /* Used for changing the resolution
+ * getUserMode will get the preferred
+ * mode set thru adb shell */
+ int mode = getUserMode();
+ if (mode == -1) {
+ //Get the best mode and set
+ mode = getBestMode();
+ }
+ setResolution(mode);
setDpyHdmiAttr();
setExternalDisplay(true, mHdmiFbNum);
return 0;
@@ -385,6 +392,8 @@
int ExternalDisplay::getModeOrder(int mode)
{
+ // XXX: We dont support interlaced modes but having
+ // it here for for future
switch (mode) {
default:
case m1440x480i60_4_3:
@@ -424,6 +433,20 @@
}
}
+/// Returns the user mode set(if any) using adb shell
+int ExternalDisplay::getUserMode() {
+ /* Based on the property set the resolution */
+ char property_value[PROPERTY_VALUE_MAX];
+ property_get("hdmi.resolution", property_value, "-1");
+ int mode = atoi(property_value);
+ // We dont support interlaced modes
+ if(isValidMode(mode) && !isInterlacedMode(mode)) {
+ ALOGD_IF("%s: setting the HDMI mode = %d", __FUNCTION__, mode);
+ return mode;
+ }
+ return -1;
+}
+
// Get the best mode for the current HD TV
int ExternalDisplay::getBestMode() {
int bestOrder = 0;
@@ -443,7 +466,30 @@
inline bool ExternalDisplay::isValidMode(int ID)
{
- return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
+ bool valid = false;
+ for (int i = 0; i < mModeCount; i++) {
+ if(ID == mEDIDModes[i]) {
+ valid = true;
+ break;
+ }
+ }
+ return valid;
+}
+
+// returns true if the mode(ID) is interlaced mode format
+bool ExternalDisplay::isInterlacedMode(int ID) {
+ bool interlaced = false;
+ switch(ID) {
+ case m1440x480i60_4_3:
+ case m1440x480i60_16_9:
+ case m1440x576i50_4_3:
+ case m1440x576i50_16_9:
+ case m1920x1080i60_16_9:
+ interlaced = true;
+ default:
+ interlaced = false;
+ }
+ return interlaced;
}
void ExternalDisplay::setResolution(int ID)
@@ -462,7 +508,7 @@
mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
mVInfo.pixclock/1000/1000);
- //If its a valid mode and its a new ID - update var_screeninfo
+ //If its a new ID - update var_screeninfo
if ((isValidMode(ID)) && mCurrentMode != ID) {
const struct disp_mode_timing_type *mode =
&supported_video_mode_lut[0];
diff --git a/libexternal/external.h b/libexternal/external.h
index 46c982d..d85ce44 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -55,7 +55,9 @@
bool isValidMode(int ID);
void handleUEvent(char* str, int len);
int getModeOrder(int mode);
+ int getUserMode();
int getBestMode();
+ bool isInterlacedMode(int mode);
void resetInfo();
void setDpyHdmiAttr();
void setDpyWfdAttr();
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 823c1ae..669ea08 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -235,6 +235,11 @@
alignedh = height;
size = ALIGN(alignedw * alignedh * 2, 4096);
break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ alignedw = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+ alignedh = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
+ size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+ break;
default:
ALOGE("unrecognized pixel format: 0x%x", format);
return -EINVAL;
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 92e7193..f11a5fe 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -27,6 +27,7 @@
#include "gpu.h"
#include "memalloc.h"
#include "alloc_controller.h"
+#include <qdMetaData.h>
using namespace gralloc;
@@ -138,37 +139,52 @@
data.pHandle = (unsigned int) pHandle;
err = mAllocCtrl->allocate(data, usage);
- if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
- flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
- }
+ if (!err) {
+ /* allocate memory for enhancement data */
+ alloc_data eData;
+ eData.fd = -1;
+ eData.base = 0;
+ eData.offset = 0;
+ eData.size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ eData.pHandle = data.pHandle;
+ eData.align = getpagesize();
+ int eDataUsage = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+ int eDataErr = mAllocCtrl->allocate(eData, eDataUsage);
+ ALOGE_IF(eDataErr, "gralloc failed for eDataErr=%s",
+ strerror(-eDataErr));
- if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
- flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
- //The EXTERNAL_BLOCK flag is always an add-on
- if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
- flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
- }if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
- flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
+ if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
+ flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
}
- }
- if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
- flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
- }
+ if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
+ flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+ //The EXTERNAL_BLOCK flag is always an add-on
+ if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
+ flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
+ }
+ if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
+ flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
+ }
+ }
- if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
- flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
- }
+ if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
+ flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+ }
- if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
- flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
- }
+ if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+ flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+ }
- if (err == 0) {
+ if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
+ flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+ }
+
flags |= data.allocType;
- private_handle_t* hnd = new private_handle_t(data.fd, size, flags,
- bufferType, format, width,
- height);
+ int eBaseAddr = int(eData.base) + eData.offset;
+ private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
+ bufferType, format, width, height, eData.fd, eData.offset,
+ eBaseAddr);
hnd->offset = data.offset;
hnd->base = int(data.base) + data.offset;
@@ -176,6 +192,7 @@
}
ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+
return err;
}
@@ -262,6 +279,13 @@
hnd->offset, hnd->fd);
if(err)
return err;
+ // free the metadata space
+ unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ err = memalloc->free_buffer((void*)hnd->base_metadata,
+ (size_t) size, hnd->offset_metadata,
+ hnd->fd_metadata);
+ if (err)
+ return err;
}
// Release the genlock
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 59fbd30..6ccc7e0 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -30,6 +30,9 @@
#include <cutils/log.h>
+#define ROUND_UP_PAGESIZE(x) ( (((unsigned long)(x)) + PAGE_SIZE-1) & \
+ (~(PAGE_SIZE-1)) )
+
enum {
/* gralloc usage bits indicating the type
* of allocation that should be used */
@@ -96,6 +99,7 @@
enum {
/* OEM specific HAL formats */
HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
+ HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS = 0x7FA30C04,
HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x7FA30C03,
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01,
@@ -166,6 +170,7 @@
int fd;
// genlock handle to be dup'd by the binder
int genlockHandle;
+ int fd_metadata; // fd for the meta-data
// ints
int magic;
int flags;
@@ -173,6 +178,7 @@
int offset;
int bufferType;
int base;
+ int offset_metadata;
// The gpu address mapped into the mmu.
// If using ashmem, set to 0, they don't care
int gpuaddr;
@@ -182,19 +188,21 @@
int height;
// local fd of the genlock device.
int genlockPrivFd;
+ int base_metadata;
#ifdef __cplusplus
- static const int sNumInts = 12;
- static const int sNumFds = 2;
+ static const int sNumInts = 14;
+ static const int sNumFds = 3;
static const int sMagic = 'gmsm';
private_handle_t(int fd, int size, int flags, int bufferType,
- int format,int width, int height) :
- fd(fd), genlockHandle(-1), magic(sMagic),
- flags(flags), size(size), offset(0),
- bufferType(bufferType), base(0), gpuaddr(0),
- pid(0), format(format),
- width(width), height(height), genlockPrivFd(-1)
+ int format,int width, int height, int eFd = -1,
+ int eOffset = 0, int eBase = 0) :
+ fd(fd), genlockHandle(-1), fd_metadata(eFd), magic(sMagic),
+ flags(flags), size(size), offset(0), bufferType(bufferType),
+ base(0), offset_metadata(eOffset), gpuaddr(0), pid(getpid()),
+ format(format), width(width), height(height), genlockPrivFd(-1),
+ base_metadata(eBase)
{
version = sizeof(native_handle);
numInts = sNumInts;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 3088ecc..176a84e 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -42,6 +42,7 @@
#include "gr.h"
#include "alloc_controller.h"
#include "memalloc.h"
+#include <qdMetaData.h>
using namespace gralloc;
/*****************************************************************************/
@@ -68,22 +69,27 @@
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
int err = memalloc->map_buffer(&mappedAddress, size,
hnd->offset, hnd->fd);
- if(err) {
+ if(err || mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap handle %p, fd=%d (%s)",
handle, hnd->fd, strerror(errno));
hnd->base = 0;
return -errno;
}
- if (mappedAddress == MAP_FAILED) {
- ALOGE("Could not mmap handle %p, fd=%d (%s)",
- handle, hnd->fd, strerror(errno));
- hnd->base = 0;
- return -errno;
- }
hnd->base = intptr_t(mappedAddress) + hnd->offset;
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
+ mappedAddress = MAP_FAILED;
+ size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ err = memalloc->map_buffer(&mappedAddress, size,
+ hnd->offset_metadata, hnd->fd_metadata);
+ if(err || mappedAddress == MAP_FAILED) {
+ ALOGE("Could not mmap handle %p, fd=%d (%s)",
+ handle, hnd->fd_metadata, strerror(errno));
+ hnd->base_metadata = 0;
+ return -errno;
+ }
+ hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
}
*vaddr = (void*)hnd->base;
return 0;
@@ -98,10 +104,17 @@
void* base = (void*)hnd->base;
size_t size = hnd->size;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
- if(memalloc != NULL)
+ if(memalloc != NULL) {
err = memalloc->unmap_buffer(base, size, hnd->offset);
- if (err) {
- ALOGE("Could not unmap memory at address %p", base);
+ if (err) {
+ ALOGE("Could not unmap memory at address %p", base);
+ }
+ base = (void*)hnd->base_metadata;
+ size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
+ if (err) {
+ ALOGE("Could not unmap memory at address %p", base);
+ }
}
}
hnd->base = 0;
@@ -277,6 +290,12 @@
hnd->size, hnd->offset, hnd->fd);
ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
+ unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ err = memalloc->clean_buffer((void*)hnd->base_metadata, size,
+ hnd->offset_metadata, hnd->fd_metadata);
+ ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%lu, "
+ "flags = 0x%x) err=%s\n", hnd, hnd->offset_metadata, size,
+ hnd->flags, strerror(errno));
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
}
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index a0a0c82..ac1be19 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.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-2013, 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.
@@ -93,9 +93,11 @@
list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
}
}
+
+ if(ctx->mFBUpdate[i])
+ ctx->mFBUpdate[i]->reset();
}
VideoOverlay::reset();
- FBUpdate::reset();
}
//clear prev layer prop flags and realloc for current frame
@@ -115,20 +117,21 @@
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ const int dpy = HWC_DISPLAY_PRIMARY;
if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+ ctx->dpyAttr[dpy].isActive) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(fbLayer->handle) {
- setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
- reset_layer_prop(ctx, HWC_DISPLAY_PRIMARY);
- if(!MDPComp::configure(ctx, list)) {
- VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY);
- FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_PRIMARY);
+ setListStats(ctx, list, dpy);
+ reset_layer_prop(ctx, dpy);
+ if(!ctx->mMDPComp->prepare(ctx, list)) {
+ VideoOverlay::prepare(ctx, list, dpy);
+ ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
}
- ctx->mLayerCache[HWC_DISPLAY_PRIMARY]->updateLayerCache(list);
+ ctx->mLayerCache[dpy]->updateLayerCache(list);
}
}
return 0;
@@ -137,20 +140,21 @@
static int hwc_prepare_external(hwc_composer_device_1 *dev,
hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ const int dpy = HWC_DISPLAY_EXTERNAL;
if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+ ctx->dpyAttr[dpy].isActive &&
+ ctx->dpyAttr[dpy].connected) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(fbLayer->handle) {
- setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
- reset_layer_prop(ctx, HWC_DISPLAY_EXTERNAL);
-
- VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL);
- FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_EXTERNAL);
- ctx->mLayerCache[HWC_DISPLAY_EXTERNAL]->updateLayerCache(list);
+ setListStats(ctx, list, dpy);
+ reset_layer_prop(ctx, dpy);
+ VideoOverlay::prepare(ctx, list, dpy);
+ ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+ ctx->mLayerCache[dpy]->updateLayerCache(list);
+ ctx->mExtDispConfiguring = false;
}
}
return 0;
@@ -173,15 +177,14 @@
ret = hwc_prepare_primary(dev, list);
break;
case HWC_DISPLAY_EXTERNAL:
-
ret = hwc_prepare_external(dev, list);
break;
default:
ret = -EINVAL;
}
}
- ctx->mOverlay->configDone();
+ ctx->mOverlay->configDone();
return ret;
}
@@ -230,7 +233,12 @@
break;
case HWC_DISPLAY_EXTERNAL:
if(blank) {
- //TODO actual
+ // External Display post commits the changes to display
+ // Call this on blank, so that any pipe unsets gets committed
+ if (!ctx->mExtDisplay->post()) {
+ ret = -1;
+ ALOGE("%s:ctx->mExtDisplay->post fail!! ", __FUNCTION__);
+ }
} else {
}
break;
@@ -282,18 +290,19 @@
static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
int ret = 0;
+ const int dpy = HWC_DISPLAY_PRIMARY;
if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+ ctx->dpyAttr[dpy].isActive) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
- if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY)) {
+ hwc_sync(ctx, list, dpy);
+ if (!VideoOverlay::draw(ctx, list, dpy)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
ret = -1;
}
- if (!MDPComp::draw(ctx, list)) {
+ if (!ctx->mMDPComp->draw(ctx, list)) {
ALOGE("%s: MDPComp::draw fail!", __FUNCTION__);
ret = -1;
}
@@ -303,7 +312,7 @@
private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
- if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_PRIMARY)) {
+ if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
}
@@ -320,17 +329,19 @@
static int hwc_set_external(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
int ret = 0;
+ const int dpy = HWC_DISPLAY_EXTERNAL;
+
Locker::Autolock _l(ctx->mExtSetLock);
if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
- ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+ ctx->dpyAttr[dpy].isActive &&
+ ctx->dpyAttr[dpy].connected) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+ hwc_sync(ctx, list, dpy);
- if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL)) {
+ if (!VideoOverlay::draw(ctx, list, dpy)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
ret = -1;
}
@@ -338,7 +349,7 @@
private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
!(fbLayer->flags & HWC_SKIP_LAYER) && hnd) {
- if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_EXTERNAL)) {
+ if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
}
@@ -462,7 +473,7 @@
dumpsys_log(buf, "Qualcomm HWC state:\n");
dumpsys_log(buf, " MDPVersion=%d\n", ctx->mMDP.version);
dumpsys_log(buf, " DisplayPanel=%c\n", ctx->mMDP.panel);
- MDPComp::dump(buf);
+ ctx->mMDPComp->dump(buf);
//XXX: Call Other dump functions
strlcpy(buff, buf.string(), buff_len);
}
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 0d0787e..ecbf813 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -18,7 +18,7 @@
* limitations under the License.
*/
-#define HWC_FB_UPDATE 0
+#define DEBUG_FBUPDATE 0
#include <gralloc_priv.h>
#include <fb_priv.h>
#include "hwc_fbupdate.h"
@@ -28,30 +28,38 @@
namespace ovutils = overlay::utils;
-//Static Members
-bool FBUpdate::sModeOn[] = {false};
-ovutils::eDest FBUpdate::sDest[] = {ovutils::OV_INVALID};
-
-void FBUpdate::reset() {
- sModeOn[HWC_DISPLAY_PRIMARY] = false;
- sModeOn[HWC_DISPLAY_EXTERNAL] = false;
- sDest[HWC_DISPLAY_PRIMARY] = ovutils::OV_INVALID;
- sDest[HWC_DISPLAY_EXTERNAL] = ovutils::OV_INVALID;
+IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) {
+ if(width > MAX_DISPLAY_DIM) {
+ return new FBUpdateHighRes(dpy);
+ }
+ return new FBUpdateLowRes(dpy);
}
-bool FBUpdate::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy) {
+inline void IFBUpdate::reset() {
+ mModeOn = false;
+}
+
+//================= Low res====================================
+FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
+
+inline void FBUpdateLowRes::reset() {
+ IFBUpdate::reset();
+ mDest = ovutils::OV_INVALID;
+}
+
+bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
if(!ctx->mMDP.hasOverlay) {
- ALOGD_IF(HWC_FB_UPDATE, "%s, this hw doesnt support mirroring",
+ ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
-
- return (sModeOn[dpy] = configure(ctx, fblayer, dpy));
-
+ mModeOn = configure(ctx, fblayer);
+ ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
+ return mModeOn;
}
// Configure
-bool FBUpdate::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy)
+bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
{
bool ret = false;
if (LIKELY(ctx->mOverlay)) {
@@ -64,12 +72,12 @@
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
//Request an RGB pipe
- ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
+ ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
if(dest == ovutils::OV_INVALID) { //None available
return false;
}
- sDest[dpy] = dest;
+ mDest = dest;
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
if(ctx->mSecureMode) {
@@ -112,14 +120,14 @@
return ret;
}
-bool FBUpdate::draw(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy)
+bool FBUpdateLowRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
{
- if(!sModeOn[dpy]) {
+ if(!mModeOn) {
return true;
}
bool ret = true;
overlay::Overlay& ov = *(ctx->mOverlay);
- ovutils::eDest dest = sDest[dpy];
+ ovutils::eDest dest = mDest;
private_handle_t *hnd = (private_handle_t *)layer->handle;
if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
@@ -128,5 +136,138 @@
return ret;
}
+//================= High res====================================
+FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
+
+inline void FBUpdateHighRes::reset() {
+ IFBUpdate::reset();
+ mDestLeft = ovutils::OV_INVALID;
+ mDestRight = ovutils::OV_INVALID;
+}
+
+bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+ if(!ctx->mMDP.hasOverlay) {
+ ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
+ __FUNCTION__);
+ return false;
+ }
+ ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
+ mModeOn = configure(ctx, fblayer);
+ return mModeOn;
+}
+
+// Configure
+bool FBUpdateHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+{
+ bool ret = false;
+ if (LIKELY(ctx->mOverlay)) {
+ overlay::Overlay& ov = *(ctx->mOverlay);
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if (!hnd) {
+ ALOGE("%s:NULL private handle for layer!", __FUNCTION__);
+ return false;
+ }
+ ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+
+ //Request left RGB pipe
+ ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+ if(destL == ovutils::OV_INVALID) { //None available
+ return false;
+ }
+ //Request right RGB pipe
+ ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+ if(destR == ovutils::OV_INVALID) { //None available
+ return false;
+ }
+
+ mDestLeft = destL;
+ mDestRight = destR;
+
+ ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
+ if(ctx->mSecureMode) {
+ ovutils::setMdpFlags(mdpFlagsL,
+ ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+ }
+
+ ovutils::PipeArgs pargL(mdpFlagsL,
+ info,
+ ovutils::ZORDER_0,
+ ovutils::IS_FG_SET,
+ ovutils::ROT_FLAG_DISABLED);
+ ov.setSource(pargL, destL);
+
+ ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
+ ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
+ ovutils::PipeArgs pargR(mdpFlagsR,
+ info,
+ ovutils::ZORDER_0,
+ ovutils::IS_FG_SET,
+ ovutils::ROT_FLAG_DISABLED);
+ ov.setSource(pargR, destR);
+
+ hwc_rect_t sourceCrop = layer->sourceCrop;
+ ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
+ (sourceCrop.right - sourceCrop.left) / 2,
+ sourceCrop.bottom - sourceCrop.top);
+ ovutils::Dim dcropR(
+ sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2,
+ sourceCrop.top,
+ (sourceCrop.right - sourceCrop.left) / 2,
+ sourceCrop.bottom - sourceCrop.top);
+ ov.setCrop(dcropL, destL);
+ ov.setCrop(dcropR, destR);
+
+ int transform = layer->transform;
+ ovutils::eTransform orient =
+ static_cast<ovutils::eTransform>(transform);
+ ov.setTransform(orient, destL);
+ ov.setTransform(orient, destR);
+
+ hwc_rect_t displayFrame = layer->displayFrame;
+ //For FB left, top will always be 0
+ //That should also be the case if using 2 mixers for single display
+ ovutils::Dim dpos(displayFrame.left,
+ displayFrame.top,
+ (displayFrame.right - displayFrame.left) / 2,
+ displayFrame.bottom - displayFrame.top);
+ ov.setPosition(dpos, destL);
+ ov.setPosition(dpos, destR);
+
+ ret = true;
+ if (!ov.commit(destL)) {
+ ALOGE("%s: commit fails for left", __FUNCTION__);
+ ret = false;
+ }
+ if (!ov.commit(destR)) {
+ ALOGE("%s: commit fails for right", __FUNCTION__);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+bool FBUpdateHighRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+{
+ if(!mModeOn) {
+ return true;
+ }
+ bool ret = true;
+ overlay::Overlay& ov = *(ctx->mOverlay);
+ ovutils::eDest destL = mDestLeft;
+ ovutils::eDest destR = mDestRight;
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
+ ALOGE("%s: queue failed for left of dpy = %d",
+ __FUNCTION__, mDpy);
+ ret = false;
+ }
+ if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
+ ALOGE("%s: queue failed for right of dpy = %d",
+ __FUNCTION__, mDpy);
+ ret = false;
+ }
+ return ret;
+}
+
//---------------------------------------------------------------------
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 708eb6f..a30a3af 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -28,22 +28,50 @@
namespace qhwc {
namespace ovutils = overlay::utils;
-//Framebuffer update
-class FBUpdate {
- public:
- // Sets up members and prepares overlay if conditions are met
- static bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy);
- // Draws layer if this feature is on
- static bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy);
- //Reset values
- static void reset();
- private:
- //Configures overlay
- static bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer,
- int dpy);
- //Flags if this feature is on.
- static bool sModeOn[HWC_NUM_DISPLAY_TYPES];
- static ovutils::eDest sDest[HWC_NUM_DISPLAY_TYPES];
+//Framebuffer update Interface
+class IFBUpdate {
+public:
+ explicit IFBUpdate(const int& dpy) : mDpy(dpy) {}
+ virtual ~IFBUpdate() {};
+ // Sets up members and prepares overlay if conditions are met
+ virtual bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+ // Draws layer
+ virtual bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+ //Reset values
+ virtual void reset();
+ //Factory method that returns a low-res or high-res version
+ static IFBUpdate *getObject(const int& width, const int& dpy);
+
+protected:
+ const int mDpy; // display to update
+ bool mModeOn; // if prepare happened
+};
+
+//Low resolution (<= 2048) panel handler.
+class FBUpdateLowRes : public IFBUpdate {
+public:
+ explicit FBUpdateLowRes(const int& dpy);
+ virtual ~FBUpdateLowRes() {};
+ bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ void reset();
+private:
+ bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ ovutils::eDest mDest; //pipe to draw on
+};
+
+//High resolution (> 2048) panel handler.
+class FBUpdateHighRes : public IFBUpdate {
+public:
+ explicit FBUpdateHighRes(const int& dpy);
+ virtual ~FBUpdateHighRes() {};
+ bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ void reset();
+private:
+ bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ ovutils::eDest mDestLeft; //left pipe to draw on
+ ovutils::eDest mDestRight; //right pipe to draw on
};
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 4200be9..2c0a77a 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -19,32 +19,74 @@
#include "hwc_mdpcomp.h"
#include <sys/ioctl.h>
#include "external.h"
+#include "qdMetaData.h"
namespace qhwc {
namespace ovutils = overlay::utils;
-/****** Class MDPComp ***********/
-MDPComp::eState MDPComp::sMDPCompState = MDPCOMP_OFF;
-struct MDPComp::FrameInfo MDPComp::sCurrentFrame;
+//==============MDPComp========================================================
+
IdleInvalidator *MDPComp::idleInvalidator = NULL;
bool MDPComp::sIdleFallBack = false;
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
-int MDPComp::sActiveMax = 0;
-bool MDPComp::sSecuredVid = false;
-bool MDPComp::deinit() {
- //XXX: Tear down MDP comp state
+MDPComp* MDPComp::getObject(const int& width) {
+ //For now. Later check for width > 2048
+ return new MDPCompLowRes();
+}
+
+void MDPComp::dump(android::String8& buf)
+{
+ dumpsys_log(buf, " MDP Composition: ");
+ dumpsys_log(buf, "MDPCompState=%d\n", mState);
+ //XXX: Log more info
+}
+
+bool MDPComp::init(hwc_context_t *ctx) {
+
+ if(!ctx) {
+ ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
+ return false;
+ }
+
+ if(!setupBasePipe(ctx)) {
+ ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
+ return false;
+ }
+
+ char property[PROPERTY_VALUE_MAX];
+
+ sEnabled = false;
+ if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ sEnabled = true;
+ }
+
+ sDebugLogs = false;
+ if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
+ if(atoi(property) != 0)
+ sDebugLogs = true;
+ }
+
+ unsigned long idle_timeout = DEFAULT_IDLE_TIME;
+ if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+ if(atoi(property) != 0)
+ idle_timeout = atoi(property);
+ }
+
+ //create Idle Invalidator
+ idleInvalidator = IdleInvalidator::getInstance();
+
+ if(idleInvalidator == NULL) {
+ ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
+ } else {
+ idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+ }
return true;
}
-bool MDPComp::isSkipPresent (hwc_context_t *ctx) {
- return ctx->listStats[HWC_DISPLAY_PRIMARY].skipCount;
-};
-
-bool MDPComp::isYuvPresent (hwc_context_t *ctx) {
- return ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount;
-};
void MDPComp::timeout_handler(void *udata) {
struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
@@ -63,179 +105,249 @@
ctx->proc->invalidate(ctx->proc);
}
-void MDPComp::reset(hwc_context_t *ctx, hwc_display_contents_1_t* list ) {
- //Reset flags and states
- unsetMDPCompLayerFlags(ctx, list);
- sCurrentFrame.count = 0;
- if(sCurrentFrame.pipeLayer) {
- free(sCurrentFrame.pipeLayer);
- sCurrentFrame.pipeLayer = NULL;
+void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ const int dpy = HWC_DISPLAY_PRIMARY;
+ LayerProp *layerProp = ctx->layerProp[dpy];
+
+ for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
+ hwc_layer_1_t* layer = &(list->hwLayers[index]);
+ layerProp[index].mFlags |= HWC_MDPCOMP;
+ layer->compositionType = HWC_OVERLAY;
+ layer->hints |= HWC_HINT_CLEAR_FB;
}
}
-void MDPComp::print_info(hwc_layer_1_t* layer)
-{
- hwc_rect_t sourceCrop = layer->sourceCrop;
- hwc_rect_t displayFrame = layer->displayFrame;
+void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list) {
+ const int dpy = HWC_DISPLAY_PRIMARY;
+ LayerProp *layerProp = ctx->layerProp[dpy];
- int s_l = sourceCrop.left;
- int s_t = sourceCrop.top;
- int s_r = sourceCrop.right;
- int s_b = sourceCrop.bottom;
+ for (int index = 0 ;
+ index < ctx->listStats[dpy].numAppLayers; index++) {
+ if(layerProp[index].mFlags & HWC_MDPCOMP) {
+ layerProp[index].mFlags &= ~HWC_MDPCOMP;
+ }
- int d_l = displayFrame.left;
- int d_t = displayFrame.top;
- int d_r = displayFrame.right;
- int d_b = displayFrame.bottom;
-
- ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
- dst:[%d,%d,%d,%d] (%d x %d)",
- s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
- d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
+ if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
+ list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
+ }
+ }
}
-void MDPComp::setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags) {
+/*
+ * Sets up BORDERFILL as default base pipe and detaches RGB0.
+ * Framebuffer is always updated using PLAY ioctl.
+ */
+bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
+ const int dpy = HWC_DISPLAY_PRIMARY;
+ int fb_stride = ctx->dpyAttr[dpy].stride;
+ int fb_width = ctx->dpyAttr[dpy].xres;
+ int fb_height = ctx->dpyAttr[dpy].yres;
+ int fb_fd = ctx->dpyAttr[dpy].fd;
+
+ mdp_overlay ovInfo;
+ msmfb_overlay_data ovData;
+ memset(&ovInfo, 0, sizeof(mdp_overlay));
+ memset(&ovData, 0, sizeof(msmfb_overlay_data));
+
+ ovInfo.src.format = MDP_RGB_BORDERFILL;
+ ovInfo.src.width = fb_width;
+ ovInfo.src.height = fb_height;
+ ovInfo.src_rect.w = fb_width;
+ ovInfo.src_rect.h = fb_height;
+ ovInfo.dst_rect.w = fb_width;
+ ovInfo.dst_rect.h = fb_height;
+ ovInfo.id = MSMFB_NEW_REQUEST;
+
+ if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
+ strerror(errno));
+ return false;
+ }
+
+ ovData.id = ovInfo.id;
+ if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
+ ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+void MDPComp::printInfo(hwc_layer_1_t* layer) {
+ hwc_rect_t sourceCrop = layer->sourceCrop;
+ hwc_rect_t displayFrame = layer->displayFrame;
+
+ int s_l = sourceCrop.left;
+ int s_t = sourceCrop.top;
+ int s_r = sourceCrop.right;
+ int s_b = sourceCrop.bottom;
+
+ int d_l = displayFrame.left;
+ int d_t = displayFrame.top;
+ int d_r = displayFrame.right;
+ int d_b = displayFrame.bottom;
+
+ ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
+ dst:[%d,%d,%d,%d] (%d x %d)",
+ s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
+ d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
+}
+
+//=============MDPCompLowRes===================================================
+void MDPCompLowRes::reset(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list ) {
+ //Reset flags and states
+ unsetMDPCompLayerFlags(ctx, list);
+ mCurrentFrame.count = 0;
+ if(mCurrentFrame.pipeLayer) {
+ free(mCurrentFrame.pipeLayer);
+ mCurrentFrame.pipeLayer = NULL;
+ }
+}
+
+void MDPCompLowRes::setVidInfo(hwc_layer_1_t *layer,
+ ovutils::eMdpFlags &mdpFlags) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
if(isSecureBuffer(hnd)) {
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
- sSecuredVid = true;
+ }
+ if((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
}
}
/*
* Configures pipe(s) for MDP composition
*/
-int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
- MdpPipeInfo& mdp_info) {
-
+int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ MdpPipeInfo& mdp_info) {
int nPipeIndex = mdp_info.index;
+ const int dpy = HWC_DISPLAY_PRIMARY;
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ overlay::Overlay& ov = *ctx->mOverlay;
- if (ctx) {
+ if(!hnd) {
+ ALOGE("%s: layer handle is NULL", __FUNCTION__);
+ return -1;
+ }
- private_handle_t *hnd = (private_handle_t *)layer->handle;
+ int hw_w = ctx->dpyAttr[dpy].xres;
+ int hw_h = ctx->dpyAttr[dpy].yres;
- overlay::Overlay& ov = *ctx->mOverlay;
+ hwc_rect_t sourceCrop = layer->sourceCrop;
+ hwc_rect_t displayFrame = layer->displayFrame;
- if(!hnd) {
- ALOGE("%s: layer handle is NULL", __FUNCTION__);
- return -1;
+ const int src_w = sourceCrop.right - sourceCrop.left;
+ const int src_h = sourceCrop.bottom - sourceCrop.top;
+
+ hwc_rect_t crop = sourceCrop;
+ int crop_w = crop.right - crop.left;
+ int crop_h = crop.bottom - crop.top;
+
+ hwc_rect_t dst = displayFrame;
+ int dst_w = dst.right - dst.left;
+ int dst_h = dst.bottom - dst.top;
+
+ if(dst.left < 0 || dst.top < 0 ||
+ dst.right > hw_w || dst.bottom > hw_h) {
+ ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
+ __FUNCTION__);
+ qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, 0);
+
+ //Update calulated width and height
+ crop_w = crop.right - crop.left;
+ crop_h = crop.bottom - crop.top;
+
+ dst_w = dst.right - dst.left;
+ dst_h = dst.bottom - dst.top;
+ }
+
+ if( (dst_w > hw_w)|| (dst_h > hw_h)) {
+ ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
+ printInfo(layer);
+ dst_w = hw_w;
+ dst_h = hw_h;
+ }
+
+ // Determine pipe to set based on pipe index
+ ovutils::eDest dest = (ovutils::eDest)mdp_info.index;
+
+ ovutils::eZorder zOrder = ovutils::ZORDER_0;
+
+ if(mdp_info.zOrder == 0 ) {
+ zOrder = ovutils::ZORDER_0;
+ } else if(mdp_info.zOrder == 1 ) {
+ zOrder = ovutils::ZORDER_1;
+ } else if(mdp_info.zOrder == 2 ) {
+ zOrder = ovutils::ZORDER_2;
+ } else if(mdp_info.zOrder == 3) {
+ zOrder = ovutils::ZORDER_3;
+ }
+
+ // Order order order
+ // setSource - just setting source
+ // setParameter - changes src w/h/f accordingly
+ // setCrop - ROI - src_rect
+ // setPosition - dst_rect
+ // commit - commit changes to mdp driver
+ // queueBuffer - not here, happens when draw is called
+
+ ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+
+ ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+
+ if(isYuvBuffer(hnd))
+ setVidInfo(layer, mdpFlags);
+
+ ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
+
+ if(layer->blending == HWC_BLENDING_PREMULT) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_BLEND_FG_PREMULT);
+ }
+
+ ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
+
+ if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
+ if(layer->transform & HWC_TRANSFORM_FLIP_H) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
}
- int hw_w = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int hw_h = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
-
- hwc_rect_t sourceCrop = layer->sourceCrop;
- hwc_rect_t displayFrame = layer->displayFrame;
-
- const int src_w = sourceCrop.right - sourceCrop.left;
- const int src_h = sourceCrop.bottom - sourceCrop.top;
-
- hwc_rect_t crop = sourceCrop;
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
-
- hwc_rect_t dst = displayFrame;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
-
- if(dst.left < 0 || dst.top < 0 ||
- dst.right > hw_w || dst.bottom > hw_h) {
- ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
- __FUNCTION__);
- qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, 0);
-
- //Update calulated width and height
- crop_w = crop.right - crop.left;
- crop_h = crop.bottom - crop.top;
-
- dst_w = dst.right - dst.left;
- dst_h = dst.bottom - dst.top;
+ if(layer->transform & HWC_TRANSFORM_FLIP_V) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
}
+ } else {
+ orient = static_cast<ovutils::eTransform>(layer->transform);
+ }
- if( (dst_w > hw_w)|| (dst_h > hw_h)) {
- ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
- print_info(layer);
- dst_w = hw_w;
- dst_h = hw_h;
- }
+ ovutils::PipeArgs parg(mdpFlags,
+ info,
+ zOrder,
+ ovutils::IS_FG_OFF,
+ ovutils::ROT_FLAG_DISABLED);
- // Determine pipe to set based on pipe index
- ovutils::eDest dest = (ovutils::eDest)mdp_info.index;
+ ov.setSource(parg, dest);
- ovutils::eZorder zOrder = ovutils::ZORDER_0;
+ ov.setTransform(orient, dest);
- if(mdp_info.zOrder == 0 ) {
- zOrder = ovutils::ZORDER_0;
- } else if(mdp_info.zOrder == 1 ) {
- zOrder = ovutils::ZORDER_1;
- } else if(mdp_info.zOrder == 2 ) {
- zOrder = ovutils::ZORDER_2;
- } else if(mdp_info.zOrder == 3) {
- zOrder = ovutils::ZORDER_3;
- }
+ ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
+ ov.setCrop(dcrop, dest);
- // Order order order
- // setSource - just setting source
- // setParameter - changes src w/h/f accordingly
- // setCrop - ROI - src_rect
- // setPosition - dst_rect
- // commit - commit changes to mdp driver
- // queueBuffer - not here, happens when draw is called
+ ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
+ ov.setPosition(dim, dest);
- ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+ ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
+ nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
+ dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
+ mdp_info.index, mdp_info.zOrder);
- ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-
- if(isYuvBuffer(hnd))
- setVidInfo(layer, mdpFlags);
-
- ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
-
- if(layer->blending == HWC_BLENDING_PREMULT) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_BLEND_FG_PREMULT);
- }
-
- ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
-
- if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
- if(layer->transform & HWC_TRANSFORM_FLIP_H) {
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
- }
-
- if(layer->transform & HWC_TRANSFORM_FLIP_V) {
- ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_V);
- }
- } else {
- orient = static_cast<ovutils::eTransform>(layer->transform);
- }
-
- ovutils::PipeArgs parg(mdpFlags,
- info,
- zOrder,
- ovutils::IS_FG_OFF,
- ovutils::ROT_FLAG_DISABLED);
-
- ov.setSource(parg, dest);
-
- ov.setTransform(orient, dest);
-
- ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
- ov.setCrop(dcrop, dest);
-
- ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
- ov.setPosition(dim, dest);
-
- ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
- nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
- dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
- mdp_info.index, mdp_info.zOrder);
-
- if (!ov.commit(dest)) {
- ALOGE("%s: commit failed", __FUNCTION__);
- return -1;
- }
+ if (!ov.commit(dest)) {
+ ALOGE("%s: commit failed", __FUNCTION__);
+ return -1;
}
return 0;
}
@@ -250,15 +362,26 @@
* 5. Overlay in use
*/
-bool MDPComp::isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::isDoable(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
//Number of layers
- int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+ const int dpy = HWC_DISPLAY_PRIMARY;
+ int numAppLayers = ctx->listStats[dpy].numAppLayers;
- if(numAppLayers < 1 || numAppLayers > (uint32_t)sActiveMax) {
+ overlay::Overlay& ov = *ctx->mOverlay;
+ int availablePipes = ov.availablePipes(dpy);
+
+ if(numAppLayers < 1 || numAppLayers > (uint32_t)availablePipes) {
ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
return false;
}
+ if(ctx->mExtDispConfiguring) {
+ ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+ __FUNCTION__);
+ return false;
+ }
+
if(isSecuring(ctx)) {
ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
return false;
@@ -268,12 +391,12 @@
return false;
//Check for skip layers
- if(isSkipPresent(ctx)) {
+ if(isSkipPresent(ctx, dpy)) {
ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
return false;
}
- if(ctx->listStats[HWC_DISPLAY_PRIMARY].needsAlphaScale) {
+ if(ctx->listStats[dpy].needsAlphaScale) {
ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
return false;
}
@@ -299,75 +422,62 @@
return true;
}
-void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
-
- for(int index = 0 ; index < sCurrentFrame.count; index++ ) {
- hwc_layer_1_t* layer = &(list->hwLayers[index]);
- layerProp[index].mFlags |= HWC_MDPCOMP;
- layer->compositionType = HWC_OVERLAY;
- layer->hints |= HWC_HINT_CLEAR_FB;
- }
-}
-
-int MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type){
+int MDPCompLowRes::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
+ const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
int mdp_pipe = -1;
switch(type) {
- case MDPCOMP_OV_ANY:
- case MDPCOMP_OV_RGB:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, HWC_DISPLAY_PRIMARY);
- if(mdp_pipe != ovutils::OV_INVALID) {
- return mdp_pipe;
- }
+ case MDPCOMP_OV_ANY:
+ case MDPCOMP_OV_RGB:
+ mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
+ if(mdp_pipe != ovutils::OV_INVALID) {
+ return mdp_pipe;
+ }
- if(type == MDPCOMP_OV_RGB) {
- //Requested only for RGB pipe
+ if(type == MDPCOMP_OV_RGB) {
+ //Requested only for RGB pipe
+ return -1;
+ }
+ case MDPCOMP_OV_VG:
+ mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
+ if(mdp_pipe != ovutils::OV_INVALID) {
+ return mdp_pipe;
+ }
return -1;
- }
- case MDPCOMP_OV_VG:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, HWC_DISPLAY_PRIMARY);
- if(mdp_pipe != ovutils::OV_INVALID) {
- return mdp_pipe;
- }
- return -1;
- default:
- ALOGE("%s: Invalid pipe type",__FUNCTION__);
- return -1;
+ default:
+ ALOGE("%s: Invalid pipe type",__FUNCTION__);
+ return -1;
};
}
-bool MDPComp::allocLayerPipes(hwc_context_t *ctx,
+bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list,
FrameInfo& currentFrame) {
-
+ const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
-
- int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+ int layer_count = ctx->listStats[dpy].numAppLayers;
currentFrame.count = layer_count;
-
currentFrame.pipeLayer = (PipeLayerPair*)
- malloc(sizeof(PipeLayerPair) * currentFrame.count);
+ malloc(sizeof(PipeLayerPair) * currentFrame.count);
- if(isYuvPresent(ctx)) {
- int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndex;
+ if(isYuvPresent(ctx, dpy)) {
+ int nYuvIndex = ctx->listStats[dpy].yuvIndex;
hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
MdpPipeInfo& pipe_info = info.pipeIndex;
pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
if(pipe_info.index < 0) {
ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
- __FUNCTION__);
+ __FUNCTION__);
return false;
}
pipe_info.zOrder = nYuvIndex;
}
for(int index = 0 ; index < layer_count ; index++ ) {
- if(index == ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndex )
+ if(index == ctx->listStats[dpy].yuvIndex )
continue;
hwc_layer_1_t* layer = &list->hwLayers[index];
@@ -383,11 +493,12 @@
return true;
}
-bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+ const int dpy = HWC_DISPLAY_PRIMARY;
int nPipeIndex, vsync_wait, isFG;
- int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+ int numHwLayers = ctx->listStats[dpy].numAppLayers;
- FrameInfo ¤tFrame = sCurrentFrame;
+ FrameInfo ¤tFrame = mCurrentFrame;
currentFrame.count = 0;
if(currentFrame.pipeLayer) {
@@ -396,8 +507,8 @@
}
if(!ctx) {
- ALOGE("%s: invalid context", __FUNCTION__);
- return -1;
+ ALOGE("%s: invalid context", __FUNCTION__);
+ return -1;
}
if(!allocLayerPipes(ctx, list, currentFrame)) {
@@ -417,39 +528,22 @@
hwc_layer_1_t* layer = &list->hwLayers[index];
MdpPipeInfo& cur_pipe = currentFrame.pipeLayer[index].pipeIndex;
- if( prepare(ctx, layer, cur_pipe) != 0 ) {
- ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
- layer %d with pipe index:%d",__FUNCTION__,
- index, cur_pipe.index);
- return false;
- }
+ if(configure(ctx, layer, cur_pipe) != 0 ) {
+ ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
+ layer %d with pipe index:%d",__FUNCTION__,
+ index, cur_pipe.index);
+ return false;
+ }
}
return true;
}
-void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
- hwc_display_contents_1_t* list)
-{
- LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
-
- for (int index = 0 ;
- index < ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers; index++) {
- if(layerProp[index].mFlags & HWC_MDPCOMP) {
- layerProp[index].mFlags &= ~HWC_MDPCOMP;
- }
-
- if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
- list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
- }
- }
-}
-
-bool MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(!isEnabled() || !isUsed()) {
ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
return true;
- }
+ }
if(!ctx || !list) {
ALOGE("%s: invalid contxt or list",__FUNCTION__);
@@ -460,10 +554,11 @@
if(idleInvalidator)
idleInvalidator->markForSleep();
+ const int dpy = HWC_DISPLAY_PRIMARY;
overlay::Overlay& ov = *ctx->mOverlay;
- LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
+ LayerProp *layerProp = ctx->layerProp[dpy];
- int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+ int numHwLayers = ctx->listStats[dpy].numAppLayers;
for(int i = 0; i < numHwLayers; i++ )
{
hwc_layer_1_t *layer = &list->hwLayers[i];
@@ -473,7 +568,7 @@
}
MdpPipeInfo& pipe_info =
- sCurrentFrame.pipeLayer[i].pipeIndex;
+ mCurrentFrame.pipeLayer[i].pipeIndex;
int index = pipe_info.index;
if(index < 0) {
@@ -491,8 +586,8 @@
}
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
- using pipe: %d", __FUNCTION__, layer,
- hnd, index );
+ using pipe: %d", __FUNCTION__, layer,
+ hnd, index );
if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
@@ -505,103 +600,14 @@
return true;
}
-/*
- * Sets up BORDERFILL as default base pipe and detaches RGB0.
- * Framebuffer is always updated using PLAY ioctl.
- */
-
-bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
-
- int fb_stride = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride;
- int fb_width = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int fb_height = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- int fb_fd = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd;
-
- mdp_overlay ovInfo;
- msmfb_overlay_data ovData;
- memset(&ovInfo, 0, sizeof(mdp_overlay));
- memset(&ovData, 0, sizeof(msmfb_overlay_data));
-
- ovInfo.src.format = MDP_RGB_BORDERFILL;
- ovInfo.src.width = fb_width;
- ovInfo.src.height = fb_height;
- ovInfo.src_rect.w = fb_width;
- ovInfo.src_rect.h = fb_height;
- ovInfo.dst_rect.w = fb_width;
- ovInfo.dst_rect.h = fb_height;
- ovInfo.id = MSMFB_NEW_REQUEST;
-
- if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
- strerror(errno));
- return false;
- }
-
- ovData.id = ovInfo.id;
- if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
-bool MDPComp::init(hwc_context_t *ctx) {
-
- if(!ctx) {
- ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
- return false;
- }
-
- if(!setupBasePipe(ctx)) {
- ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
- return false;
- }
-
- char property[PROPERTY_VALUE_MAX];
-
- sEnabled = false;
- if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
- sEnabled = true;
- }
-
- sDebugLogs = false;
- if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
- if(atoi(property) != 0)
- sDebugLogs = true;
- }
-
- unsigned long idle_timeout = DEFAULT_IDLE_TIME;
- if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
- if(atoi(property) != 0)
- idle_timeout = atoi(property);
- }
-
- //create Idle Invalidator
- idleInvalidator = IdleInvalidator::getInstance();
-
- if(idleInvalidator == NULL) {
- ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__);
- } else {
- idleInvalidator->init(timeout_handler, ctx, idle_timeout);
- }
- return true;
-}
-
-bool MDPComp::configure(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
-
+bool MDPCompLowRes::prepare(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
if(!isEnabled()) {
ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
return false;
}
overlay::Overlay& ov = *ctx->mOverlay;
-
- sActiveMax = ov.availablePipes();
-
bool isMDPCompUsed = true;
bool doable = isDoable(ctx, list);
@@ -612,31 +618,21 @@
ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
isMDPCompUsed = false;
}
- } else {
+ } else {
ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
- doable);
+ doable);
isMDPCompUsed = false;
- }
+ }
- //Reset states
- if(!isMDPCompUsed) {
+ //Reset states
+ if(!isMDPCompUsed) {
//Reset current frame
- reset(ctx, list);
- }
+ reset(ctx, list);
+ }
- sMDPCompState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
-
- return isMDPCompUsed;
+ mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
+ return isMDPCompUsed;
}
-void MDPComp::dump(android::String8& buf)
-{
- dumpsys_log(buf, " MDP Composition: ");
- dumpsys_log(buf, "MDPCompState=%d\n", sMDPCompState);
- //XXX: Log more info
-
-}
-
-
}; //namespace
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 6ff6385..4dc5878 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -30,6 +30,22 @@
namespace ovutils = overlay::utils;
class MDPComp {
+public:
+ virtual ~MDPComp() {}
+ /*sets up mdp comp for the current frame */
+ virtual bool prepare(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* draw */
+ virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+ void dump(android::String8& buf);
+ bool isUsed() { return (mState == MDPCOMP_ON); };
+
+ static MDPComp* getObject(const int& width);
+ /* Handler to invoke frame redraw on Idle Timer expiry */
+ static void timeout_handler(void *udata);
+ static bool init(hwc_context_t *ctx);
+
+protected:
enum eState {
MDPCOMP_ON = 0,
MDPCOMP_OFF,
@@ -41,6 +57,39 @@
MDPCOMP_OV_ANY,
};
+ /* set/reset flags for MDPComp */
+ void setMDPCompLayerFlags(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ void unsetMDPCompLayerFlags(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list);
+ void printInfo(hwc_layer_1_t* layer);
+ /* get/set states */
+ eState getState() { return mState; };
+
+ /* set up Border fill as Base pipe */
+ static bool setupBasePipe(hwc_context_t*);
+ /* Is debug enabled */
+ static bool isDebug() { return sDebugLogs ? true : false; };
+ /* Is feature enabled */
+ static bool isEnabled() { return sEnabled; };
+
+ eState mState;
+
+ static bool sEnabled;
+ static bool sDebugLogs;
+ static bool sIdleFallBack;
+ static IdleInvalidator *idleInvalidator;
+
+};
+
+class MDPCompLowRes : public MDPComp {
+public:
+ virtual ~MDPCompLowRes() {}
+ virtual bool prepare(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+private:
struct MdpPipeInfo {
int index;
int zOrder;
@@ -56,81 +105,35 @@
struct PipeLayerPair* pipeLayer;
};
-
- static eState sMDPCompState;
- static IdleInvalidator *idleInvalidator;
- static struct FrameInfo sCurrentFrame;
- static bool sEnabled;
- static bool sDebugLogs;
- static bool sIdleFallBack;
- static int sActiveMax;
- static bool sSecuredVid;
-
-public:
- /* Handler to invoke frame redraw on Idle Timer expiry */
- static void timeout_handler(void *udata);
-
- /* configure/tear-down MDPComp params*/
- static bool init(hwc_context_t *ctx);
- static bool deinit();
- static bool isUsed() { return (sMDPCompState == MDPCOMP_ON); };
-
- /*sets up mdp comp for the current frame */
- static bool configure(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
-
- /* draw */
- static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
- static void dump(android::String8& buf);
-
-private:
- /* set/reset flags for MDPComp */
- static void setMDPCompLayerFlags(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
- static void unsetMDPCompLayerFlags(hwc_context_t* ctx,
- hwc_display_contents_1_t* list);
-
- static void print_info(hwc_layer_1_t* layer);
-
/* configure's overlay pipes for the frame */
- static int prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
+ int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
MdpPipeInfo& mdp_info);
-
/* checks for conditions where mdpcomp is not possible */
- static bool isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
- static bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
-
+ bool isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
/* allocates pipes to selected candidates */
- static bool allocLayerPipes(hwc_context_t *ctx,
+ bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list,
FrameInfo& current_frame);
-
- /* get/set states */
- static eState getState() { return sMDPCompState; };
-
/* reset state */
- static void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list );
-
- /* Is feature enabled */
- static bool isEnabled() { return sEnabled; };
-
- /* Is debug enabled */
- static bool isDebug() { return sDebugLogs ? true : false; };
-
- /* check layer state */
- static bool isSkipPresent (hwc_context_t *ctx);
- static bool isYuvPresent (hwc_context_t *ctx);
-
+ void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list );
/* configure MDP flags for video buffers */
- static void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags);
-
- /* set up Border fill as Base pipe */
- static bool setupBasePipe(hwc_context_t*);
-
+ void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags);
/* allocate MDP pipes from overlay */
- static int getMdpPipe(hwc_context_t *ctx, ePipeType type);
+ int getMdpPipe(hwc_context_t *ctx, ePipeType type);
+
+ struct FrameInfo mCurrentFrame;
};
+
+class MDPCompHighRes : public MDPComp {
+public:
+ virtual ~MDPCompHighRes() {}
+ virtual bool prepare(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) { return false; }
+ virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+ return true;
+ }
+};
+
}; //namespace
#endif
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 78f6788..334df26 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -26,6 +26,7 @@
#include <string.h>
#include <stdlib.h>
#include "hwc_utils.h"
+#include "hwc_fbupdate.h"
#include "external.h"
namespace qhwc {
@@ -38,8 +39,8 @@
int64_t timestamp = 0;
const char *str = udata;
- if(!strcasestr(str, "change@/devices/virtual/switch/hdmi") &&
- !strcasestr(str, "change@/devices/virtual/switch/wfd")) {
+ if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
+ !strcasestr("change@/devices/virtual/switch/wfd", str)) {
ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
return;
}
@@ -65,10 +66,19 @@
if(connected != -1) { //either we got switch_state connected or disconnect
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
- if(connected) {
+ if (connected) {
+ ctx->mExtDispConfiguring = true;
ctx->mExtDisplay->processUEventOnline(udata);
- }else {
+ ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] =
+ IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
+ HWC_DISPLAY_EXTERNAL);
+ } else {
ctx->mExtDisplay->processUEventOffline(udata);
+ if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) {
+ Locker::Autolock _l(ctx->mExtSetLock);
+ delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL];
+ ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL;
+ }
}
ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected);
Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 2f35567..76635d5 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -23,6 +23,7 @@
#include <overlay.h>
#include "hwc_utils.h"
#include "hwc_mdpcomp.h"
+#include "hwc_fbupdate.h"
#include "mdp_version.h"
#include "external.h"
#include "QService.h"
@@ -59,15 +60,22 @@
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
+ //Is created and destroyed only once for primary
+ //For external it could get created and destroyed multiple times depending
+ //on what external we connect to.
+ ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
+ IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
+ HWC_DISPLAY_PRIMARY);
ctx->mExtDisplay = new ExternalDisplay(ctx);
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
ctx->mLayerCache[i] = new LayerCache();
+ ctx->mMDPComp = MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
MDPComp::init(ctx);
pthread_mutex_init(&(ctx->vstate.lock), NULL);
pthread_cond_init(&(ctx->vstate.cond), NULL);
ctx->vstate.enable = false;
-
+ ctx->mExtDispConfiguring = false;
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
@@ -91,6 +99,18 @@
ctx->mExtDisplay = NULL;
}
+ for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ if(ctx->mFBUpdate[i]) {
+ delete ctx->mFBUpdate[i];
+ ctx->mFBUpdate[i] = NULL;
+ }
+ }
+
+ if(ctx->mMDPComp) {
+ delete ctx->mMDPComp;
+ ctx->mMDPComp = NULL;
+ }
+
pthread_mutex_destroy(&(ctx->vstate.lock));
pthread_cond_destroy(&(ctx->vstate.cond));
}
@@ -238,15 +258,25 @@
int count = 0;
int releaseFd = -1;
int fbFd = -1;
+ bool swapzero = false;
data.flags = MDP_BUF_SYNC_FLAG_WAIT;
data.acq_fen_fd = acquireFd;
data.rel_fen_fd = &releaseFd;
+ char property[PROPERTY_VALUE_MAX];
+ if(property_get("debug.egl.swapinterval", property, "1") > 0) {
+ if(atoi(property) == 0)
+ swapzero = true;
+ }
+
//Accumulate acquireFenceFds
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
list->hwLayers[i].acquireFenceFd != -1 ){
- acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+ if(UNLIKELY(swapzero))
+ acquireFd[count++] = -1;
+ else
+ acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
}
}
@@ -254,7 +284,8 @@
fbFd = ctx->dpyAttr[dpy].fd;
//Waits for acquire fences, returns a release fence
- ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
+ if(LIKELY(!swapzero))
+ ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
if(ret < 0) {
ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
strerror(errno));
@@ -269,10 +300,18 @@
list->hwLayers[i].acquireFenceFd = -1;
}
//Populate releaseFenceFds.
- list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ if(UNLIKELY(swapzero))
+ list->hwLayers[i].releaseFenceFd = -1;
+ else
+ list->hwLayers[i].releaseFenceFd = dup(releaseFd);
}
}
- list->retireFenceFd = releaseFd;
+ if(UNLIKELY(swapzero)){
+ list->retireFenceFd = -1;
+ close(releaseFd);
+ } else {
+ list->retireFenceFd = releaseFd;
+ }
return ret;
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index d7200b0..9541404 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -31,6 +31,7 @@
#define FINAL_TRANSFORM_MASK 0x000F
#define MAX_NUM_DISPLAYS 4 //Yes, this is ambitious
#define MAX_NUM_LAYERS 32
+#define MAX_DISPLAY_DIM 2048
//Fwrd decls
struct hwc_context_t;
@@ -48,6 +49,8 @@
//fwrd decl
class QueuedBufferStore;
class ExternalDisplay;
+class IFBUpdate;
+class MDPComp;
struct MDPInfo {
int version;
@@ -215,6 +218,9 @@
overlay::Overlay *mOverlay;
//QService object
qService::QService *mQService;
+
+ //Primary and external FB updater
+ qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
// External display related information
qhwc::ExternalDisplay *mExtDisplay;
qhwc::MDPInfo mMDP;
@@ -222,9 +228,12 @@
qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
qhwc::LayerCache *mLayerCache[HWC_NUM_DISPLAY_TYPES];
qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
+ qhwc::MDPComp *mMDPComp;
//Securing in progress indicator
bool mSecuring;
+ //External Display configuring progress indicator
+ bool mExtDispConfiguring;
//Display in secure mode indicator
bool mSecureMode;
//Lock to prevent set from being called while blanking
@@ -235,4 +244,12 @@
struct vsync_state vstate;
};
+static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
+ return ctx->listStats[dpy].skipCount;
+}
+
+static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
+ return ctx->listStats[dpy].yuvCount;
+}
+
#endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 48cb165..1784593 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -19,6 +19,7 @@
#include <overlay.h>
#include "hwc_video.h"
#include "hwc_utils.h"
+#include "qdMetaData.h"
namespace qhwc {
@@ -106,6 +107,11 @@
ovutils::OV_MDP_BLEND_FG_PREMULT);
}
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if ((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+ ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
+ }
+
ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
if (ctx->listStats[dpy].numAppLayers == 1) {
isFgFlag = ovutils::IS_FG_SET;
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index ee6af28..7f7bb1f 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -112,9 +112,11 @@
if(!fakevsync) {
for(int i = 0; i < MAX_RETRY_COUNT; i++) {
len = pread(fd_timestamp, vdata, MAX_DATA, 0);
- if(len < 0 && (errno == EAGAIN || errno == EINTR)) {
- ALOGW("%s: vsync read: EAGAIN, retry (%d/%d).",
- __FUNCTION__, i, MAX_RETRY_COUNT);
+ if(len < 0 && (errno == EAGAIN ||
+ errno == EINTR ||
+ errno == EBUSY)) {
+ ALOGW("%s: vsync read: %s, retry (%d/%d).",
+ __FUNCTION__, strerror(errno), i, MAX_RETRY_COUNT);
continue;
} else {
break;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 2378889..151cfb3 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -71,8 +71,8 @@
static void initOverlay();
/* Returns the singleton instance of overlay */
static Overlay* getInstance();
- /* Returns total of available ("unallocated") pipes */
- static int availablePipes();
+ /* Returns available ("unallocated") pipes for a display */
+ int availablePipes(int dpy);
/* set the framebuffer index for external display */
void setExtFbNum(int fbNum);
/* Returns framebuffer index of the current external display */
@@ -111,8 +111,6 @@
static void resetAllocation(int index);
static bool isAllocated(int index);
static bool isNotAllocated(int index);
- /* Returns total of available ("unallocated") pipes */
- static int availablePipes();
static int NUM_PIPES;
@@ -149,8 +147,15 @@
utils::getDestStr((utils::eDest)index));
}
-inline int Overlay::availablePipes() {
- return PipeBook::availablePipes();
+inline int Overlay::availablePipes(int dpy) {
+ int avail = 0;
+ for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+ if((mPipeBook[i].mDisplay == PipeBook::DPY_UNUSED ||
+ mPipeBook[i].mDisplay == dpy) && PipeBook::isNotAllocated(i)) {
+ avail++;
+ }
+ }
+ return avail;
}
inline void Overlay::setExtFbNum(int fbNum) {
@@ -163,16 +168,6 @@
return sExtFbIndex;
}
-inline int Overlay::PipeBook::availablePipes() {
- int used = 0;
- int bmp = sAllocatedBitmap;
- for(; bmp; used++) {
- //clearing from lsb
- bmp = bmp & (bmp - 1);
- }
- return NUM_PIPES - used;
-}
-
inline bool Overlay::PipeBook::valid() {
return (mPipe != NULL);
}
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index cb3c48f..dedc396 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -30,6 +30,8 @@
#define MDSS_MDP_ROT_ONLY 0x80
#endif
+#define SIZE_1M 0x00100000
+
namespace ovutils = overlay::utils;
namespace overlay {
@@ -93,7 +95,10 @@
}
void MdssRot::setFlags(const utils::eMdpFlags& flags) {
- // TODO
+ mRotInfo.flags &= ~utils::OV_MDP_SECURE_OVERLAY_SESSION;
+ if (flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) {
+ mRotInfo.flags |= utils::OV_MDP_SECURE_OVERLAY_SESSION;
+ }
}
void MdssRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
@@ -119,6 +124,7 @@
bool MdssRot::commit() {
doTransform();
+ setBufSize(mRotInfo.src.format);
mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
ALOGE("MdssRot commit failed!");
@@ -166,8 +172,9 @@
{
OvMem mem;
OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+ bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION;
- if(!mem.open(numbufs, bufsz, false)){ // TODO: secure for badger
+ if(!mem.open(numbufs, bufsz, isSecure)){
ALOGE("%s: Failed to open", __func__);
mem.close();
return false;
@@ -248,4 +255,12 @@
ALOGE("== Dump MdssRot end ==");
}
+void MdssRot::setBufSize(int format) {
+ if (format == MDP_Y_CBCR_H2V2_VENUS) {
+ mBufSize = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, mRotInfo.dst_rect.w,
+ mRotInfo.dst_rect.h);
+ }
+ if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
+ mBufSize = utils::align(mBufSize, SIZE_1M);
+}
} // namespace overlay
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
index 60ed8fe..e81c2dc 100644
--- a/liboverlay/overlayMem.h
+++ b/liboverlay/overlayMem.h
@@ -119,8 +119,9 @@
alloc_data data;
int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
if(isSecure) {
- allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP;
+ allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER;
+ allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
}
int err = 0;
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 4ef33f3..ca71402 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -199,6 +199,7 @@
void doTransform();
/* reset underlying data, basically memset 0 */
void reset();
+ void setBufSize(int format);
/* MdssRot info structure */
mdp_overlay mRotInfo;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index d0f9457..49a1eaf 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -231,7 +231,8 @@
return MDP_Y_CBCR_H1V1;
case HAL_PIXEL_FORMAT_YCrCb_444_SP:
return MDP_Y_CRCB_H1V1;
-
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ return MDP_Y_CBCR_H2V2_VENUS;
default:
//Unsupported by MDP
//---graphics.h--------
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index f9fcca8..cbacf3e 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-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
@@ -44,6 +44,11 @@
#include <utils/Log.h>
#include "gralloc_priv.h" //for interlace
+// Older platforms do not support Venus.
+#ifndef VENUS_COLOR_FORMAT
+#define MDP_Y_CBCR_H2V2_VENUS (MDP_IMGTYPE_LIMIT2 + 1)
+#endif
+
/*
*
* Collection of utilities functions/structs/enums etc...
@@ -63,6 +68,10 @@
#define DEBUG_OVERLAY 0
#define PROFILE_OVERLAY 0
+#ifndef MDSS_MDP_RIGHT_MIXER
+#define MDSS_MDP_RIGHT_MIXER 0x100
+#endif
+
namespace overlay {
// fwd
@@ -297,6 +306,7 @@
OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
OV_MDP_FLIP_H = MDP_FLIP_LR,
OV_MDP_FLIP_V = MDP_FLIP_UD,
+ OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER,
};
enum eZorder {
@@ -487,6 +497,7 @@
case MDP_Y_CBCR_H2V2_TILE:
case MDP_Y_CR_CB_H2V2:
case MDP_Y_CR_CB_GH2V2:
+ case MDP_Y_CBCR_H2V2_VENUS:
return true;
default:
return false;
@@ -534,6 +545,8 @@
"MDP_YCRCB_H1V1",
"MDP_YCBCR_H1V1",
"MDP_BGR_565",
+ "MDP_BGR_888",
+ "MDP_Y_CBCR_H2V2_VENUS",
"MDP_IMGTYPE_LIMIT",
"MDP_RGB_BORDERFILL",
"MDP_FB_FORMAT",
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index ed8bed0..ecae273 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -12,3 +12,19 @@
idle_invalidator.cpp
include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO := qcom/display
+LOCAL_COPY_HEADERS := qdMetaData.h
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES := qdMetaData.cpp
+LOCAL_CFLAGS := $(common_flags)
+LOCAL_CFLAGS += -DLOG_TAG=\"DisplayMetaData\"
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libqdMetaData
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
new file mode 100644
index 0000000..a53ba07
--- /dev/null
+++ b/libqdutils/qdMetaData.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#include <string.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+#include <gralloc_priv.h>
+#include "qdMetaData.h"
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+ void *param) {
+ if (!handle) {
+ ALOGE("%s: Private handle is null!", __func__);
+ return -1;
+ }
+ if (handle->fd_metadata == -1) {
+ ALOGE("%s: Bad fd for extra data!", __func__);
+ return -1;
+ }
+ unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ handle->fd_metadata, 0);
+ if (!base) {
+ ALOGE("%s: mmap() failed: Base addr is NULL!", __func__);
+ return -1;
+ }
+ MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+ data->operation |= paramType;
+ switch (paramType) {
+ case PP_PARAM_HSIC:
+ memcpy((void *)&data->hsicData, param, sizeof(HSICData_t));
+ break;
+ case PP_PARAM_SHARPNESS:
+ data->sharpness = *((int32_t *)param);
+ break;
+ case PP_PARAM_VID_INTFC:
+ data->video_interface = *((int32_t *)param);
+ break;
+ case PP_PARAM_INTERLACED:
+ data->interlaced = *((int32_t *)param);
+ break;
+ default:
+ ALOGE("Unknown paramType %d", paramType);
+ break;
+ }
+ if(munmap(base, size))
+ ALOGE("%s: failed to unmap ptr 0x%x, err %d", __func__, (int)base,
+ errno);
+ return 0;
+}
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
new file mode 100644
index 0000000..e60daed
--- /dev/null
+++ b/libqdutils/qdMetaData.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#ifndef _QDMETADATA_H
+#define _QDMETADATA_H
+
+
+typedef struct {
+ int32_t hue;
+ float saturation;
+ int32_t intensity;
+ float contrast;
+} HSICData_t;
+
+typedef struct {
+ int32_t operation;
+ int32_t interlaced;
+ HSICData_t hsicData;
+ int32_t sharpness;
+ int32_t video_interface;
+} MetaData_t;
+
+typedef enum {
+ PP_PARAM_HSIC = 0x0001,
+ PP_PARAM_SHARPNESS = 0x0002,
+ PP_PARAM_INTERLACED = 0x0004,
+ PP_PARAM_VID_INTFC = 0x0008
+} DispParamType;
+
+int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);
+
+#endif /* _QDMETADATA_H */
+