Merge "hwc: Add assertive display support."
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
1e67338868
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES := hwc.cpp \
|
|||||||
hwc_mdpcomp.cpp \
|
hwc_mdpcomp.cpp \
|
||||||
hwc_copybit.cpp \
|
hwc_copybit.cpp \
|
||||||
hwc_qclient.cpp \
|
hwc_qclient.cpp \
|
||||||
hwc_dump_layers.cpp
|
hwc_dump_layers.cpp \
|
||||||
|
hwc_ad.cpp
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "hwc_dump_layers.h"
|
#include "hwc_dump_layers.h"
|
||||||
#include "external.h"
|
#include "external.h"
|
||||||
#include "hwc_copybit.h"
|
#include "hwc_copybit.h"
|
||||||
|
#include "hwc_ad.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
|
|
||||||
using namespace qhwc;
|
using namespace qhwc;
|
||||||
@@ -107,6 +108,8 @@ static void reset(hwc_context_t *ctx, int numDisplays,
|
|||||||
if(ctx->mCopyBit[i])
|
if(ctx->mCopyBit[i])
|
||||||
ctx->mCopyBit[i]->reset();
|
ctx->mCopyBit[i]->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->mAD->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear prev layer prop flags and realloc for current frame
|
//clear prev layer prop flags and realloc for current frame
|
||||||
|
|||||||
261
libhwcomposer/hwc_ad.cpp
Normal file
261
libhwcomposer/hwc_ad.cpp
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
* * Neither the name of The Linux Foundation. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <overlay.h>
|
||||||
|
#include <overlayUtils.h>
|
||||||
|
#include <overlayWriteback.h>
|
||||||
|
#include <mdp_version.h>
|
||||||
|
#include "hwc_ad.h"
|
||||||
|
#include "hwc_utils.h"
|
||||||
|
#include "external.h"
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
using namespace overlay;
|
||||||
|
using namespace overlay::utils;
|
||||||
|
namespace qhwc {
|
||||||
|
|
||||||
|
//Opens writeback framebuffer and returns fd.
|
||||||
|
static int openWbFb() {
|
||||||
|
int wbFd = -1;
|
||||||
|
//Check opening which FB would connect LM to WB
|
||||||
|
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
||||||
|
if(wbFbNum >= 0) {
|
||||||
|
char wbFbPath[256];
|
||||||
|
snprintf (wbFbPath, sizeof(wbFbPath),
|
||||||
|
"/sys/class/graphics/fb%d", wbFbNum);
|
||||||
|
//Opening writeback fb first time would create ad node if the device
|
||||||
|
//supports adaptive display
|
||||||
|
wbFd = open(wbFbPath, O_RDONLY);
|
||||||
|
if(wbFd < 0) {
|
||||||
|
ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
|
||||||
|
__func__, wbFbNum, strerror(errno));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
|
||||||
|
}
|
||||||
|
return wbFd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void closeWbFb(int& fd) {
|
||||||
|
if(fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Invalid fd %d", __func__, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper to write data to ad node
|
||||||
|
static void adWrite(const int& value) {
|
||||||
|
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
||||||
|
char wbFbPath[256];
|
||||||
|
snprintf (wbFbPath, sizeof(wbFbPath),
|
||||||
|
"/sys/class/graphics/fb%d/ad", wbFbNum);
|
||||||
|
int adFd = open(wbFbPath, O_WRONLY);
|
||||||
|
if(adFd >= 0) {
|
||||||
|
char opStr[4] = "";
|
||||||
|
snprintf(opStr, sizeof(opStr), "%d", value);
|
||||||
|
int ret = write(adFd, opStr, strlen(opStr));
|
||||||
|
if(ret < 0) {
|
||||||
|
ALOGE("%s: Failed to write %d with error %s",
|
||||||
|
__func__, value, strerror(errno));
|
||||||
|
} else if (ret == 0){
|
||||||
|
ALOGE("%s Nothing written to ad", __func__);
|
||||||
|
} else {
|
||||||
|
ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value);
|
||||||
|
}
|
||||||
|
close(adFd);
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
|
||||||
|
__func__, wbFbNum, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Helper to read data from ad node
|
||||||
|
static int adRead() {
|
||||||
|
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
||||||
|
int ret = -1;
|
||||||
|
char wbFbPath[256];
|
||||||
|
snprintf (wbFbPath, sizeof(wbFbPath),
|
||||||
|
"/sys/class/graphics/fb%d/ad", wbFbNum);
|
||||||
|
int adFd = open(wbFbPath, O_RDONLY);
|
||||||
|
if(adFd >= 0) {
|
||||||
|
char opStr[4] = {'\0'};
|
||||||
|
if(read(adFd, opStr, strlen(opStr)) >= 0) {
|
||||||
|
//Should return -1, 0 or 1
|
||||||
|
ret = atoi(opStr);
|
||||||
|
ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Read from ad node failed with error %s", __func__,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
close(adFd);
|
||||||
|
} else {
|
||||||
|
ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
|
||||||
|
__func__, wbFbNum, strerror(errno));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertiveDisplay::AssertiveDisplay() :mWbFd(-1), mDoable(false),
|
||||||
|
mFeatureEnabled(false), mDest(overlay::utils::OV_INVALID) {
|
||||||
|
int fd = openWbFb();
|
||||||
|
if(fd >= 0) {
|
||||||
|
//-1 means feature is disabled on device
|
||||||
|
// 0 means feature exists but turned off, will be turned on by hwc
|
||||||
|
// 1 means feature is turned on by hwc
|
||||||
|
if(adRead() >= 0) {
|
||||||
|
ALOGD_IF(DEBUG, "Assertive display feature supported");
|
||||||
|
mFeatureEnabled = true;
|
||||||
|
}
|
||||||
|
closeWbFb(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertiveDisplay::markDoable(hwc_context_t *ctx,
|
||||||
|
const hwc_display_contents_1_t* list) {
|
||||||
|
mDoable = false;
|
||||||
|
if(mFeatureEnabled &&
|
||||||
|
!ctx->mExtDisplay->isExternalConnected() &&
|
||||||
|
ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) {
|
||||||
|
int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0];
|
||||||
|
const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
|
||||||
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
|
if(hnd && hnd->width <= qdutils::MAX_DISPLAY_DIM) {
|
||||||
|
mDoable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssertiveDisplay::prepare(hwc_context_t *ctx,
|
||||||
|
const hwc_rect_t& crop,
|
||||||
|
const Whf& whf,
|
||||||
|
const private_handle_t *hnd) {
|
||||||
|
if(!isDoable()) {
|
||||||
|
if(isModeOn()) {
|
||||||
|
//Cleanup one time during this switch
|
||||||
|
const int off = 0;
|
||||||
|
adWrite(off);
|
||||||
|
closeWbFb(mWbFd);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ovutils::eDest dest = ctx->mOverlay->nextPipe(ovutils::OV_MDP_PIPE_VG,
|
||||||
|
overlay::Overlay::DPY_WRITEBACK, Overlay::MIXER_DEFAULT);
|
||||||
|
if(dest == OV_INVALID) {
|
||||||
|
ALOGE("%s failed: No VG pipe available", __func__);
|
||||||
|
mDoable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
|
||||||
|
if(!wb->configureDpyInfo(hnd->width, hnd->height)) {
|
||||||
|
ALOGE("%s: config display failed", __func__);
|
||||||
|
mDoable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmpW, tmpH, size;
|
||||||
|
int format = ovutils::getHALFormat(wb->getOutputFormat());
|
||||||
|
if(format < 0) {
|
||||||
|
ALOGE("%s invalid format %d", __func__, format);
|
||||||
|
mDoable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = getBufferSizeAndDimensions(hnd->width, hnd->height,
|
||||||
|
format, tmpW, tmpH);
|
||||||
|
|
||||||
|
if(!wb->configureMemory(size, isSecureBuffer(hnd))) {
|
||||||
|
ALOGE("%s: config memory failed", __func__);
|
||||||
|
mDoable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE;
|
||||||
|
if(isSecureBuffer(hnd)) {
|
||||||
|
ovutils::setMdpFlags(mdpFlags,
|
||||||
|
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeArgs parg(mdpFlags, whf, ZORDER_0, IS_FG_OFF,
|
||||||
|
ROT_FLAGS_NONE);
|
||||||
|
hwc_rect_t dst = crop; //input same as output
|
||||||
|
|
||||||
|
if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL,
|
||||||
|
dest) < 0) {
|
||||||
|
ALOGE("%s: configMdp failed", __func__);
|
||||||
|
mDoable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDest = dest;
|
||||||
|
if(!isModeOn()) {
|
||||||
|
mWbFd = openWbFb();
|
||||||
|
if(mWbFd >= 0) {
|
||||||
|
//write to sysfs, one time during this switch
|
||||||
|
const int on = 1;
|
||||||
|
adWrite(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
|
||||||
|
if(!isDoable() || !isModeOn()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) {
|
||||||
|
ALOGE("%s: queueBuffer failed", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
if(!wb->writeSync()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AssertiveDisplay::getDstFd(hwc_context_t *ctx) const {
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
return wb->getDstFd();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AssertiveDisplay::getDstOffset(hwc_context_t *ctx) const {
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
return wb->getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
67
libhwcomposer/hwc_ad.h
Normal file
67
libhwcomposer/hwc_ad.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013 The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials provided
|
||||||
|
* with the distribution.
|
||||||
|
* * Neither the name of The Linux Foundation. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HWC_AD_H
|
||||||
|
#define HWC_AD_H
|
||||||
|
|
||||||
|
#include <overlayUtils.h>
|
||||||
|
#include <hwc_utils.h>
|
||||||
|
|
||||||
|
struct hwc_context_t;
|
||||||
|
|
||||||
|
namespace qhwc {
|
||||||
|
|
||||||
|
class AssertiveDisplay {
|
||||||
|
public:
|
||||||
|
AssertiveDisplay();
|
||||||
|
void markDoable(hwc_context_t *ctx, const hwc_display_contents_1_t* list);
|
||||||
|
bool prepare(hwc_context_t *ctx, const hwc_rect_t& crop,
|
||||||
|
const overlay::utils::Whf& whf,
|
||||||
|
const private_handle_t *hnd);
|
||||||
|
bool draw(hwc_context_t *ctx, int fd, uint32_t offset);
|
||||||
|
//Resets a few members on each draw round
|
||||||
|
void reset() { mDoable = false;
|
||||||
|
mDest = overlay::utils::OV_INVALID;
|
||||||
|
}
|
||||||
|
bool isDoable() const { return mDoable; }
|
||||||
|
bool isModeOn() const { return (mWbFd >= 0); }
|
||||||
|
int getDstFd(hwc_context_t *ctx) const;
|
||||||
|
uint32_t getDstOffset(hwc_context_t *ctx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//State of feature turned on and off
|
||||||
|
int mWbFd;
|
||||||
|
bool mDoable;
|
||||||
|
//State of feature existence on certain devices and configs.
|
||||||
|
bool mFeatureEnabled;
|
||||||
|
overlay::utils::eDest mDest;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "qdMetaData.h"
|
#include "qdMetaData.h"
|
||||||
#include "mdp_version.h"
|
#include "mdp_version.h"
|
||||||
#include "hwc_fbupdate.h"
|
#include "hwc_fbupdate.h"
|
||||||
|
#include "hwc_ad.h"
|
||||||
#include <overlayRotator.h>
|
#include <overlayRotator.h>
|
||||||
|
|
||||||
using namespace overlay;
|
using namespace overlay;
|
||||||
@@ -453,6 +454,10 @@ bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ctx->mAD->isDoable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//If all above hard conditions are met we can do full or partial MDP comp.
|
//If all above hard conditions are met we can do full or partial MDP comp.
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if(fullMDPComp(ctx, list)) {
|
if(fullMDPComp(ctx, list)) {
|
||||||
@@ -955,6 +960,14 @@ bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
|
|
||||||
int fd = hnd->fd;
|
int fd = hnd->fd;
|
||||||
uint32_t offset = hnd->offset;
|
uint32_t offset = hnd->offset;
|
||||||
|
|
||||||
|
if(ctx->mAD->isModeOn()) {
|
||||||
|
if(ctx->mAD->draw(ctx, fd, offset)) {
|
||||||
|
fd = ctx->mAD->getDstFd(ctx);
|
||||||
|
offset = ctx->mAD->getDstOffset(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
|
Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
|
||||||
if(rot) {
|
if(rot) {
|
||||||
if(!rot->queueBuffer(fd, offset))
|
if(!rot->queueBuffer(fd, offset))
|
||||||
@@ -1150,6 +1163,13 @@ bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
int fd = hnd->fd;
|
int fd = hnd->fd;
|
||||||
int offset = hnd->offset;
|
int offset = hnd->offset;
|
||||||
|
|
||||||
|
if(ctx->mAD->isModeOn()) {
|
||||||
|
if(ctx->mAD->draw(ctx, fd, offset)) {
|
||||||
|
fd = ctx->mAD->getDstFd(ctx);
|
||||||
|
offset = ctx->mAD->getDstOffset(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(rot) {
|
if(rot) {
|
||||||
rot->queueBuffer(fd, offset);
|
rot->queueBuffer(fd, offset);
|
||||||
fd = rot->getDstMemId();
|
fd = rot->getDstMemId();
|
||||||
|
|||||||
@@ -27,9 +27,11 @@
|
|||||||
#include <gralloc_priv.h>
|
#include <gralloc_priv.h>
|
||||||
#include <overlay.h>
|
#include <overlay.h>
|
||||||
#include <overlayRotator.h>
|
#include <overlayRotator.h>
|
||||||
|
#include <overlayWriteback.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"
|
||||||
|
#include "hwc_ad.h"
|
||||||
#include "mdp_version.h"
|
#include "mdp_version.h"
|
||||||
#include "hwc_copybit.h"
|
#include "hwc_copybit.h"
|
||||||
#include "hwc_dump_layers.h"
|
#include "hwc_dump_layers.h"
|
||||||
@@ -161,6 +163,7 @@ void initContext(hwc_context_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MDPComp::init(ctx);
|
MDPComp::init(ctx);
|
||||||
|
ctx->mAD = new AssertiveDisplay();
|
||||||
|
|
||||||
ctx->vstate.enable = false;
|
ctx->vstate.enable = false;
|
||||||
ctx->vstate.fakevsync = false;
|
ctx->vstate.fakevsync = false;
|
||||||
@@ -234,6 +237,10 @@ void closeContext(hwc_context_t *ctx)
|
|||||||
ctx->mLayerRotMap[i] = NULL;
|
ctx->mLayerRotMap[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(ctx->mAD) {
|
||||||
|
delete ctx->mAD;
|
||||||
|
ctx->mAD = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -475,6 +482,9 @@ void setListStats(hwc_context_t *ctx,
|
|||||||
if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
|
if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
|
||||||
ctx->mVideoTransFlag = true;
|
ctx->mVideoTransFlag = true;
|
||||||
}
|
}
|
||||||
|
if(dpy == HWC_DISPLAY_PRIMARY) {
|
||||||
|
ctx->mAD->markDoable(ctx, list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -991,6 +1001,13 @@ int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
|
|||||||
setMdpFlags(layer, mdpFlags, downscale, transform);
|
setMdpFlags(layer, mdpFlags, downscale, transform);
|
||||||
trimLayer(ctx, dpy, transform, crop, dst);
|
trimLayer(ctx, dpy, transform, crop, dst);
|
||||||
|
|
||||||
|
//Will do something only if feature enabled and conditions suitable
|
||||||
|
//hollow call otherwise
|
||||||
|
if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
whf.format = wb->getOutputFormat();
|
||||||
|
}
|
||||||
|
|
||||||
if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
|
if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
|
||||||
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
|
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
|
||||||
*rot = ctx->mRotMgr->getNext();
|
*rot = ctx->mRotMgr->getNext();
|
||||||
@@ -1069,6 +1086,13 @@ int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
|
|||||||
setMdpFlags(layer, mdpFlagsL, 0, transform);
|
setMdpFlags(layer, mdpFlagsL, 0, transform);
|
||||||
trimLayer(ctx, dpy, transform, crop, dst);
|
trimLayer(ctx, dpy, transform, crop, dst);
|
||||||
|
|
||||||
|
//Will do something only if feature enabled and conditions suitable
|
||||||
|
//hollow call otherwise
|
||||||
|
if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
|
||||||
|
overlay::Writeback *wb = overlay::Writeback::getInstance();
|
||||||
|
whf.format = wb->getOutputFormat();
|
||||||
|
}
|
||||||
|
|
||||||
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
|
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
|
||||||
(*rot) = ctx->mRotMgr->getNext();
|
(*rot) = ctx->mRotMgr->getNext();
|
||||||
if((*rot) == NULL) return -1;
|
if((*rot) == NULL) return -1;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class IVideoOverlay;
|
|||||||
class MDPComp;
|
class MDPComp;
|
||||||
class CopyBit;
|
class CopyBit;
|
||||||
class HwcDebug;
|
class HwcDebug;
|
||||||
|
class AssertiveDisplay;
|
||||||
|
|
||||||
|
|
||||||
struct MDPInfo {
|
struct MDPInfo {
|
||||||
@@ -321,6 +322,7 @@ struct hwc_context_t {
|
|||||||
qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
|
qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
|
||||||
qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
|
qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
|
||||||
qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
|
qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
|
||||||
|
qhwc::AssertiveDisplay *mAD;
|
||||||
|
|
||||||
// No animation on External display feature
|
// No animation on External display feature
|
||||||
// Notifies hwcomposer about the device orientation before animation.
|
// Notifies hwcomposer about the device orientation before animation.
|
||||||
|
|||||||
@@ -73,12 +73,13 @@ bool WritebackMem::dealloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=========== class Writeback =================================================
|
//=========== class Writeback =================================================
|
||||||
Writeback::Writeback() : mXres(0), mYres(0) {
|
Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1) {
|
||||||
int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
||||||
if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
|
if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
|
||||||
ALOGE("%s failed to init %s", __func__, Res::fbPath);
|
ALOGE("%s failed to init %s", __func__, Res::fbPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
queryOutputFormat();
|
||||||
startSession();
|
startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +185,17 @@ bool Writeback::writeSync() {
|
|||||||
return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
|
return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Writeback::queryOutputFormat() {
|
||||||
|
struct msmfb_metadata metadata;
|
||||||
|
memset(&metadata, 0 , sizeof(metadata));
|
||||||
|
metadata.op = metadata_op_wb_format;
|
||||||
|
if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) {
|
||||||
|
ALOGE("Error retrieving MDP Writeback format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mOpFmt = metadata.data.mixer_cfg.writeback_format;
|
||||||
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
|
||||||
Writeback *Writeback::getInstance() {
|
Writeback *Writeback::getInstance() {
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ public:
|
|||||||
bool queueBuffer(int opFd, uint32_t opOffset);
|
bool queueBuffer(int opFd, uint32_t opOffset);
|
||||||
uint32_t getOffset() const { return mWbMem.getOffset(); }
|
uint32_t getOffset() const { return mWbMem.getOffset(); }
|
||||||
int getDstFd() const { return mWbMem.getDstFd(); }
|
int getDstFd() const { return mWbMem.getDstFd(); }
|
||||||
|
int getOutputFormat() const { return mOpFmt; }
|
||||||
|
|
||||||
static Writeback* getInstance();
|
static Writeback* getInstance();
|
||||||
static void configBegin() { sUsed = false; }
|
static void configBegin() { sUsed = false; }
|
||||||
@@ -93,11 +94,13 @@ private:
|
|||||||
bool stopSession();
|
bool stopSession();
|
||||||
//Actually block_until_write_done for the usage here.
|
//Actually block_until_write_done for the usage here.
|
||||||
bool dequeueBuffer();
|
bool dequeueBuffer();
|
||||||
|
void queryOutputFormat();
|
||||||
OvFD mFd;
|
OvFD mFd;
|
||||||
WritebackMem mWbMem;
|
WritebackMem mWbMem;
|
||||||
struct msmfb_data mFbData;
|
struct msmfb_data mFbData;
|
||||||
int mXres;
|
int mXres;
|
||||||
int mYres;
|
int mYres;
|
||||||
|
int mOpFmt;
|
||||||
|
|
||||||
static bool sUsed;
|
static bool sUsed;
|
||||||
static Writeback *sWb;
|
static Writeback *sWb;
|
||||||
|
|||||||
Reference in New Issue
Block a user