/*
 * 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 "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"

#include <cutils/memory.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:

    explicit 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(800.0f, 255 * 0.075f, 255 * 0.15f);
        mProxy->setLightCenter(lightVector);
        mCanvas.reset(new android::uirenderer::RecordingCanvas(mSize.width(), mSize.height()));
    }

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

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

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

    bool capturePixels(SkBitmap* bmp) {
        sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB();
        SkImageInfo destinationConfig =
            SkImageInfo::Make(mSize.width(), mSize.height(),
                              kRGBA_8888_SkColorType, kPremul_SkAlphaType, colorSpace);
        bmp->allocPixels(destinationConfig);
        android_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
                         mSize.width() * mSize.height() * 4);

        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;
    std::unique_ptr<android::uirenderer::RecordingCanvas> mCanvas;
    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

