/*
 * Copyright (C) 2015 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 "TestWindowContext.h"

#include "AnimationContext.h"
#include "DisplayListCanvas.h"
#include "IContextFactory.h"
#include "RecordingCanvas.h"
#include "RenderNode.h"
#include "SkTypes.h"
#include "gui/BufferQueue.h"
#include "gui/CpuConsumer.h"
#include "gui/IGraphicBufferConsumer.h"
#include "gui/IGraphicBufferProducer.h"
#include "gui/Surface.h"
#include "renderthread/RenderProxy.h"


namespace {

/**
 * Helper class for setting up android::uirenderer::renderthread::RenderProxy.
 */
class ContextFactory : public android::uirenderer::IContextFactory {
public:
    android::uirenderer::AnimationContext* createAnimationContext
        (android::uirenderer::renderthread::TimeLord& clock) override {
        return new android::uirenderer::AnimationContext(clock);
    }
};

} // anonymous namespace

namespace android {
namespace uirenderer {

/**
  Android strong pointers (android::sp) can't hold forward-declared classes,
  so we have to use pointer-to-implementation here if we want to hide the
  details from our non-framework users.
*/

class TestWindowContext::TestWindowData {

public:

    TestWindowData(SkISize size) : mSize(size) {
        android::BufferQueue::createBufferQueue(&mProducer, &mConsumer);
        mCpuConsumer = new android::CpuConsumer(mConsumer, 1);
        mCpuConsumer->setName(android::String8("TestWindowContext"));
        mCpuConsumer->setDefaultBufferSize(mSize.width(), mSize.height());
        mAndroidSurface = new android::Surface(mProducer);
        native_window_set_buffers_dimensions(mAndroidSurface.get(),
                                             mSize.width(), mSize.height());
        native_window_set_buffers_format(mAndroidSurface.get(),
                                         android::PIXEL_FORMAT_RGBA_8888);
        native_window_set_usage(mAndroidSurface.get(),
                                GRALLOC_USAGE_SW_READ_OFTEN |
                                GRALLOC_USAGE_SW_WRITE_NEVER |
                                GRALLOC_USAGE_HW_RENDER);
        mRootNode.reset(new android::uirenderer::RenderNode());
        mRootNode->incStrong(nullptr);
        mRootNode->mutateStagingProperties().setLeftTopRightBottom
            (0, 0, mSize.width(), mSize.height());
        mRootNode->mutateStagingProperties().setClipToBounds(false);
        mRootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
        ContextFactory factory;
        mProxy.reset
            (new android::uirenderer::renderthread::RenderProxy(false,
                                                                mRootNode.get(),
                                                                &factory));
        mProxy->loadSystemProperties();
        mProxy->initialize(mAndroidSurface.get());
        float lightX = mSize.width() / 2.0f;
        android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
        mProxy->setup(mSize.width(), mSize.height(), 800.0f,
                             255 * 0.075f, 255 * 0.15f);
        mProxy->setLightCenter(lightVector);
#if HWUI_NEW_OPS
        mCanvas.reset(new android::uirenderer::RecordingCanvas(mSize.width(), mSize.height()));
#else
        mCanvas.reset(new android::uirenderer::DisplayListCanvas(mSize.width(), mSize.height()));
#endif
    }

    SkCanvas* prepareToDraw() {
        //mCanvas->reset(mSize.width(), mSize.height());
        mCanvas->clipRect(0, 0, mSize.width(), mSize.height(),
                               SkRegion::Op::kReplace_Op);
        return mCanvas->asSkCanvas();
    }

    void finishDrawing() {
        mRootNode->setStagingDisplayList(mCanvas->finishRecording(), nullptr);
        mProxy->syncAndDrawFrame(nullptr);
        // Surprisingly, calling mProxy->fence() here appears to make no difference to
        // the timings we record.
    }

    void fence() {
        mProxy->fence();
    }

    bool capturePixels(SkBitmap* bmp) {
        SkImageInfo destinationConfig =
            SkImageInfo::Make(mSize.width(), mSize.height(),
                              kRGBA_8888_SkColorType, kPremul_SkAlphaType);
        bmp->allocPixels(destinationConfig);
        sk_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
                    mSize.width() * mSize.height());

        android::CpuConsumer::LockedBuffer nativeBuffer;
        android::status_t retval = mCpuConsumer->lockNextBuffer(&nativeBuffer);
        if (retval == android::BAD_VALUE) {
            SkDebugf("write_canvas_png() got no buffer; returning transparent");
            // No buffer ready to read - commonly triggered by dm sending us
            // a no-op source, or calling code that doesn't do anything on this
            // backend.
            bmp->eraseColor(SK_ColorTRANSPARENT);
            return false;
        } else if (retval) {
            SkDebugf("Failed to lock buffer to read pixels: %d.", retval);
            return false;
        }

        // Move the pixels into the destination SkBitmap

        LOG_ALWAYS_FATAL_IF(nativeBuffer.format != android::PIXEL_FORMAT_RGBA_8888,
                            "Native buffer not RGBA!");
        SkImageInfo nativeConfig =
            SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
                              kRGBA_8888_SkColorType, kPremul_SkAlphaType);

        // Android stride is in pixels, Skia stride is in bytes
        SkBitmap nativeWrapper;
        bool success =
            nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
        if (!success) {
            SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
            return false;
        }

        LOG_ALWAYS_FATAL_IF(bmp->colorType() != kRGBA_8888_SkColorType,
                            "Destination buffer not RGBA!");
        success =
            nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0, 0);
        if (!success) {
            SkDebugf("Failed to extract pixels from HWUI buffer");
            return false;
        }

        mCpuConsumer->unlockBuffer(nativeBuffer);

        return true;
    }

private:

    std::unique_ptr<android::uirenderer::RenderNode> mRootNode;
    std::unique_ptr<android::uirenderer::renderthread::RenderProxy> mProxy;
#if HWUI_NEW_OPS
    std::unique_ptr<android::uirenderer::RecordingCanvas> mCanvas;
#else
    std::unique_ptr<android::uirenderer::DisplayListCanvas> mCanvas;
#endif
    android::sp<android::IGraphicBufferProducer> mProducer;
    android::sp<android::IGraphicBufferConsumer> mConsumer;
    android::sp<android::CpuConsumer> mCpuConsumer;
    android::sp<android::Surface> mAndroidSurface;
    SkISize mSize;
};


TestWindowContext::TestWindowContext() :
    mData (nullptr) { }

TestWindowContext::~TestWindowContext() {
    delete mData;
}

void TestWindowContext::initialize(int width, int height)  {
    mData = new TestWindowData(SkISize::Make(width, height));
}

SkCanvas* TestWindowContext::prepareToDraw() {
    return mData ? mData->prepareToDraw() : nullptr;
}

void TestWindowContext::finishDrawing() {
    if (mData) {
        mData->finishDrawing();
    }
}

void TestWindowContext::fence() {
    if (mData) {
        mData->fence();
    }
}

bool TestWindowContext::capturePixels(SkBitmap* bmp) {
    return mData ? mData->capturePixels(bmp) : false;
}

} // namespace uirenderer
} // namespace android

