/*
 * Copyright (C) 2012 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 LOG_NDEBUG 0
#define LOG_TAG "CpuConsumer"
//#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <gui/CpuConsumer.h>

#include <gui/BufferItem.h>
#include <utils/Log.h>

#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
// #define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
// #define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
#define CC_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
#define CC_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)

namespace android {

CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
        size_t maxLockedBuffers, bool controlledByApp) :
    ConsumerBase(bq, controlledByApp),
    mMaxLockedBuffers(maxLockedBuffers),
    mCurrentLockedBuffers(0)
{
    // Create tracking entries for locked buffers
    mAcquiredBuffers.insertAt(0, maxLockedBuffers);

    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
    mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers));
}

size_t CpuConsumer::findAcquiredBufferLocked(uintptr_t id) const {
    for (size_t i = 0; i < mMaxLockedBuffers; i++) {
        const auto& ab = mAcquiredBuffers[i];
        // note that this finds AcquiredBuffer::kUnusedId as well
        if (ab.mLockedBufferId == id) {
            return i;
        }
    }
    return mMaxLockedBuffers; // an invalid index
}

static uintptr_t getLockedBufferId(const CpuConsumer::LockedBuffer& buffer) {
    return reinterpret_cast<uintptr_t>(buffer.data);
}

static bool isPossiblyYUV(PixelFormat format) {
    switch (static_cast<int>(format)) {
        case HAL_PIXEL_FORMAT_RGBA_8888:
        case HAL_PIXEL_FORMAT_RGBX_8888:
        case HAL_PIXEL_FORMAT_RGBA_FP16:
        case HAL_PIXEL_FORMAT_RGBA_1010102:
        case HAL_PIXEL_FORMAT_RGB_888:
        case HAL_PIXEL_FORMAT_RGB_565:
        case HAL_PIXEL_FORMAT_BGRA_8888:
        case HAL_PIXEL_FORMAT_Y8:
        case HAL_PIXEL_FORMAT_Y16:
        case HAL_PIXEL_FORMAT_RAW16:
        case HAL_PIXEL_FORMAT_RAW12:
        case HAL_PIXEL_FORMAT_RAW10:
        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
        case HAL_PIXEL_FORMAT_BLOB:
        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
            return false;

        case HAL_PIXEL_FORMAT_YV12:
        case HAL_PIXEL_FORMAT_YCbCr_420_888:
        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
        case HAL_PIXEL_FORMAT_YCbCr_422_I:
        default:
            return true;
    }
}

status_t CpuConsumer::lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const {
    android_ycbcr ycbcr = android_ycbcr();

    PixelFormat format = item.mGraphicBuffer->getPixelFormat();
    PixelFormat flexFormat = format;
    if (isPossiblyYUV(format)) {
        int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
        status_t err = item.mGraphicBuffer->lockAsyncYCbCr(GraphicBuffer::USAGE_SW_READ_OFTEN,
                                                           item.mCrop, &ycbcr, fenceFd);
        if (err == OK) {
            flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
            if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
                CC_LOGV("locking buffer of format %#x as flex YUV", format);
            }
        } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
            CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)", strerror(-err), err);
            return err;
        }
    }

    if (ycbcr.y != nullptr) {
        outBuffer->data = reinterpret_cast<uint8_t*>(ycbcr.y);
        outBuffer->stride = static_cast<uint32_t>(ycbcr.ystride);
        outBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
        outBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
        outBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
        outBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
    } else {
        // not flexible YUV; try lockAsync
        void* bufferPointer = nullptr;
        int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
        status_t err = item.mGraphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN,
                                                      item.mCrop, &bufferPointer, fenceFd);
        if (err != OK) {
            CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err), err);
            return err;
        }

        outBuffer->data = reinterpret_cast<uint8_t*>(bufferPointer);
        outBuffer->stride = item.mGraphicBuffer->getStride();
        outBuffer->dataCb = nullptr;
        outBuffer->dataCr = nullptr;
        outBuffer->chromaStride = 0;
        outBuffer->chromaStep = 0;
    }

    outBuffer->width = item.mGraphicBuffer->getWidth();
    outBuffer->height = item.mGraphicBuffer->getHeight();
    outBuffer->format = format;
    outBuffer->flexFormat = flexFormat;

    outBuffer->crop = item.mCrop;
    outBuffer->transform = item.mTransform;
    outBuffer->scalingMode = item.mScalingMode;
    outBuffer->timestamp = item.mTimestamp;
    outBuffer->dataSpace = item.mDataSpace;
    outBuffer->frameNumber = item.mFrameNumber;

    return OK;
}

status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
    status_t err;

    if (!nativeBuffer) return BAD_VALUE;

    Mutex::Autolock _l(mMutex);

    if (mCurrentLockedBuffers == mMaxLockedBuffers) {
        CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.",
                mMaxLockedBuffers);
        return NOT_ENOUGH_DATA;
    }

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

    if (b.mGraphicBuffer == nullptr) {
        b.mGraphicBuffer = mSlots[b.mSlot].mGraphicBuffer;
    }

    err = lockBufferItem(b, nativeBuffer);
    if (err != OK) {
        return err;
    }

    // find an unused AcquiredBuffer
    size_t lockedIdx = findAcquiredBufferLocked(AcquiredBuffer::kUnusedId);
    ALOG_ASSERT(lockedIdx < mMaxLockedBuffers);
    AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);

    ab.mSlot = b.mSlot;
    ab.mGraphicBuffer = b.mGraphicBuffer;
    ab.mLockedBufferId = getLockedBufferId(*nativeBuffer);

    mCurrentLockedBuffers++;

    return OK;
}

status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
    Mutex::Autolock _l(mMutex);

    uintptr_t id = getLockedBufferId(nativeBuffer);
    size_t lockedIdx =
        (id != AcquiredBuffer::kUnusedId) ? findAcquiredBufferLocked(id) : mMaxLockedBuffers;
    if (lockedIdx == mMaxLockedBuffers) {
        CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
        return BAD_VALUE;
    }

    AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);

    int fenceFd = -1;
    status_t err = ab.mGraphicBuffer->unlockAsync(&fenceFd);
    if (err != OK) {
        CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__,
                lockedIdx);
        return err;
    }

    sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
    addReleaseFenceLocked(ab.mSlot, ab.mGraphicBuffer, fence);
    releaseBufferLocked(ab.mSlot, ab.mGraphicBuffer);

    ab.reset();

    mCurrentLockedBuffers--;

    return OK;
}

} // namespace android
