overlay: Add writeback support

Add explicit writeback display type, writeback ioctls, memory mgmt,
writeback class, writeback obj manager class to overlay.

Change-Id: I171e60cea5ed8f6649859e3eb189df37b39962f1
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
new file mode 100644
index 0000000..b6ed53c
--- /dev/null
+++ b/liboverlay/overlayWriteback.cpp
@@ -0,0 +1,215 @@
+/*
+* 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"
+
+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) {
+    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(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
+            ALOGE("%s 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, bool isSecure) {
+    if(!mWbMem.manageMem(size, isSecure)) {
+        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());
+}
+
+//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;
+    }
+}
+
+Writeback *Writeback::sWb = 0;
+bool Writeback::sUsed = false;
+
+} //namespace overlay