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_copybit.cpp \
|
||||
hwc_qclient.cpp \
|
||||
hwc_dump_layers.cpp
|
||||
hwc_dump_layers.cpp \
|
||||
hwc_ad.cpp
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "hwc_dump_layers.h"
|
||||
#include "external.h"
|
||||
#include "hwc_copybit.h"
|
||||
#include "hwc_ad.h"
|
||||
#include "profiler.h"
|
||||
|
||||
using namespace qhwc;
|
||||
@@ -107,6 +108,8 @@ static void reset(hwc_context_t *ctx, int numDisplays,
|
||||
if(ctx->mCopyBit[i])
|
||||
ctx->mCopyBit[i]->reset();
|
||||
}
|
||||
|
||||
ctx->mAD->reset();
|
||||
}
|
||||
|
||||
//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 "mdp_version.h"
|
||||
#include "hwc_fbupdate.h"
|
||||
#include "hwc_ad.h"
|
||||
#include <overlayRotator.h>
|
||||
|
||||
using namespace overlay;
|
||||
@@ -453,6 +454,10 @@ bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ctx->mAD->isDoable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//If all above hard conditions are met we can do full or partial MDP comp.
|
||||
bool ret = false;
|
||||
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;
|
||||
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;
|
||||
if(rot) {
|
||||
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 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) {
|
||||
rot->queueBuffer(fd, offset);
|
||||
fd = rot->getDstMemId();
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
#include <gralloc_priv.h>
|
||||
#include <overlay.h>
|
||||
#include <overlayRotator.h>
|
||||
#include <overlayWriteback.h>
|
||||
#include "hwc_utils.h"
|
||||
#include "hwc_mdpcomp.h"
|
||||
#include "hwc_fbupdate.h"
|
||||
#include "hwc_ad.h"
|
||||
#include "mdp_version.h"
|
||||
#include "hwc_copybit.h"
|
||||
#include "hwc_dump_layers.h"
|
||||
@@ -161,6 +163,7 @@ void initContext(hwc_context_t *ctx)
|
||||
}
|
||||
|
||||
MDPComp::init(ctx);
|
||||
ctx->mAD = new AssertiveDisplay();
|
||||
|
||||
ctx->vstate.enable = false;
|
||||
ctx->vstate.fakevsync = false;
|
||||
@@ -234,6 +237,10 @@ void closeContext(hwc_context_t *ctx)
|
||||
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) {
|
||||
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);
|
||||
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
|
||||
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
|
||||
*rot = ctx->mRotMgr->getNext();
|
||||
@@ -1069,6 +1086,13 @@ int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
|
||||
setMdpFlags(layer, mdpFlagsL, 0, transform);
|
||||
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)) {
|
||||
(*rot) = ctx->mRotMgr->getNext();
|
||||
if((*rot) == NULL) return -1;
|
||||
|
||||
@@ -55,6 +55,7 @@ class IVideoOverlay;
|
||||
class MDPComp;
|
||||
class CopyBit;
|
||||
class HwcDebug;
|
||||
class AssertiveDisplay;
|
||||
|
||||
|
||||
struct MDPInfo {
|
||||
@@ -321,6 +322,7 @@ struct hwc_context_t {
|
||||
qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
|
||||
qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
|
||||
qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
|
||||
qhwc::AssertiveDisplay *mAD;
|
||||
|
||||
// No animation on External display feature
|
||||
// Notifies hwcomposer about the device orientation before animation.
|
||||
|
||||
@@ -73,12 +73,13 @@ bool WritebackMem::dealloc() {
|
||||
}
|
||||
|
||||
//=========== class Writeback =================================================
|
||||
Writeback::Writeback() : mXres(0), mYres(0) {
|
||||
Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1) {
|
||||
int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
|
||||
if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
|
||||
ALOGE("%s failed to init %s", __func__, Res::fbPath);
|
||||
return;
|
||||
}
|
||||
queryOutputFormat();
|
||||
startSession();
|
||||
}
|
||||
|
||||
@@ -184,6 +185,17 @@ bool Writeback::writeSync() {
|
||||
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
|
||||
|
||||
Writeback *Writeback::getInstance() {
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
bool queueBuffer(int opFd, uint32_t opOffset);
|
||||
uint32_t getOffset() const { return mWbMem.getOffset(); }
|
||||
int getDstFd() const { return mWbMem.getDstFd(); }
|
||||
int getOutputFormat() const { return mOpFmt; }
|
||||
|
||||
static Writeback* getInstance();
|
||||
static void configBegin() { sUsed = false; }
|
||||
@@ -93,11 +94,13 @@ private:
|
||||
bool stopSession();
|
||||
//Actually block_until_write_done for the usage here.
|
||||
bool dequeueBuffer();
|
||||
void queryOutputFormat();
|
||||
OvFD mFd;
|
||||
WritebackMem mWbMem;
|
||||
struct msmfb_data mFbData;
|
||||
int mXres;
|
||||
int mYres;
|
||||
int mOpFmt;
|
||||
|
||||
static bool sUsed;
|
||||
static Writeback *sWb;
|
||||
|
||||
Reference in New Issue
Block a user