/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

#define ATRACE_TAG ATRACE_TAG_RS

#include "rsContext.h"
#include "rsAllocation.h"
#include "rs_hal.h"

#include <cutils/compiler.h>
#include <utils/Log.h>
#include "rsGrallocConsumer.h"
#include <gui/BufferItem.h>
#include <ui/GraphicBuffer.h>


namespace android {
namespace renderscript {

GrallocConsumer::GrallocConsumer(Allocation *a, const sp<IGraphicBufferConsumer>& bq, int flags) :
    ConsumerBase(bq, true)
{
    mAlloc = a;
    if (flags == 0) {
        flags = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_RENDERSCRIPT;
    } else {
        flags |= GRALLOC_USAGE_RENDERSCRIPT;
    }
    mConsumer->setConsumerUsageBits(flags);
    mConsumer->setMaxAcquiredBufferCount(2);

    uint32_t y = a->mHal.drvState.lod[0].dimY;
    if (y < 1) y = 1;
    mConsumer->setDefaultBufferSize(a->mHal.drvState.lod[0].dimX, y);

    if (a->mHal.state.yuv) {
        bq->setDefaultBufferFormat(a->mHal.state.yuv);
    }
    //mBufferQueue->setConsumerName(name);
}

GrallocConsumer::~GrallocConsumer() {
    // ConsumerBase destructor does all the work.
}



status_t GrallocConsumer::lockNextBuffer() {
    Mutex::Autolock _l(mMutex);
    status_t err;

    if (mAcquiredBuffer.mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
        err = releaseAcquiredBufferLocked();
        if (err) {
            return err;
        }
    }

    BufferItem b;

    err = acquireBufferLocked(&b, 0);
    if (err != OK) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            return BAD_VALUE;
        } else {
            ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
            return err;
        }
    }

    int buf = b.mBuf;

    if (b.mFence.get()) {
        err = b.mFence->waitForever("GrallocConsumer::lockNextBuffer");
        if (err != OK) {
            ALOGE("Failed to wait for fence of acquired buffer: %s (%d)",
                    strerror(-err), err);
            return err;
        }
    }

    void *bufferPointer = nullptr;
    android_ycbcr ycbcr = android_ycbcr();

    if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
            HAL_PIXEL_FORMAT_YCbCr_420_888) {
        err = mSlots[buf].mGraphicBuffer->lockYCbCr(
            GraphicBuffer::USAGE_SW_READ_OFTEN,
            b.mCrop,
            &ycbcr);

        if (err != OK) {
            ALOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
                    strerror(-err), err);
            return err;
        }
        bufferPointer = ycbcr.y;
    } else {
        err = mSlots[buf].mGraphicBuffer->lock(
            GraphicBuffer::USAGE_SW_READ_OFTEN,
            b.mCrop,
            &bufferPointer);

        if (err != OK) {
            ALOGE("Unable to lock buffer for CPU reading: %s (%d)",
                    strerror(-err), err);
            return err;
        }
    }

    size_t lockedIdx = 0;
    assert(mAcquiredBuffer.mSlot == BufferQueue::INVALID_BUFFER_SLOT);

    mAcquiredBuffer.mSlot = buf;
    mAcquiredBuffer.mBufferPointer = bufferPointer;
    mAcquiredBuffer.mGraphicBuffer = mSlots[buf].mGraphicBuffer;

    mAlloc->mHal.drvState.lod[0].mallocPtr = reinterpret_cast<uint8_t*>(bufferPointer);
    mAlloc->mHal.drvState.lod[0].stride = mSlots[buf].mGraphicBuffer->getStride() *
            mAlloc->mHal.state.type->getElementSizeBytes();
    mAlloc->mHal.state.nativeBuffer = mAcquiredBuffer.mGraphicBuffer->getNativeBuffer();
    mAlloc->mHal.state.timestamp = b.mTimestamp;

    assert(mAlloc->mHal.drvState.lod[0].dimX ==
           mSlots[buf].mGraphicBuffer->getWidth());
    assert(mAlloc->mHal.drvState.lod[0].dimY ==
           mSlots[buf].mGraphicBuffer->getHeight());

    //mAlloc->format = mSlots[buf].mGraphicBuffer->getPixelFormat();

    //mAlloc->crop        = b.mCrop;
    //mAlloc->transform   = b.mTransform;
    //mAlloc->scalingMode = b.mScalingMode;
    //mAlloc->frameNumber = b.mFrameNumber;

    if (mAlloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
        mAlloc->mHal.drvState.lod[1].mallocPtr = ycbcr.cb;
        mAlloc->mHal.drvState.lod[2].mallocPtr = ycbcr.cr;

        mAlloc->mHal.drvState.lod[0].stride = ycbcr.ystride;
        mAlloc->mHal.drvState.lod[1].stride = ycbcr.cstride;
        mAlloc->mHal.drvState.lod[2].stride = ycbcr.cstride;

        mAlloc->mHal.drvState.yuv.shift = 1;
        mAlloc->mHal.drvState.yuv.step = ycbcr.chroma_step;
    }

    return OK;
}

status_t GrallocConsumer::unlockBuffer() {
    Mutex::Autolock _l(mMutex);
    return releaseAcquiredBufferLocked();
}

status_t GrallocConsumer::releaseAcquiredBufferLocked() {
    status_t err;

    err = mAcquiredBuffer.mGraphicBuffer->unlock();
    if (err != OK) {
        ALOGE("%s: Unable to unlock graphic buffer", __FUNCTION__);
        return err;
    }
    int buf = mAcquiredBuffer.mSlot;

    // release the buffer if it hasn't already been freed by the BufferQueue.
    // This can happen, for example, when the producer of this buffer
    // disconnected after this buffer was acquired.
    if (CC_LIKELY(mAcquiredBuffer.mGraphicBuffer ==
            mSlots[buf].mGraphicBuffer)) {
        releaseBufferLocked(
                buf, mAcquiredBuffer.mGraphicBuffer,
                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
    }

    mAcquiredBuffer.mSlot = BufferQueue::INVALID_BUFFER_SLOT;
    mAcquiredBuffer.mBufferPointer = nullptr;
    mAcquiredBuffer.mGraphicBuffer.clear();
    return OK;
}

} // namespace renderscript
} // namespace android

