/*
// Copyright (c) 2014 Intel Corporation 
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include <HwcTrace.h>
#include <Hwcomposer.h>
#include <Dump.h>
#include <UeventObserver.h>

namespace android {
namespace intel {

Hwcomposer* Hwcomposer::sInstance(0);

Hwcomposer::Hwcomposer(IPlatFactory *factory)
    : mProcs(0),
      mDrm(0),
      mPlatFactory(factory),
      mVsyncManager(0),
      mDisplayAnalyzer(0),
      mMultiDisplayObserver(0),
      mUeventObserver(0),
      mPlaneManager(0),
      mBufferManager(0),
      mDisplayContext(0),
      mInitialized(false)
{
    CTRACE();

    mDisplayDevices.setCapacity(IDisplayDevice::DEVICE_COUNT);
    mDisplayDevices.clear();
}

Hwcomposer::~Hwcomposer()
{
    CTRACE();
    deinitialize();
}

bool Hwcomposer::initCheck() const
{
    return mInitialized;
}

bool Hwcomposer::prepare(size_t numDisplays,
                          hwc_display_contents_1_t** displays)
{
    bool ret = true;

    RETURN_FALSE_IF_NOT_INIT();
    ATRACE("display count = %d", numDisplays);

    if (!numDisplays || !displays) {
        ETRACE("invalid parameters");
        return false;
    }

    mDisplayAnalyzer->analyzeContents(numDisplays, displays);

    // disable reclaimed planes
    mPlaneManager->disableReclaimedPlanes();

        if(numDisplays > mDisplayDevices.size())
                numDisplays = mDisplayDevices.size();

    // reclaim all allocated planes if possible
    for (size_t i = 0; i < numDisplays; i++) {
        IDisplayDevice *device = mDisplayDevices.itemAt(i);
        if (!device) {
            VTRACE("device %d doesn't exist", i);
            continue;
        }

        device->prePrepare(displays[i]);
    }

    for (size_t i = 0; i < numDisplays; i++) {
        IDisplayDevice *device = mDisplayDevices.itemAt(i);
        if (!device) {
            VTRACE("device %d doesn't exist", i);
            continue;
        }

        ret = device->prepare(displays[i]);
        if (ret == false) {
            ETRACE("failed to do prepare for device %d", i);
            continue;
        }
    }

    return ret;
}

bool Hwcomposer::commit(size_t numDisplays,
                         hwc_display_contents_1_t **displays)
{
    bool ret = true;

    RETURN_FALSE_IF_NOT_INIT();
    ATRACE("display count = %d", numDisplays);

    if (!numDisplays || !displays) {
        ETRACE("invalid parameters");
        return false;
    }

        if(numDisplays > mDisplayDevices.size())
                numDisplays = mDisplayDevices.size();

    mDisplayContext->commitBegin(numDisplays, displays);

    for (size_t i = 0; i < numDisplays; i++) {
        IDisplayDevice *device = mDisplayDevices.itemAt(i);
        if (!device) {
            VTRACE("device %d doesn't exist", i);
            continue;
        }

        if (!device->isConnected()) {
            VTRACE("device %d is disconnected", i);
            continue;
        }

        ret = device->commit(displays[i], mDisplayContext);
        if (ret == false) {
            ETRACE("failed to do commit for device %d", i);
            continue;
        }
    }

    mDisplayContext->commitEnd(numDisplays, displays);
    // return true always
    return true;
}

bool Hwcomposer::setPowerMode(int disp, int mode)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    if(disp >= mDisplayDevices.size()){
        ETRACE("no device found");
        return false;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return false;
    }

    return device->setPowerMode(mode);
}

int Hwcomposer::getActiveConfig(int disp)
{
    RETURN_NULL_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return -1;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return -1;
    }

    return device->getActiveConfig();
}

bool Hwcomposer::setActiveConfig(int disp, int index)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return false;
    }

    return device->setActiveConfig(index);
}

bool Hwcomposer::setCursorPositionAsync(int disp, int x, int y)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp != HWC_DISPLAY_PRIMARY && disp != HWC_DISPLAY_EXTERNAL) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    return mDisplayContext->setCursorPosition(disp, x, y);
}

bool Hwcomposer::vsyncControl(int disp, int enabled)
{
    RETURN_FALSE_IF_NOT_INIT();
    ATRACE("disp = %d, enabled = %d", disp, enabled);
    return mVsyncManager->handleVsyncControl(disp, enabled ? true : false);
}

bool Hwcomposer::blank(int disp, int blank)
{
    RETURN_FALSE_IF_NOT_INIT();
    ATRACE("disp = %d, blank = %d", disp, blank);

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return false;
    }

    return device->blank(blank ? true : false);
}

bool Hwcomposer::getDisplayConfigs(int disp,
                                      uint32_t *configs,
                                      size_t *numConfigs)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    if(disp >= mDisplayDevices.size()){
        ETRACE("no device found");
        return false;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device %d found", disp);
        return false;
    }

    return device->getDisplayConfigs(configs, numConfigs);
}

bool Hwcomposer::getDisplayAttributes(int disp,
                                         uint32_t config,
                                         const uint32_t *attributes,
                                         int32_t *values)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }
    if(disp >= mDisplayDevices.size()){
        ETRACE("no device found");
        return false;
    }


    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return false;
    }

    return device->getDisplayAttributes(config, attributes, values);
}

bool Hwcomposer::compositionComplete(int disp)
{
    RETURN_FALSE_IF_NOT_INIT();

    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return false;
    }

    mDisplayContext->compositionComplete();

    if(disp >= mDisplayDevices.size()){
        ETRACE("no device found");
        return false;
    }

    IDisplayDevice *device = mDisplayDevices.itemAt(disp);
    if (!device) {
        ETRACE("no device found");
        return false;
    }

    return device->compositionComplete();
}

void Hwcomposer::vsync(int disp, int64_t timestamp)
{
    RETURN_VOID_IF_NOT_INIT();

    if (mProcs && mProcs->vsync) {
        VTRACE("report vsync on disp %d, timestamp %llu", disp, timestamp);
        // workaround to pretend vsync is from primary display
        // Display will freeze if vsync is from external display.
        mProcs->vsync(const_cast<hwc_procs_t*>(mProcs), IDisplayDevice::DEVICE_PRIMARY, timestamp);
    }
}

void Hwcomposer::hotplug(int disp, bool connected)
{
    RETURN_VOID_IF_NOT_INIT();

    // TODO: Two fake hotplug events are sent during mode setting. To avoid
    // unnecessary audio switch, real connection status should be sent to MDS
    mMultiDisplayObserver->notifyHotPlug(mDrm->isConnected(disp));

    if (mProcs && mProcs->hotplug) {
        DTRACE("report hotplug on disp %d, connected %d", disp, connected);
        mProcs->hotplug(const_cast<hwc_procs_t*>(mProcs), disp, connected);
        DTRACE("hotplug callback processed and returned!");
    }

    mDisplayAnalyzer->postHotplugEvent(connected);
}

void Hwcomposer::invalidate()
{
    RETURN_VOID_IF_NOT_INIT();

    if (mProcs && mProcs->invalidate) {
        DTRACE("invalidating screen...");
        mProcs->invalidate(const_cast<hwc_procs_t*>(mProcs));
    }
}

bool Hwcomposer::release()
{
    RETURN_FALSE_IF_NOT_INIT();

    return true;
}

bool Hwcomposer::dump(char *buff, int buff_len, int *cur_len)
{
    RETURN_FALSE_IF_NOT_INIT();

    Dump d(buff, buff_len);

    // dump composer status
    d.append("Hardware Composer state:");
    // dump device status
    for (size_t i= 0; i < mDisplayDevices.size(); i++) {
        IDisplayDevice *device = mDisplayDevices.itemAt(i);
        if (device)
            device->dump(d);
    }

    // dump plane manager status
    if (mPlaneManager)
        mPlaneManager->dump(d);

    // dump buffer manager status
    if (mBufferManager)
        mBufferManager->dump(d);

    return true;
}

void Hwcomposer::registerProcs(hwc_procs_t const *procs)
{
    CTRACE();

    if (!procs) {
        WTRACE("procs is NULL");
    }
    mProcs = procs;
}

bool Hwcomposer::initialize()
{
    CTRACE();

    // create drm
    mDrm = new Drm();
    if (!mDrm || !mDrm->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to create DRM");
    }

    if (!mPlatFactory){
        DEINIT_AND_RETURN_FALSE("failed to provide a PlatFactory");
    }

    // create buffer manager
    mBufferManager = mPlatFactory->createBufferManager();
    if (!mBufferManager || !mBufferManager->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to create buffer manager");
    }

    // create display plane manager
    mPlaneManager = mPlatFactory->createDisplayPlaneManager();
    if (!mPlaneManager || !mPlaneManager->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to create display plane manager");
    }

    mDisplayContext = mPlatFactory->createDisplayContext();
    if (!mDisplayContext || !mDisplayContext->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to create display context");
    }

    mUeventObserver = new UeventObserver();
    if (!mUeventObserver || !mUeventObserver->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to initialize uevent observer");
    }

    // create display device
    mDisplayDevices.clear();
    for (int i = 0; i < IDisplayDevice::DEVICE_COUNT; i++) {
        IDisplayDevice *device = mPlatFactory->createDisplayDevice(i);
        if (!device || !device->initialize()) {
            DEINIT_AND_DELETE_OBJ(device);
            DEINIT_AND_RETURN_FALSE("failed to create device %d", i);
        }
        // add this device
        ETRACE("HWC devices initialize device is %p at %d", device, i);
        mDisplayDevices.insertAt(device, i, 1);
    }

    mVsyncManager = new VsyncManager(*this);
    if (!mVsyncManager || !mVsyncManager->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to create Vsync Manager");
    }

    mDisplayAnalyzer = new DisplayAnalyzer();
    if (!mDisplayAnalyzer || !mDisplayAnalyzer->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to initialize display analyzer");
    }

    mMultiDisplayObserver = new MultiDisplayObserver();
    if (!mMultiDisplayObserver || !mMultiDisplayObserver->initialize()) {
        DEINIT_AND_RETURN_FALSE("failed to initialize display observer");
    }

    // all initialized, starting uevent observer
    mUeventObserver->start();

    mInitialized = true;
    return true;
}

void Hwcomposer::deinitialize()
{
    DEINIT_AND_DELETE_OBJ(mMultiDisplayObserver);
    DEINIT_AND_DELETE_OBJ(mDisplayAnalyzer);
    // delete mVsyncManager first as it holds reference to display devices.
    DEINIT_AND_DELETE_OBJ(mVsyncManager);

    DEINIT_AND_DELETE_OBJ(mUeventObserver);
    // destroy display devices
    for (size_t i = 0; i < mDisplayDevices.size(); i++) {
        IDisplayDevice *device = mDisplayDevices.itemAt(i);
        DEINIT_AND_DELETE_OBJ(device);
    }
    mDisplayDevices.clear();

    if (mPlatFactory) {
        delete mPlatFactory;
        mPlatFactory = 0;
    }

    DEINIT_AND_DELETE_OBJ(mDisplayContext);
    DEINIT_AND_DELETE_OBJ(mPlaneManager);
    DEINIT_AND_DELETE_OBJ(mBufferManager);
    DEINIT_AND_DELETE_OBJ(mDrm);
    mInitialized = false;
}

Drm* Hwcomposer::getDrm()
{
    return mDrm;
}

DisplayPlaneManager* Hwcomposer::getPlaneManager()
{
    return mPlaneManager;
}

BufferManager* Hwcomposer::getBufferManager()
{
    return mBufferManager;
}

IDisplayContext* Hwcomposer::getDisplayContext()
{
    return mDisplayContext;
}

DisplayAnalyzer* Hwcomposer::getDisplayAnalyzer()
{
    return mDisplayAnalyzer;
}

MultiDisplayObserver* Hwcomposer::getMultiDisplayObserver()
{
    return mMultiDisplayObserver;
}

IDisplayDevice* Hwcomposer::getDisplayDevice(int disp)
{
    if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
        ETRACE("invalid disp %d", disp);
        return NULL;
    }
    return mDisplayDevices.itemAt(disp);
}

VsyncManager* Hwcomposer::getVsyncManager()
{
    return mVsyncManager;
}

UeventObserver* Hwcomposer::getUeventObserver()
{
    return mUeventObserver;
}

} // namespace intel
} // namespace android
