You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
7.9 KiB
281 lines
7.9 KiB
4 months ago
|
/*
|
||
|
* 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 "overlay.h"
|
||
|
#include "overlayWriteback.h"
|
||
|
#include "mdpWrapper.h"
|
||
|
|
||
|
#define SIZE_1M 0x00100000
|
||
|
|
||
|
namespace overlay {
|
||
|
|
||
|
//=========== class WritebackMem ==============================================
|
||
|
bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
|
||
|
if(mBuf.bufSz() == size) {
|
||
|
return true;
|
||
|
}
|
||
|
if(mBuf.valid()) {
|
||
|
if(!mBuf.close()) {
|
||
|
ALOGE("%s error closing mem", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return alloc(size, isSecure);
|
||
|
}
|
||
|
|
||
|
bool WritebackMem::alloc(uint32_t size, bool isSecure) {
|
||
|
if(!mBuf.open(NUM_BUFS, size, isSecure)){
|
||
|
ALOGE("%s: Failed to open", __func__);
|
||
|
mBuf.close();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
OVASSERT(MAP_FAILED != mBuf.addr(), "MAP failed");
|
||
|
OVASSERT(mBuf.getFD() != -1, "getFd is -1");
|
||
|
|
||
|
mCurrOffsetIndex = 0;
|
||
|
for (uint32_t i = 0; i < NUM_BUFS; i++) {
|
||
|
mOffsets[i] = i * size;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WritebackMem::dealloc() {
|
||
|
bool ret = true;
|
||
|
if(mBuf.valid()) {
|
||
|
ret = mBuf.close();
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
//=========== class Writeback =================================================
|
||
|
Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1), mSecure(false) {
|
||
|
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;
|
||
|
}
|
||
|
startSession();
|
||
|
}
|
||
|
|
||
|
Writeback::~Writeback() {
|
||
|
stopSession();
|
||
|
if (!mFd.close()) {
|
||
|
ALOGE("%s error closing fd", __func__);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Writeback::startSession() {
|
||
|
if(!mdp_wrapper::wbInitStart(mFd.getFD())) {
|
||
|
ALOGE("%s failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::stopSession() {
|
||
|
if(mFd.valid()) {
|
||
|
if(!Overlay::displayCommit(mFd.getFD())) {
|
||
|
ALOGE("%s: displayCommit failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
|
||
|
ALOGE("%s: wbStopTerminate failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
} else {
|
||
|
ALOGE("%s Invalid fd", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::configureDpyInfo(int xres, int yres) {
|
||
|
if(mXres != xres || mYres != yres) {
|
||
|
fb_var_screeninfo vinfo;
|
||
|
memset(&vinfo, 0, sizeof(fb_var_screeninfo));
|
||
|
if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
|
||
|
ALOGE("%s failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
vinfo.xres = xres;
|
||
|
vinfo.yres = yres;
|
||
|
vinfo.xres_virtual = xres;
|
||
|
vinfo.yres_virtual = yres;
|
||
|
vinfo.xoffset = 0;
|
||
|
vinfo.yoffset = 0;
|
||
|
if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) {
|
||
|
ALOGE("%s failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
mXres = xres;
|
||
|
mYres = yres;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::configureMemory(uint32_t size) {
|
||
|
if(!mWbMem.manageMem(size, mSecure)) {
|
||
|
ALOGE("%s failed, memory failure", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::queueBuffer(int opFd, uint32_t opOffset) {
|
||
|
memset(&mFbData, 0, sizeof(struct msmfb_data));
|
||
|
//Queue
|
||
|
mFbData.offset = opOffset;
|
||
|
mFbData.memory_id = opFd;
|
||
|
mFbData.id = 0;
|
||
|
mFbData.flags = 0;
|
||
|
if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) {
|
||
|
ALOGE("%s: queuebuffer failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::dequeueBuffer() {
|
||
|
//Dequeue
|
||
|
mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
|
||
|
if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) {
|
||
|
ALOGE("%s: dequeuebuffer failed", __func__);
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::writeSync(int opFd, uint32_t opOffset) {
|
||
|
if(!queueBuffer(opFd, opOffset)) {
|
||
|
return false;
|
||
|
}
|
||
|
if(!Overlay::displayCommit(mFd.getFD())) {
|
||
|
return false;
|
||
|
}
|
||
|
if(!dequeueBuffer()) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Writeback::writeSync() {
|
||
|
mWbMem.useNextBuffer();
|
||
|
return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
|
||
|
}
|
||
|
|
||
|
bool Writeback::setOutputFormat(int mdpFormat) {
|
||
|
if(mdpFormat != mOpFmt) {
|
||
|
struct msmfb_metadata metadata;
|
||
|
memset(&metadata, 0 , sizeof(metadata));
|
||
|
metadata.op = metadata_op_wb_format;
|
||
|
metadata.data.mixer_cfg.writeback_format = mdpFormat;
|
||
|
if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
|
||
|
ALOGE("Error setting MDP Writeback format");
|
||
|
return false;
|
||
|
}
|
||
|
mOpFmt = mdpFormat;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int Writeback::getOutputFormat() {
|
||
|
if(mOpFmt < 0) {
|
||
|
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 -1;
|
||
|
}
|
||
|
mOpFmt = metadata.data.mixer_cfg.writeback_format;
|
||
|
}
|
||
|
return mOpFmt;
|
||
|
}
|
||
|
|
||
|
bool Writeback::setSecure(bool isSecure) {
|
||
|
if(isSecure != mSecure) {
|
||
|
// Call IOCTL to set WB interface as secure
|
||
|
struct msmfb_metadata metadata;
|
||
|
memset(&metadata, 0 , sizeof(metadata));
|
||
|
metadata.op = metadata_op_wb_secure;
|
||
|
metadata.data.secure_en = isSecure;
|
||
|
if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
|
||
|
ALOGE("Error setting MDP WB secure");
|
||
|
return false;
|
||
|
}
|
||
|
mSecure = isSecure;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//static
|
||
|
|
||
|
Writeback *Writeback::getInstance() {
|
||
|
if(sWb == NULL) {
|
||
|
sWb = new Writeback();
|
||
|
}
|
||
|
sUsed = true;
|
||
|
return sWb;
|
||
|
}
|
||
|
|
||
|
void Writeback::configDone() {
|
||
|
if(sUsed == false && sWb) {
|
||
|
delete sWb;
|
||
|
sWb = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Writeback::clear() {
|
||
|
sUsed = false;
|
||
|
if(sWb) {
|
||
|
delete sWb;
|
||
|
sWb = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Writeback::getDump(char *buf, size_t len) {
|
||
|
if(sWb) {
|
||
|
utils::getDump(buf, len, "WBData", sWb->mFbData);
|
||
|
char outputBufferInfo[256];
|
||
|
snprintf(outputBufferInfo, sizeof(outputBufferInfo),
|
||
|
"OutputBuffer xres=%d yres=%d format=%s\n\n",
|
||
|
sWb->getWidth(), sWb->getHeight(),
|
||
|
utils::getFormatString(sWb->getOutputFormat()));
|
||
|
strlcat(buf, outputBufferInfo, len);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Writeback *Writeback::sWb = 0;
|
||
|
bool Writeback::sUsed = false;
|
||
|
|
||
|
} //namespace overlay
|