/*
 * Copyright 2014 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_TAG "BufferQueueCore"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0

#define EGL_EGLEXT_PROTOTYPES

#if DEBUG_ONLY_CODE
#define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
#else
#define VALIDATE_CONSISTENCY()
#endif

#include <inttypes.h>

#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>

namespace android {

static String8 getUniqueName() {
    static volatile int32_t counter = 0;
    return String8::format("unnamed-%d-%d", getpid(),
            android_atomic_inc(&counter));
}

static uint64_t getUniqueId() {
    static std::atomic<uint32_t> counter{0};
    static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
    return id | counter++;
}

BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
    mAllocator(allocator),
    mMutex(),
    mIsAbandoned(false),
    mConsumerControlledByApp(false),
    mConsumerName(getUniqueName()),
    mConsumerListener(),
    mConsumerUsageBits(0),
    mConnectedApi(NO_CONNECTED_API),
    mLinkedToDeath(),
    mConnectedProducerListener(),
    mSlots(),
    mQueue(),
    mFreeSlots(),
    mFreeBuffers(),
    mUnusedSlots(),
    mActiveBuffers(),
    mDequeueCondition(),
    mDequeueBufferCannotBlock(false),
    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
    mDefaultWidth(1),
    mDefaultHeight(1),
    mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
    mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
    mMaxAcquiredBufferCount(1),
    mMaxDequeuedBufferCount(1),
    mBufferHasBeenQueued(false),
    mFrameCounter(0),
    mTransformHint(0),
    mIsAllocating(false),
    mIsAllocatingCondition(),
    mAllowAllocation(true),
    mBufferAge(0),
    mGenerationNumber(0),
    mAsyncMode(false),
    mSharedBufferMode(false),
    mAutoRefresh(false),
    mSharedBufferSlot(INVALID_BUFFER_SLOT),
    mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
            HAL_DATASPACE_UNKNOWN),
    mLastQueuedSlot(INVALID_BUFFER_SLOT),
    mUniqueId(getUniqueId())
{
    if (allocator == NULL) {
        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
        mAllocator = composer->createGraphicBufferAlloc();
        if (mAllocator == NULL) {
            BQ_LOGE("createGraphicBufferAlloc failed");
        }
    }

    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
        mFreeSlots.insert(s);
    }
    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
            s++) {
        mUnusedSlots.push_front(s);
    }
}

BufferQueueCore::~BufferQueueCore() {}

void BufferQueueCore::dump(String8& result, const char* prefix) const {
    Mutex::Autolock lock(mMutex);

    String8 fifo;
    Fifo::const_iterator current(mQueue.begin());
    while (current != mQueue.end()) {
        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
                "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
                current->mSlot, current->mGraphicBuffer.get(),
                current->mCrop.left, current->mCrop.top, current->mCrop.right,
                current->mCrop.bottom, current->mTransform, current->mTimestamp,
                BufferItem::scalingModeName(current->mScalingMode));
        ++current;
    }

    result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
            "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
            mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
            mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
            fifo.string());

    for (int s : mActiveBuffers) {
        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
        // A dequeued buffer might be null if it's still being allocated
        if (buffer.get()) {
            result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
                    "[%4ux%4u:%4u,%3X]\n", prefix,
                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
                    buffer.get(), mSlots[s].mBufferState.string(),
                    buffer->handle, buffer->width, buffer->height,
                    buffer->stride, buffer->format);
        } else {
            result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
                    buffer.get(), mSlots[s].mBufferState.string());
        }
    }
    for (int s : mFreeBuffers) {
        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
        result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
                prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
                buffer->handle, buffer->width, buffer->height, buffer->stride,
                buffer->format);
    }

    for (int s : mFreeSlots) {
        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
        result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
                buffer.get(), mSlots[s].mBufferState.string());
    }
}

int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
    // If dequeueBuffer is allowed to error out, we don't have to add an
    // extra buffer.
    if (mAsyncMode || mDequeueBufferCannotBlock) {
        return mMaxAcquiredBufferCount + 1;
    }

    return mMaxAcquiredBufferCount;
}

int BufferQueueCore::getMinMaxBufferCountLocked() const {
    return getMinUndequeuedBufferCountLocked() + 1;
}

int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
        bool dequeueBufferCannotBlock, int maxBufferCount) const {
    int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
            ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
    maxCount = std::min(maxBufferCount, maxCount);
    return maxCount;
}

int BufferQueueCore::getMaxBufferCountLocked() const {
    int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
            ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);

    // limit maxBufferCount by mMaxBufferCount always
    maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);

    return maxBufferCount;
}

void BufferQueueCore::clearBufferSlotLocked(int slot) {
    BQ_LOGV("clearBufferSlotLocked: slot %d", slot);

    mSlots[slot].mGraphicBuffer.clear();
    mSlots[slot].mBufferState.reset();
    mSlots[slot].mRequestBufferCalled = false;
    mSlots[slot].mFrameNumber = 0;
    mSlots[slot].mAcquireCalled = false;
    mSlots[slot].mNeedsReallocation = true;

    // Destroy fence as BufferQueue now takes ownership
    if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
        eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
        mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
    }
    mSlots[slot].mFence = Fence::NO_FENCE;
    mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;

    if (mLastQueuedSlot == slot) {
        mLastQueuedSlot = INVALID_BUFFER_SLOT;
    }
}

void BufferQueueCore::freeAllBuffersLocked() {
    for (int s : mFreeSlots) {
        clearBufferSlotLocked(s);
    }

    for (int s : mFreeBuffers) {
        mFreeSlots.insert(s);
        clearBufferSlotLocked(s);
    }
    mFreeBuffers.clear();

    for (int s : mActiveBuffers) {
        mFreeSlots.insert(s);
        clearBufferSlotLocked(s);
    }
    mActiveBuffers.clear();

    for (auto& b : mQueue) {
        b.mIsStale = true;
    }

    VALIDATE_CONSISTENCY();
}

void BufferQueueCore::discardFreeBuffersLocked() {
    for (int s : mFreeBuffers) {
        mFreeSlots.insert(s);
        clearBufferSlotLocked(s);
    }
    mFreeBuffers.clear();

    VALIDATE_CONSISTENCY();
}

bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
    if (delta >= 0) {
        // If we're going to fail, do so before modifying anything
        if (delta > static_cast<int>(mUnusedSlots.size())) {
            return false;
        }
        while (delta > 0) {
            if (mUnusedSlots.empty()) {
                return false;
            }
            int slot = mUnusedSlots.back();
            mUnusedSlots.pop_back();
            mFreeSlots.insert(slot);
            delta--;
        }
    } else {
        // If we're going to fail, do so before modifying anything
        if (-delta > static_cast<int>(mFreeSlots.size() +
                mFreeBuffers.size())) {
            return false;
        }
        while (delta < 0) {
            if (!mFreeSlots.empty()) {
                auto slot = mFreeSlots.begin();
                clearBufferSlotLocked(*slot);
                mUnusedSlots.push_back(*slot);
                mFreeSlots.erase(slot);
            } else if (!mFreeBuffers.empty()) {
                int slot = mFreeBuffers.back();
                clearBufferSlotLocked(slot);
                mUnusedSlots.push_back(slot);
                mFreeBuffers.pop_back();
            } else {
                return false;
            }
            delta++;
        }
    }
    return true;
}

void BufferQueueCore::waitWhileAllocatingLocked() const {
    ATRACE_CALL();
    while (mIsAllocating) {
        mIsAllocatingCondition.wait(mMutex);
    }
}

#if DEBUG_ONLY_CODE
void BufferQueueCore::validateConsistencyLocked() const {
    static const useconds_t PAUSE_TIME = 0;
    int allocatedSlots = 0;
    for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
        bool isInFreeSlots = mFreeSlots.count(slot) != 0;
        bool isInFreeBuffers =
                std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
                mFreeBuffers.cend();
        bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
        bool isInUnusedSlots =
                std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
                mUnusedSlots.cend();

        if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
            allocatedSlots++;
        }

        if (isInUnusedSlots) {
            if (isInFreeSlots) {
                BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
                usleep(PAUSE_TIME);
            }
            if (isInFreeBuffers) {
                BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
                usleep(PAUSE_TIME);
            }
            if (isInActiveBuffers) {
                BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
                        slot);
                usleep(PAUSE_TIME);
            }
            if (!mSlots[slot].mBufferState.isFree()) {
                BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
                usleep(PAUSE_TIME);
            }
            if (mSlots[slot].mGraphicBuffer != NULL) {
                BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
                        slot);
                usleep(PAUSE_TIME);
            }
        } else if (isInFreeSlots) {
            if (isInUnusedSlots) {
                BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
                usleep(PAUSE_TIME);
            }
            if (isInFreeBuffers) {
                BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
                usleep(PAUSE_TIME);
            }
            if (isInActiveBuffers) {
                BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
                usleep(PAUSE_TIME);
            }
            if (!mSlots[slot].mBufferState.isFree()) {
                BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
                usleep(PAUSE_TIME);
            }
            if (mSlots[slot].mGraphicBuffer != NULL) {
                BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
                        slot);
                usleep(PAUSE_TIME);
            }
        } else if (isInFreeBuffers) {
            if (isInUnusedSlots) {
                BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
                usleep(PAUSE_TIME);
            }
            if (isInFreeSlots) {
                BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
                usleep(PAUSE_TIME);
            }
            if (isInActiveBuffers) {
                BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
                        slot);
                usleep(PAUSE_TIME);
            }
            if (!mSlots[slot].mBufferState.isFree()) {
                BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
                usleep(PAUSE_TIME);
            }
            if (mSlots[slot].mGraphicBuffer == NULL) {
                BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
                usleep(PAUSE_TIME);
            }
        } else if (isInActiveBuffers) {
            if (isInUnusedSlots) {
                BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
                        slot);
                usleep(PAUSE_TIME);
            }
            if (isInFreeSlots) {
                BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
                usleep(PAUSE_TIME);
            }
            if (isInFreeBuffers) {
                BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
                        slot);
                usleep(PAUSE_TIME);
            }
            if (mSlots[slot].mBufferState.isFree() &&
                    !mSlots[slot].mBufferState.isShared()) {
                BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
                usleep(PAUSE_TIME);
            }
            if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) {
                BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
                usleep(PAUSE_TIME);
            }
        } else {
            BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
                    "mFreeBuffers, or mActiveBuffers", slot);
            usleep(PAUSE_TIME);
        }
    }

    if (allocatedSlots != getMaxBufferCountLocked()) {
        BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
                "Should be %d (%zu free slots, %zu free buffers, "
                "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
                getMaxBufferCountLocked(), mFreeSlots.size(),
                mFreeBuffers.size(), mActiveBuffers.size(),
                mUnusedSlots.size());
    }
}
#endif

} // namespace android
