/*
 * Copyright 2019 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.
 */

#include <cutils/native_handle.h>
#include <gui/BufferQueueCore.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/bufferqueue/2.0/types.h>
#include <system/window.h>
#include <vndk/hardware_buffer.h>

namespace android {
namespace hardware {
namespace graphics {
namespace bufferqueue {
namespace V2_0 {
namespace utils {

// Status
// ======

bool b2h(status_t from, HStatus* to,
         bool* bufferNeedsReallocation, bool* releaseAllBuffers) {
    switch (from) {
    case OK:
        *to = HStatus::OK; break;
    case NO_MEMORY:
        *to = HStatus::NO_MEMORY; break;
    case NO_INIT:
        *to = HStatus::NO_INIT; break;
    case BAD_VALUE:
        *to = HStatus::BAD_VALUE; break;
    case DEAD_OBJECT:
        *to = HStatus::DEAD_OBJECT; break;
    case INVALID_OPERATION:
        *to = HStatus::INVALID_OPERATION; break;
    case TIMED_OUT:
        *to = HStatus::TIMED_OUT; break;
    case WOULD_BLOCK:
        *to = HStatus::WOULD_BLOCK; break;
    case UNKNOWN_ERROR:
        *to = HStatus::UNKNOWN_ERROR; break;
    default:
        using BGBP = ::android::IGraphicBufferProducer;
        status_t mask =
                (bufferNeedsReallocation ? BGBP::BUFFER_NEEDS_REALLOCATION : 0)
                | (releaseAllBuffers ? BGBP::RELEASE_ALL_BUFFERS : 0);
        if (from & ~mask) {
            *to = static_cast<HStatus>(from);
        } else {
            *to = HStatus::OK;
            if (bufferNeedsReallocation) {
                *bufferNeedsReallocation = from & BGBP::BUFFER_NEEDS_REALLOCATION;
            }
            if (releaseAllBuffers) {
                *releaseAllBuffers = from & BGBP::RELEASE_ALL_BUFFERS;
            }
        }
    }
    return true;
}

bool h2b(HStatus from, status_t* to) {
    switch (from) {
    case HStatus::OK:
        *to = OK; break;
    case HStatus::NO_MEMORY:
        *to = NO_MEMORY; break;
    case HStatus::NO_INIT:
        *to = NO_INIT; break;
    case HStatus::BAD_VALUE:
        *to = BAD_VALUE; break;
    case HStatus::DEAD_OBJECT:
        *to = DEAD_OBJECT; break;
    case HStatus::INVALID_OPERATION:
        *to = INVALID_OPERATION; break;
    case HStatus::TIMED_OUT:
        *to = TIMED_OUT; break;
    case HStatus::WOULD_BLOCK:
        *to = WOULD_BLOCK; break;
    case HStatus::UNKNOWN_ERROR:
        *to = UNKNOWN_ERROR; break;
    default:
        *to = static_cast<status_t>(from);
    }
    return true;
}

// Fence
// =====

HFenceWrapper::HFenceWrapper(native_handle_t* h) : mHandle{h} {
}

HFenceWrapper::~HFenceWrapper() {
    native_handle_delete(mHandle);
}

HFenceWrapper& HFenceWrapper::set(native_handle_t* h) {
    native_handle_delete(mHandle);
    mHandle = h;
    return *this;
}

HFenceWrapper& HFenceWrapper::operator=(native_handle_t* h) {
    return set(h);
}

hidl_handle HFenceWrapper::getHandle() const {
    return hidl_handle{mHandle};
}

HFenceWrapper::operator hidl_handle() const {
    return getHandle();
}

bool b2h(sp<BFence> const& from, HFenceWrapper* to) {
    if (!from) {
        to->set(nullptr);
        return true;
    }
    int fenceFd = from->get();
    if (fenceFd == -1) {
        to->set(nullptr);
        return true;
    }
    native_handle_t* nh = native_handle_create(1, 0);
    if (!nh) {
        return false;
    }
    nh->data[0] = fenceFd;
    to->set(nh);
    return true;
}

bool h2b(native_handle_t const* from, sp<BFence>* to) {
    if (!from || from->numFds == 0) {
        *to = new ::android::Fence();
        return true;
    }
    if (from->numFds != 1 || from->numInts != 0) {
        return false;
    }
    *to = new BFence(dup(from->data[0]));
    return true;
}

// ConnectionType
// ==============

bool b2h(int from, HConnectionType* to) {
    *to = static_cast<HConnectionType>(from);
    switch (from) {
    case BufferQueueCore::CURRENTLY_CONNECTED_API:
        *to = HConnectionType::CURRENTLY_CONNECTED; break;
    case NATIVE_WINDOW_API_EGL:
        *to = HConnectionType::EGL; break;
    case NATIVE_WINDOW_API_CPU:
        *to = HConnectionType::CPU; break;
    case NATIVE_WINDOW_API_MEDIA:
        *to = HConnectionType::MEDIA; break;
    case NATIVE_WINDOW_API_CAMERA:
        *to = HConnectionType::CAMERA; break;
    }
    return true;
}

bool h2b(HConnectionType from, int* to) {
    *to = static_cast<int>(from);
    switch (from) {
    case HConnectionType::CURRENTLY_CONNECTED:
        *to = BufferQueueCore::CURRENTLY_CONNECTED_API; break;
    case HConnectionType::EGL:
        *to = NATIVE_WINDOW_API_EGL; break;
    case HConnectionType::CPU:
        *to = NATIVE_WINDOW_API_CPU; break;
    case HConnectionType::MEDIA:
        *to = NATIVE_WINDOW_API_MEDIA; break;
    case HConnectionType::CAMERA:
        *to = NATIVE_WINDOW_API_CAMERA; break;
    }
    return true;
}

// Rect
// ====

bool b2h(BRect const& from, HRect* to) {
    BRect* dst = reinterpret_cast<BRect*>(to->data());
    dst->left = from.left;
    dst->top = from.top;
    dst->right = from.right;
    dst->bottom = from.bottom;
    return true;
}

bool h2b(HRect const& from, BRect* to) {
    BRect const* src = reinterpret_cast<BRect const*>(from.data());
    to->left = src->left;
    to->top = src->top;
    to->right = src->right;
    to->bottom = src->bottom;
    return true;
}

// Region
// ======

bool b2h(BRegion const& from, HRegion* to) {
    size_t numRects;
    BRect const* rectArray = from.getArray(&numRects);
    to->resize(numRects);
    for (size_t i = 0; i < numRects; ++i) {
        if (!b2h(rectArray[i], &(*to)[i])) {
            return false;
        }
    }
    return true;
}

bool h2b(HRegion const& from, BRegion* to) {
    if (from.size() > 0) {
        BRect bRect;
        if (!h2b(from[0], &bRect)) {
            return false;
        }
        to->set(bRect);
        for (size_t i = 1; i < from.size(); ++i) {
            if (!h2b(from[i], &bRect)) {
                return false;
            }
            to->addRectUnchecked(
                    static_cast<int>(bRect.left),
                    static_cast<int>(bRect.top),
                    static_cast<int>(bRect.right),
                    static_cast<int>(bRect.bottom));
        }
    } else {
        to->clear();
    }
    return true;
}

// GraphicBuffer
// =============

// The handle is not cloned. Its lifetime is tied to the original GraphicBuffer.
bool b2h(sp<GraphicBuffer> const& from, HardwareBuffer* to,
         uint32_t* toGenerationNumber) {
    if (!from) {
        return false;
    }
    AHardwareBuffer* hwBuffer = from->toAHardwareBuffer();
    to->nativeHandle.setTo(
          const_cast<native_handle_t*>(
              AHardwareBuffer_getNativeHandle(hwBuffer)),
          false);
    AHardwareBuffer_describe(
            hwBuffer,
            reinterpret_cast<AHardwareBuffer_Desc*>(to->description.data()));
    if (toGenerationNumber) {
        *toGenerationNumber = from->getGenerationNumber();
    }
    return true;
}

// The handle is cloned.
bool h2b(HardwareBuffer const& from, sp<GraphicBuffer>* to) {
    AHardwareBuffer_Desc const* desc =
            reinterpret_cast<AHardwareBuffer_Desc const*>(
            from.description.data());
    native_handle_t const* handle = from.nativeHandle;
    AHardwareBuffer* hwBuffer;
    if (AHardwareBuffer_createFromHandle(
            desc, handle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
            &hwBuffer) != OK) {
        return false;
    }
    *to = GraphicBuffer::fromAHardwareBuffer(hwBuffer);
    AHardwareBuffer_release(hwBuffer);
    return true;
}

}  // namespace utils
}  // namespace V2_0
}  // namespace bufferqueue
}  // namespace graphics
}  // namespace hardware
}  // namespace android

