display: Add support for HW Cursor
- Retrieve cursor pipe info from driver - Configure the layer marked with flag HWC_IS_CURSOR_LAYER to the HWCursor using the fb_cursor ioctl. - The config happens only when it satisfies the hw limitions of cursor - HWCursor is supported on primary display - Since cursor configuration happens first, make use of drop layer/count to handle other composition strategies - Add support for hwc_setCursorPositionAsync as per HWC 1.4 Change-Id: I8663b6da89b0c2dd9b48af96d64a433b2b8a302c
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <overlay.h>
|
#include <overlay.h>
|
||||||
#include <overlayRotator.h>
|
#include <overlayRotator.h>
|
||||||
#include <overlayWriteback.h>
|
#include <overlayWriteback.h>
|
||||||
|
#include <overlayCursor.h>
|
||||||
#include <mdp_version.h>
|
#include <mdp_version.h>
|
||||||
#include "hwc_utils.h"
|
#include "hwc_utils.h"
|
||||||
#include "hwc_fbupdate.h"
|
#include "hwc_fbupdate.h"
|
||||||
@@ -443,6 +444,30 @@ static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hwc_setCursorPositionAsync(struct hwc_composer_device_1* dev,
|
||||||
|
int dpy, int x, int y) {
|
||||||
|
int ret = -1;
|
||||||
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
|
switch(dpy) {
|
||||||
|
case HWC_DISPLAY_PRIMARY:
|
||||||
|
{
|
||||||
|
ATRACE_CALL();
|
||||||
|
HWCursor* hwCursor = HWCursor::getInstance();
|
||||||
|
ctx->mDrawLock.lock();
|
||||||
|
if (hwCursor->isCursorSet() &&
|
||||||
|
hwCursor->setPositionAsync(ctx->dpyAttr[dpy].fd, x, y)) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
ctx->mDrawLock.unlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
|
static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
|
||||||
int mode)
|
int mode)
|
||||||
{
|
{
|
||||||
@@ -462,6 +487,7 @@ static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
|
|||||||
ctx->mOverlay->configBegin();
|
ctx->mOverlay->configBegin();
|
||||||
ctx->mOverlay->configDone();
|
ctx->mOverlay->configDone();
|
||||||
ctx->mRotMgr->clear();
|
ctx->mRotMgr->clear();
|
||||||
|
HWCursor::getInstance()->free(ctx->dpyAttr[dpy].fd);
|
||||||
// If VDS is connected, do not clear WB object as it
|
// If VDS is connected, do not clear WB object as it
|
||||||
// will end up detaching IOMMU. This is required
|
// will end up detaching IOMMU. This is required
|
||||||
// to send black frame to WFD sink on power suspend.
|
// to send black frame to WFD sink on power suspend.
|
||||||
@@ -922,17 +948,20 @@ void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
|
|||||||
if(ctx->mMDPComp[dpy])
|
if(ctx->mMDPComp[dpy])
|
||||||
ctx->mMDPComp[dpy]->dump(aBuf, ctx);
|
ctx->mMDPComp[dpy]->dump(aBuf, ctx);
|
||||||
}
|
}
|
||||||
char ovDump[2048] = {'\0'};
|
char ovDump[3072] = {'\0'};
|
||||||
ctx->mOverlay->getDump(ovDump, 2048);
|
ctx->mOverlay->getDump(ovDump, 3072);
|
||||||
dumpsys_log(aBuf, ovDump);
|
dumpsys_log(aBuf, ovDump);
|
||||||
ovDump[0] = '\0';
|
ovDump[0] = '\0';
|
||||||
ctx->mRotMgr->getDump(ovDump, 1024);
|
ctx->mRotMgr->getDump(ovDump, 1024);
|
||||||
dumpsys_log(aBuf, ovDump);
|
dumpsys_log(aBuf, ovDump);
|
||||||
ovDump[0] = '\0';
|
ovDump[0] = '\0';
|
||||||
if(Writeback::getDump(ovDump, 1024)) {
|
if(Writeback::getDump(ovDump, 512)) {
|
||||||
dumpsys_log(aBuf, ovDump);
|
dumpsys_log(aBuf, ovDump);
|
||||||
ovDump[0] = '\0';
|
ovDump[0] = '\0';
|
||||||
}
|
}
|
||||||
|
HWCursor::getInstance()->getDump(ovDump, 512);
|
||||||
|
dumpsys_log(aBuf, ovDump);
|
||||||
|
ovDump[0] = '\0';
|
||||||
dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
|
dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
|
||||||
strlcpy(buff, aBuf.string(), buff_len);
|
strlcpy(buff, aBuf.string(), buff_len);
|
||||||
}
|
}
|
||||||
@@ -1029,6 +1058,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
|
|||||||
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
|
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
|
||||||
dev->device.getActiveConfig = hwc_getActiveConfig;
|
dev->device.getActiveConfig = hwc_getActiveConfig;
|
||||||
dev->device.setActiveConfig = hwc_setActiveConfig;
|
dev->device.setActiveConfig = hwc_setActiveConfig;
|
||||||
|
dev->device.setCursorPositionAsync = hwc_setCursorPositionAsync;
|
||||||
*device = &dev->device.common;
|
*device = &dev->device.common;
|
||||||
status = 0;
|
status = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "hwc_mdpcomp.h"
|
#include "hwc_mdpcomp.h"
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "hdmi.h"
|
#include "hdmi.h"
|
||||||
#include "qdMetaData.h"
|
#include "qdMetaData.h"
|
||||||
@@ -26,6 +25,7 @@
|
|||||||
#include "hwc_fbupdate.h"
|
#include "hwc_fbupdate.h"
|
||||||
#include "hwc_ad.h"
|
#include "hwc_ad.h"
|
||||||
#include <overlayRotator.h>
|
#include <overlayRotator.h>
|
||||||
|
#include <overlayCursor.h>
|
||||||
#include "hwc_copybit.h"
|
#include "hwc_copybit.h"
|
||||||
#include "qd_utils.h"
|
#include "qd_utils.h"
|
||||||
|
|
||||||
@@ -77,8 +77,8 @@ void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
|
|||||||
(mDpy == 0) ? "\"PRIMARY\"" :
|
(mDpy == 0) ? "\"PRIMARY\"" :
|
||||||
(mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
|
(mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
|
||||||
dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
|
dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
|
||||||
"fbCount:%2d \n", mCurrentFrame.layerCount,
|
"fbCount:%2d dropCount:%2d\n", mCurrentFrame.layerCount,
|
||||||
mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
|
mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
|
||||||
dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
|
dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
|
||||||
(mCurrentFrame.needsRedraw? "YES" : "NO"),
|
(mCurrentFrame.needsRedraw? "YES" : "NO"),
|
||||||
mCurrentFrame.mdpCount, sMaxPipesPerMixer);
|
mCurrentFrame.mdpCount, sMaxPipesPerMixer);
|
||||||
@@ -106,7 +106,8 @@ void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
|
|||||||
(mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
|
(mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
|
||||||
mCurrentFrame.layerToMDP[index],
|
mCurrentFrame.layerToMDP[index],
|
||||||
(mCurrentFrame.isFBComposed[index] ?
|
(mCurrentFrame.isFBComposed[index] ?
|
||||||
(mCurrentFrame.drop[index] ? "DROP" :
|
(mCurrentFrame.drop[index] ?
|
||||||
|
((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
|
||||||
(mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
|
(mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
|
||||||
(mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
|
(mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
|
||||||
mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
|
mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
|
||||||
@@ -301,11 +302,15 @@ void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
|
|||||||
/* Drop the layer when its already present in FB OR when it lies
|
/* Drop the layer when its already present in FB OR when it lies
|
||||||
* outside frame's ROI */
|
* outside frame's ROI */
|
||||||
if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
|
if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
|
||||||
|
if(index == mCurrentFrame.hwCursorIndex) {
|
||||||
|
layer->compositionType = HWC_CURSOR_OVERLAY;
|
||||||
|
} else {
|
||||||
layer->compositionType = HWC_OVERLAY;
|
layer->compositionType = HWC_OVERLAY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MDPComp::setRedraw(hwc_context_t *ctx,
|
void MDPComp::setRedraw(hwc_context_t *ctx,
|
||||||
hwc_display_contents_1_t* list) {
|
hwc_display_contents_1_t* list) {
|
||||||
@@ -946,6 +951,9 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
hwc_display_contents_1_t* list) {
|
hwc_display_contents_1_t* list) {
|
||||||
|
|
||||||
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
|
||||||
|
// PTOR does not qualify when there are layers dropped, but if
|
||||||
|
// dropped layer is only a cursor, PTOR could qualify
|
||||||
|
const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
|
||||||
const int stagesForMDP = min(sMaxPipesPerMixer,
|
const int stagesForMDP = min(sMaxPipesPerMixer,
|
||||||
ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
|
ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
|
||||||
|
|
||||||
@@ -955,10 +963,11 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frame level checks
|
// Frame level checks - consider PTOR in case of dropCount only if the cursor
|
||||||
|
// layer is dropped, otherwise bail out of PTOR
|
||||||
if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
|
if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
|
||||||
isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
|
isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
|
||||||
isSecurePresent(ctx, mDpy)) {
|
(mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
|
||||||
ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
|
ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -983,7 +992,7 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
memset(overlapRect, 0, sizeof(overlapRect));
|
memset(overlapRect, 0, sizeof(overlapRect));
|
||||||
int layerPixelCount, minPixelCount = 0;
|
int layerPixelCount, minPixelCount = 0;
|
||||||
int numPTORLayersFound = 0;
|
int numPTORLayersFound = 0;
|
||||||
for (int i = numAppLayers-1; (i >= 0 &&
|
for (int i = numNonCursorLayers - 1; (i >= 0 &&
|
||||||
numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
|
numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
|
||||||
hwc_layer_1_t* layer = &list->hwLayers[i];
|
hwc_layer_1_t* layer = &list->hwLayers[i];
|
||||||
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
|
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
|
||||||
@@ -1028,9 +1037,9 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Store the displayFrame and the sourceCrops of the layers
|
// Store the displayFrame and the sourceCrops of the layers
|
||||||
hwc_rect_t displayFrame[numAppLayers];
|
hwc_rect_t displayFrame[numNonCursorLayers];
|
||||||
hwc_rect_t sourceCrop[numAppLayers];
|
hwc_rect_t sourceCrop[numNonCursorLayers];
|
||||||
for(int i = 0; i < numAppLayers; i++) {
|
for(int i = 0; i < numNonCursorLayers; i++) {
|
||||||
hwc_layer_1_t* layer = &list->hwLayers[i];
|
hwc_layer_1_t* layer = &list->hwLayers[i];
|
||||||
displayFrame[i] = layer->displayFrame;
|
displayFrame[i] = layer->displayFrame;
|
||||||
sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
|
sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
|
||||||
@@ -1119,11 +1128,11 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentFrame.mdpCount = numAppLayers;
|
mCurrentFrame.mdpCount = numNonCursorLayers;
|
||||||
mCurrentFrame.fbCount = 0;
|
mCurrentFrame.fbCount = 0;
|
||||||
mCurrentFrame.fbZ = -1;
|
mCurrentFrame.fbZ = -1;
|
||||||
|
|
||||||
for (int j = 0; j < numAppLayers; j++) {
|
for (int j = 0; j < numNonCursorLayers; j++) {
|
||||||
if(isValidRect(list->hwLayers[j].displayFrame)) {
|
if(isValidRect(list->hwLayers[j].displayFrame)) {
|
||||||
mCurrentFrame.isFBComposed[j] = false;
|
mCurrentFrame.isFBComposed[j] = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -1135,7 +1144,7 @@ bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
|
|||||||
bool result = postHeuristicsHandling(ctx, list);
|
bool result = postHeuristicsHandling(ctx, list);
|
||||||
|
|
||||||
// Restore layer attributes
|
// Restore layer attributes
|
||||||
for(int i = 0; i < numAppLayers; i++) {
|
for(int i = 0; i < numNonCursorLayers; i++) {
|
||||||
hwc_layer_1_t* layer = &list->hwLayers[i];
|
hwc_layer_1_t* layer = &list->hwLayers[i];
|
||||||
layer->displayFrame = displayFrame[i];
|
layer->displayFrame = displayFrame[i];
|
||||||
layer->sourceCropf.left = (float)sourceCrop[i].left;
|
layer->sourceCropf.left = (float)sourceCrop[i].left;
|
||||||
@@ -1342,7 +1351,9 @@ bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
|
|||||||
hwc_display_contents_1_t* list){
|
hwc_display_contents_1_t* list){
|
||||||
if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
|
if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
|
||||||
isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
|
isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
|
||||||
!sIsPartialUpdateActive || mDpy ) {
|
isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
|
||||||
|
// On Async position update, the ROI becomes invalid, hence disable PU
|
||||||
|
// when cursor is present
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ctx->listStats[mDpy].secureUI)
|
if(ctx->listStats[mDpy].secureUI)
|
||||||
@@ -1910,7 +1921,20 @@ bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
|
|||||||
bool MDPComp::resourceCheck(hwc_context_t* ctx,
|
bool MDPComp::resourceCheck(hwc_context_t* ctx,
|
||||||
hwc_display_contents_1_t* list) {
|
hwc_display_contents_1_t* list) {
|
||||||
const bool fbUsed = mCurrentFrame.fbCount;
|
const bool fbUsed = mCurrentFrame.fbCount;
|
||||||
if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
|
int cursorInUse = 0;
|
||||||
|
if(mDpy == HWC_DISPLAY_PRIMARY) {
|
||||||
|
// check if cursor is in use for primary
|
||||||
|
cursorInUse = HWCursor::getInstance()->isCursorSet();
|
||||||
|
}
|
||||||
|
int maxStages = qdutils::MDPVersion::getInstance().getBlendStages();
|
||||||
|
// HW Cursor needs one blending stage, account for that in the check below
|
||||||
|
// On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
|
||||||
|
// Make use of the remaining stages for HW Cursor so that the composition
|
||||||
|
// strategy would not fail due to this limitation.
|
||||||
|
if (maxStages > sMaxPipesPerMixer) {
|
||||||
|
cursorInUse = 0;
|
||||||
|
}
|
||||||
|
if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
|
||||||
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
|
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1985,6 +2009,52 @@ bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
|
||||||
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
|
hwc_rect dst = layer->displayFrame;
|
||||||
|
hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
|
||||||
|
int srcW = src.right - src.left;
|
||||||
|
int srcH = src.bottom - src.top;
|
||||||
|
int dstW = dst.right - dst.left;
|
||||||
|
int dstH = dst.bottom - dst.top;
|
||||||
|
qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
|
||||||
|
uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
|
||||||
|
uint32_t numHwCursors = mdpVersion.getCursorPipes();
|
||||||
|
bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
|
||||||
|
uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if(dpy > HWC_DISPLAY_PRIMARY) {
|
||||||
|
// Cursor not supported on secondary displays, as it involves scaling
|
||||||
|
// in most of the cases
|
||||||
|
return false;
|
||||||
|
} else if (isSkipLayer(layer)) {
|
||||||
|
return false;
|
||||||
|
// Checks for HW limitation
|
||||||
|
} else if (numHwCursors == 0 || maxCursorSize <= 0) {
|
||||||
|
return false;
|
||||||
|
} else if (needsScaling(layer)) {
|
||||||
|
return false;
|
||||||
|
} else if (layer->transform != 0) {
|
||||||
|
return false;
|
||||||
|
} else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
|
||||||
|
return false;
|
||||||
|
} else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
|
||||||
|
// In case of split display with no srcSplit, the driver allocates two
|
||||||
|
// pipes to support async position update across mixers, hence
|
||||||
|
// need to account for that here.
|
||||||
|
cursorPipesNeeded = 2;
|
||||||
|
}
|
||||||
|
if (cursorPipesNeeded <= numHwCursors) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Checks only if videos or single layer(RGB) is updating
|
// Checks only if videos or single layer(RGB) is updating
|
||||||
// which is used for setting dynamic fps or perf hint for single
|
// which is used for setting dynamic fps or perf hint for single
|
||||||
// layer video playback
|
// layer video playback
|
||||||
@@ -2029,9 +2099,10 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
char property[PROPERTY_VALUE_MAX];
|
char property[PROPERTY_VALUE_MAX];
|
||||||
|
|
||||||
if(!ctx || !list) {
|
if(!list) {
|
||||||
ALOGE("%s: Invalid context or list",__FUNCTION__);
|
ALOGE("%s: Invalid list", __FUNCTION__);
|
||||||
mCachedFrame.reset();
|
mCachedFrame.reset();
|
||||||
|
freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2052,6 +2123,7 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
mCurrentFrame.reset(numLayers);
|
mCurrentFrame.reset(numLayers);
|
||||||
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
|
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
|
||||||
mCurrentFrame.dropCount = 0;
|
mCurrentFrame.dropCount = 0;
|
||||||
|
mCurrentFrame.hwCursorIndex = -1;
|
||||||
|
|
||||||
//Do not cache the information for next draw cycle.
|
//Do not cache the information for next draw cycle.
|
||||||
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
|
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
|
||||||
@@ -2061,6 +2133,7 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
#ifdef DYNAMIC_FPS
|
#ifdef DYNAMIC_FPS
|
||||||
setDynRefreshRate(ctx, list);
|
setDynRefreshRate(ctx, list);
|
||||||
#endif
|
#endif
|
||||||
|
freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2077,6 +2150,7 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
#ifdef DYNAMIC_FPS
|
#ifdef DYNAMIC_FPS
|
||||||
setDynRefreshRate(ctx, list);
|
setDynRefreshRate(ctx, list);
|
||||||
#endif
|
#endif
|
||||||
|
freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
@@ -2106,6 +2180,23 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
dropNonAIVLayers(ctx, list);
|
dropNonAIVLayers(ctx, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure the cursor if present
|
||||||
|
int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
|
||||||
|
if(ctx->listStats[mDpy].cursorLayerPresent &&
|
||||||
|
validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
|
||||||
|
if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
|
||||||
|
&(list->hwLayers[topIndex]))) {
|
||||||
|
// As cursor is configured, mark that layer as dropped, so that
|
||||||
|
// it wont be considered for composition by other strategies.
|
||||||
|
mCurrentFrame.hwCursorIndex = topIndex;
|
||||||
|
mCurrentFrame.drop[topIndex] = true;
|
||||||
|
mCurrentFrame.dropCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Release the hw cursor
|
||||||
|
freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
|
||||||
|
}
|
||||||
|
|
||||||
// if tryFullFrame fails, try to push all video and secure RGB layers
|
// if tryFullFrame fails, try to push all video and secure RGB layers
|
||||||
// to MDP for composition.
|
// to MDP for composition.
|
||||||
mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
|
mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
|
||||||
@@ -2117,6 +2208,12 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
reset(ctx);
|
reset(ctx);
|
||||||
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
|
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
|
||||||
mCurrentFrame.dropCount = 0;
|
mCurrentFrame.dropCount = 0;
|
||||||
|
// Check if cursor is in use for primary and mark accordingly
|
||||||
|
if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
|
||||||
|
int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
|
||||||
|
hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
|
||||||
|
layer->compositionType = HWC_CURSOR_OVERLAY;
|
||||||
|
}
|
||||||
ret = -1;
|
ret = -1;
|
||||||
ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
|
ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
|
||||||
"MDP Composition Strategies Failed");
|
"MDP Composition Strategies Failed");
|
||||||
@@ -2131,6 +2228,8 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
}
|
}
|
||||||
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
|
ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
|
// Release the hw cursor
|
||||||
|
freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ protected:
|
|||||||
|
|
||||||
bool needsRedraw;
|
bool needsRedraw;
|
||||||
int fbZ;
|
int fbZ;
|
||||||
|
int hwCursorIndex;
|
||||||
|
|
||||||
/* c'tor */
|
/* c'tor */
|
||||||
FrameInfo();
|
FrameInfo();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <overlay.h>
|
#include <overlay.h>
|
||||||
#include <overlayRotator.h>
|
#include <overlayRotator.h>
|
||||||
#include <overlayWriteback.h>
|
#include <overlayWriteback.h>
|
||||||
|
#include <overlayCursor.h>
|
||||||
#include "hwc_utils.h"
|
#include "hwc_utils.h"
|
||||||
#include "hwc_mdpcomp.h"
|
#include "hwc_mdpcomp.h"
|
||||||
#include "hwc_fbupdate.h"
|
#include "hwc_fbupdate.h"
|
||||||
@@ -1085,6 +1086,7 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
ctx->listStats[dpy].renderBufIndexforABC = -1;
|
ctx->listStats[dpy].renderBufIndexforABC = -1;
|
||||||
ctx->listStats[dpy].secureRGBCount = 0;
|
ctx->listStats[dpy].secureRGBCount = 0;
|
||||||
ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
|
ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
|
||||||
|
ctx->listStats[dpy].cursorLayerPresent = false;
|
||||||
uint32_t refreshRate = 0;
|
uint32_t refreshRate = 0;
|
||||||
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
|
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
|
||||||
int s3dFormat = HAL_NO_3D;
|
int s3dFormat = HAL_NO_3D;
|
||||||
@@ -1116,6 +1118,12 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
|
if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Valid cursor must be the top most layer
|
||||||
|
if((int)i == (ctx->listStats[dpy].numAppLayers - 1) &&
|
||||||
|
isCursorLayer(&list->hwLayers[i])) {
|
||||||
|
ctx->listStats[dpy].cursorLayerPresent = true;
|
||||||
|
}
|
||||||
|
|
||||||
//reset yuv indices
|
//reset yuv indices
|
||||||
ctx->listStats[dpy].yuvIndices[i] = -1;
|
ctx->listStats[dpy].yuvIndices[i] = -1;
|
||||||
ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
|
ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
|
||||||
@@ -1942,6 +1950,46 @@ void updateSource(eTransform& orient, Whf& whf,
|
|||||||
crop.bottom = transformedCrop.y + transformedCrop.h;
|
crop.bottom = transformedCrop.y + transformedCrop.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer) {
|
||||||
|
if(dpy > HWC_DISPLAY_PRIMARY) {
|
||||||
|
// HWCursor not supported on secondary displays
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
|
hwc_rect dst = layer->displayFrame;
|
||||||
|
hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
|
||||||
|
int srcW = src.right - src.left;
|
||||||
|
int srcH = src.bottom - src.top;
|
||||||
|
int dstW = dst.right - dst.left;
|
||||||
|
int dstH = dst.bottom - dst.top;
|
||||||
|
|
||||||
|
Whf whf(getWidth(hnd), getHeight(hnd), hnd->format);
|
||||||
|
Dim crop(src.left, src.top, srcW, srcH);
|
||||||
|
Dim dest(dst.left, dst.top, dstW, dstH);
|
||||||
|
|
||||||
|
ovutils::PipeArgs pargs(ovutils::OV_MDP_FLAGS_NONE,
|
||||||
|
whf,
|
||||||
|
Z_SYSTEM_ALLOC,
|
||||||
|
ovutils::ROT_FLAGS_NONE,
|
||||||
|
layer->planeAlpha,
|
||||||
|
(ovutils::eBlending)
|
||||||
|
getBlending(layer->blending));
|
||||||
|
|
||||||
|
ALOGD_IF(HWC_UTILS_DEBUG, "%s: CursorInfo: w = %d h = %d "
|
||||||
|
"crop [%d, %d, %d, %d] dst [%d, %d, %d, %d]", __FUNCTION__,
|
||||||
|
getWidth(hnd), getHeight(hnd), src.left, src.top, srcW, srcH,
|
||||||
|
dst.left, dst.top, dstW, dstH);
|
||||||
|
|
||||||
|
return HWCursor::getInstance()->config(fd, (void*)hnd->base, pargs,
|
||||||
|
crop, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeHwCursor(const int fd, int dpy) {
|
||||||
|
if (dpy == HWC_DISPLAY_PRIMARY) {
|
||||||
|
HWCursor::getInstance()->free(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
|
int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
|
||||||
if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
|
if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ struct ListStats {
|
|||||||
uint32_t refreshRateRequest;
|
uint32_t refreshRateRequest;
|
||||||
// Flag related to windowboxing feature
|
// Flag related to windowboxing feature
|
||||||
bool mAIVVideoMode;
|
bool mAIVVideoMode;
|
||||||
|
// curser layer info
|
||||||
|
bool cursorLayerPresent;
|
||||||
};
|
};
|
||||||
|
|
||||||
//PTOR Comp info
|
//PTOR Comp info
|
||||||
@@ -414,6 +416,9 @@ int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
|
|||||||
void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
|
void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
|
||||||
hwc_rect_t& crop, overlay::Rotator *rot);
|
hwc_rect_t& crop, overlay::Rotator *rot);
|
||||||
|
|
||||||
|
bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer);
|
||||||
|
void freeHwCursor(const int fd, int dpy);
|
||||||
|
|
||||||
bool isZoomModeEnabled(hwc_rect_t crop);
|
bool isZoomModeEnabled(hwc_rect_t crop);
|
||||||
void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
|
void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
|
||||||
void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
|
void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
|
||||||
@@ -497,6 +502,11 @@ static inline bool isAIVCCLayer(const hwc_layer_1_t* l) {
|
|||||||
return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
|
return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isCursorLayer(const hwc_layer_1_t* l) {
|
||||||
|
return (UNLIKELY(l && (l->flags & HWC_IS_CURSOR_LAYER)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns true if the buffer is yuv
|
// Returns true if the buffer is yuv
|
||||||
static inline bool isYuvBuffer(const private_handle_t* hnd) {
|
static inline bool isYuvBuffer(const private_handle_t* hnd) {
|
||||||
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
|
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
|
||||||
@@ -718,6 +728,10 @@ inline bool isSecurePresent(hwc_context_t *ctx, int dpy) {
|
|||||||
return ctx->listStats[dpy].isSecurePresent;
|
return ctx->listStats[dpy].isSecurePresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isCursorPresent (hwc_context_t *ctx, int dpy) {
|
||||||
|
return ctx->listStats[dpy].cursorLayerPresent;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
|
static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
|
||||||
return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
|
return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
|
||||||
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
|
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ LOCAL_SRC_FILES := \
|
|||||||
overlayMdpRot.cpp \
|
overlayMdpRot.cpp \
|
||||||
overlayMdssRot.cpp \
|
overlayMdssRot.cpp \
|
||||||
overlayWriteback.cpp \
|
overlayWriteback.cpp \
|
||||||
|
overlayCursor.cpp \
|
||||||
pipes/overlayGenPipe.cpp
|
pipes/overlayGenPipe.cpp
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
147
liboverlay/overlayCursor.cpp
Normal file
147
liboverlay/overlayCursor.cpp
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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 "overlay.h"
|
||||||
|
#include "overlayCursor.h"
|
||||||
|
#include "mdpWrapper.h"
|
||||||
|
|
||||||
|
namespace overlay {
|
||||||
|
|
||||||
|
HWCursor* HWCursor::sHwCursor = 0;
|
||||||
|
|
||||||
|
//=========== class HWCursor =================================================
|
||||||
|
HWCursor* HWCursor::getInstance() {
|
||||||
|
if (sHwCursor == NULL) {
|
||||||
|
sHwCursor = new HWCursor();
|
||||||
|
}
|
||||||
|
return sHwCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HWCursor::config(const int fd, void* base, PipeArgs& pargs,
|
||||||
|
Dim& crop, Dim& dest) {
|
||||||
|
bool ret = true;
|
||||||
|
fb_cursor *cursor = &mfbCursor;
|
||||||
|
fb_image cursorImage;
|
||||||
|
|
||||||
|
cursor->set = FB_CUR_SETIMAGE | FB_CUR_SETPOS;
|
||||||
|
cursor->enable = (uint16_t)1;
|
||||||
|
cursor->rop = 0,
|
||||||
|
cursor->mask = NULL;
|
||||||
|
cursor->hot.x = (uint16_t)crop.x;
|
||||||
|
cursor->hot.y = (uint16_t)crop.y;
|
||||||
|
|
||||||
|
cursorImage.dx = dest.x;
|
||||||
|
cursorImage.dy = dest.y;
|
||||||
|
cursorImage.width = pargs.whf.w;
|
||||||
|
cursorImage.height = pargs.whf.h;
|
||||||
|
cursorImage.fg_color = pargs.planeAlpha; // Hint for PMA
|
||||||
|
cursorImage.bg_color = 0xffffff00; // RGBA
|
||||||
|
cursorImage.depth = 32;
|
||||||
|
cursorImage.data = (char*)base;
|
||||||
|
|
||||||
|
cursor->image = cursorImage;
|
||||||
|
|
||||||
|
if (!setCursor(fd)) {
|
||||||
|
ALOGE("%s: Failed to setup HW cursor", __FUNCTION__);
|
||||||
|
ret = false;
|
||||||
|
memset(cursor, 0, sizeof(fb_cursor));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HWCursor::setPositionAsync(const int fd, int x, int y) {
|
||||||
|
bool ret = true;
|
||||||
|
if (isCursorSet()) {
|
||||||
|
fb_cursor *cursor = &mfbCursor;
|
||||||
|
cursor->set = FB_CUR_SETPOS;
|
||||||
|
cursor->image.dx = x;
|
||||||
|
cursor->image.dy = y;
|
||||||
|
if (!setCursor(fd)) {
|
||||||
|
ALOGE("%s: Failed to set position x = %d y = %d", __FUNCTION__, x, y);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HWCursor::free(const int fd) {
|
||||||
|
fb_cursor *cursor = &mfbCursor;
|
||||||
|
fb_image cursorImage;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if(!cursor->enable) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor->enable = (uint16_t)0;
|
||||||
|
|
||||||
|
if (!setCursor(fd)) {
|
||||||
|
ALOGE("%s: Failed to free cursor hw", __FUNCTION__);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
memset(cursor, 0, sizeof(fb_cursor));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HWCursor::setCursor(const int fd) {
|
||||||
|
bool ret = true;
|
||||||
|
ATRACE_CALL();
|
||||||
|
fb_cursor *cursor = &mfbCursor;
|
||||||
|
|
||||||
|
if(fd <= 0) {
|
||||||
|
ALOGE("%s: Invalid fd", fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, MSMFB_CURSOR, cursor) < 0) {
|
||||||
|
ALOGE("%s: Failed to call ioctl MSMFB_CURSOR err=%s\n", __FUNCTION__,
|
||||||
|
strerror(errno));
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HWCursor::getDump(char* buf, size_t len) {
|
||||||
|
char cursordump[len];
|
||||||
|
fb_cursor* cursor = &mfbCursor;
|
||||||
|
if (cursor->enable) {
|
||||||
|
snprintf(cursordump, sizeof(cursordump),
|
||||||
|
"HWCursor on Primary: src w=%d h=%d\n"
|
||||||
|
"\tsrc_rect x=%d y=%d w=%d h=%d\n"
|
||||||
|
"\tdst_rect x=%d y=%d w=%d h=%d\n\n", cursor->image.width,
|
||||||
|
cursor->image.height, cursor->hot.x, cursor->hot.y,
|
||||||
|
cursor->image.width, cursor->image.height,
|
||||||
|
cursor->image.dx, cursor->image.dy, cursor->image.width,
|
||||||
|
cursor->image.height);
|
||||||
|
strlcat(buf, cursordump, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace overlay
|
||||||
60
liboverlay/overlayCursor.h
Normal file
60
liboverlay/overlayCursor.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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 OVERLAY_CURSOR_H
|
||||||
|
#define OVERLAY_CURSOR_H
|
||||||
|
|
||||||
|
#include "overlay.h"
|
||||||
|
#include "overlayUtils.h"
|
||||||
|
|
||||||
|
namespace overlay {
|
||||||
|
|
||||||
|
using namespace overlay;
|
||||||
|
using namespace overlay::utils;
|
||||||
|
|
||||||
|
// HW Cursor Helper
|
||||||
|
class HWCursor {
|
||||||
|
public:
|
||||||
|
static HWCursor* getInstance();
|
||||||
|
bool config(const int fd, void* base, PipeArgs& pargs, Dim& crop,
|
||||||
|
Dim& dest);
|
||||||
|
bool setPositionAsync(const int fd, int x, int y);
|
||||||
|
bool free(const int fd);
|
||||||
|
bool isCursorSet() { return mfbCursor.enable; }
|
||||||
|
void getDump(char* buf, size_t len);
|
||||||
|
private:
|
||||||
|
HWCursor() { memset(&mfbCursor, 0, sizeof(mfbCursor)); }
|
||||||
|
bool setCursor(const int fd);
|
||||||
|
fb_cursor mfbCursor;
|
||||||
|
|
||||||
|
static HWCursor* sHwCursor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OVERLAY_CURSOR_H
|
||||||
@@ -91,6 +91,7 @@ MDPVersion::MDPVersion()
|
|||||||
mRGBPipes = 0;
|
mRGBPipes = 0;
|
||||||
mVGPipes = 0;
|
mVGPipes = 0;
|
||||||
mDMAPipes = 0;
|
mDMAPipes = 0;
|
||||||
|
mCursorPipes = 0;
|
||||||
mFeatures = 0;
|
mFeatures = 0;
|
||||||
mMDPUpscale = 1;
|
mMDPUpscale = 1;
|
||||||
mMDPDownscale = 1;
|
mMDPDownscale = 1;
|
||||||
@@ -110,6 +111,7 @@ MDPVersion::MDPVersion()
|
|||||||
// Default width of MDSS SSPP. For layer resolutions beyond this, we drive
|
// Default width of MDSS SSPP. For layer resolutions beyond this, we drive
|
||||||
// using two SSPP's.
|
// using two SSPP's.
|
||||||
mMaxPipeWidth = 2048;
|
mMaxPipeWidth = 2048;
|
||||||
|
mMaxCursorSize = 0;
|
||||||
|
|
||||||
updatePanelInfo();
|
updatePanelInfo();
|
||||||
|
|
||||||
@@ -309,6 +311,10 @@ bool MDPVersion::updateSysFsInfo() {
|
|||||||
else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
|
else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
|
||||||
mDMAPipes = (uint8_t)atoi(tokens[1]);
|
mDMAPipes = (uint8_t)atoi(tokens[1]);
|
||||||
}
|
}
|
||||||
|
else if(!strncmp(tokens[0], "cursor_pipes",
|
||||||
|
strlen("cursor_pipes"))) {
|
||||||
|
mCursorPipes = (uint8_t)atoi(tokens[1]);
|
||||||
|
}
|
||||||
else if(!strncmp(tokens[0], "blending_stages",
|
else if(!strncmp(tokens[0], "blending_stages",
|
||||||
strlen("blending_stages"))) {
|
strlen("blending_stages"))) {
|
||||||
mBlendStages = (uint8_t)atoi(tokens[1]);
|
mBlendStages = (uint8_t)atoi(tokens[1]);
|
||||||
@@ -354,6 +360,9 @@ bool MDPVersion::updateSysFsInfo() {
|
|||||||
mRotDownscale = true;
|
mRotDownscale = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(!strncmp(tokens[0], "max_cursor_size",
|
||||||
|
strlen("max_cursor_size"))) {
|
||||||
|
mMaxCursorSize = atoi(tokens[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,8 +398,8 @@ bool MDPVersion::updateSysFsInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
|
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
|
||||||
"mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
|
"mVGPipes:%d mCursorPipes:%d", __FUNCTION__, mMDPVersion,
|
||||||
mRGBPipes, mVGPipes);
|
mMdpRev, mRGBPipes, mVGPipes, mCursorPipes);
|
||||||
ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
|
ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
|
||||||
__FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
|
__FUNCTION__, mDMAPipes, mMDPDownscale, mFeatures);
|
||||||
ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__, mLowBw,
|
ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__, mLowBw,
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ public:
|
|||||||
uint8_t getRGBPipes() { return mRGBPipes; }
|
uint8_t getRGBPipes() { return mRGBPipes; }
|
||||||
uint8_t getVGPipes() { return mVGPipes; }
|
uint8_t getVGPipes() { return mVGPipes; }
|
||||||
uint8_t getDMAPipes() { return mDMAPipes; }
|
uint8_t getDMAPipes() { return mDMAPipes; }
|
||||||
|
uint8_t getCursorPipes() { return mCursorPipes; }
|
||||||
uint8_t getBlendStages() { return mBlendStages; }
|
uint8_t getBlendStages() { return mBlendStages; }
|
||||||
bool supportsDecimation();
|
bool supportsDecimation();
|
||||||
uint32_t getMaxMDPDownscale();
|
uint32_t getMaxMDPDownscale();
|
||||||
@@ -140,6 +141,7 @@ public:
|
|||||||
uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
|
uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
|
||||||
uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
|
uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
|
||||||
uint32_t getMaxPipeWidth() const { return mMaxPipeWidth; }
|
uint32_t getMaxPipeWidth() const { return mMaxPipeWidth; }
|
||||||
|
uint32_t getMaxCursorSize() const { return mMaxCursorSize; }
|
||||||
bool hasMinCropWidthLimitation() const;
|
bool hasMinCropWidthLimitation() const;
|
||||||
bool isSrcSplit() const;
|
bool isSrcSplit() const;
|
||||||
bool isSrcSplitAlways() const;
|
bool isSrcSplitAlways() const;
|
||||||
@@ -166,6 +168,7 @@ private:
|
|||||||
uint8_t mRGBPipes;
|
uint8_t mRGBPipes;
|
||||||
uint8_t mVGPipes;
|
uint8_t mVGPipes;
|
||||||
uint8_t mDMAPipes;
|
uint8_t mDMAPipes;
|
||||||
|
uint8_t mCursorPipes;
|
||||||
uint8_t mBlendStages;
|
uint8_t mBlendStages;
|
||||||
uint32_t mFeatures;
|
uint32_t mFeatures;
|
||||||
uint32_t mMDPDownscale;
|
uint32_t mMDPDownscale;
|
||||||
@@ -182,6 +185,7 @@ private:
|
|||||||
bool mRotDownscale;
|
bool mRotDownscale;
|
||||||
uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
|
uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
|
||||||
uint32_t mMaxPipeWidth; //maximum x-res of the mdp pipe.
|
uint32_t mMaxPipeWidth; //maximum x-res of the mdp pipe.
|
||||||
|
uint32_t mMaxCursorSize; //maximum size supported by hw cursor
|
||||||
};
|
};
|
||||||
}; //namespace qdutils
|
}; //namespace qdutils
|
||||||
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
|
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
|
||||||
|
|||||||
Reference in New Issue
Block a user