/*
 * 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 "rsAdapter.h"
#include "rs_hal.h"

#include <cutils/compiler.h>
#include <utils/Log.h>
#include "rsGrallocConsumer.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;
        }
    }

    BufferQueue::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

