/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This is a GPU-backend specific test. It relies on static intializers to work

#include "SkTypes.h"

#if SK_SUPPORT_GPU && defined(SK_VULKAN)

#include "vk/GrVkVulkan.h"

#include "GrBackendDrawableInfo.h"
#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "SkDrawable.h"
#include "SkSurface.h"
#include "Test.h"
#include "vk/GrVkGpu.h"
#include "vk/GrVkInterface.h"
#include "vk/GrVkMemory.h"
#include "vk/GrVkSecondaryCBDrawContext.h"
#include "vk/GrVkUtil.h"

using sk_gpu_test::GrContextFactory;

static const int DEV_W = 16, DEV_H = 16;

class TestDrawable : public SkDrawable {
public:
    TestDrawable(const GrVkInterface* interface, GrContext* context, int32_t width, int32_t height)
            : INHERITED()
            , fInterface(interface)
            , fContext(context)
            , fWidth(width)
            , fHeight(height) {}

    ~TestDrawable() override {}

    class DrawHandlerBasic : public GpuDrawHandler {
    public:
        DrawHandlerBasic(const GrVkInterface* interface, int32_t width, int32_t height)
            : INHERITED()
            , fInterface(interface)
            , fWidth(width)
            , fHeight(height) {}
        ~DrawHandlerBasic() override {}

        void draw(const GrBackendDrawableInfo& info) override {
            GrVkDrawableInfo vkInfo;
            SkAssertResult(info.getVkDrawableInfo(&vkInfo));

            // Clear to Red
            VkClearColorValue vkColor;
            vkColor.float32[0] = 1.0f; // r
            vkColor.float32[1] = 0.0f; // g
            vkColor.float32[2] = 0.0f; // b
            vkColor.float32[3] = 1.0f; // a

            // Clear right half of render target
            VkClearRect clearRect;
            clearRect.rect.offset = { fWidth / 2, 0 };
            clearRect.rect.extent = { (uint32_t)fWidth / 2, (uint32_t)fHeight };
            clearRect.baseArrayLayer = 0;
            clearRect.layerCount = 1;

            VkClearAttachment attachment;
            attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
            attachment.colorAttachment = vkInfo.fColorAttachmentIndex;
            attachment.clearValue.color = vkColor;

            GR_VK_CALL(fInterface, CmdClearAttachments(vkInfo.fSecondaryCommandBuffer,
                                                       1,
                                                       &attachment,
                                                       1,
                                                       &clearRect));
            vkInfo.fDrawBounds->offset = { fWidth / 2, 0 };
            vkInfo.fDrawBounds->extent = { (uint32_t)fWidth / 2, (uint32_t)fHeight };
        }
    private:
        const GrVkInterface* fInterface;
        int32_t              fWidth;
        int32_t              fHeight;

        typedef GpuDrawHandler INHERITED;
    };

    typedef void (*DrawProc)(TestDrawable*, const GrVkDrawableInfo&);
    typedef void (*SubmitProc)(TestDrawable*);

    // Exercises the exporting of a secondary command buffer from one GrContext and then importing
    // it into a second GrContext. We then draw to the secondary command buffer from the second
    // GrContext.
    class DrawHandlerImport : public GpuDrawHandler {
    public:
        DrawHandlerImport(TestDrawable* td, DrawProc drawProc, SubmitProc submitProc)
            : INHERITED()
            , fTestDrawable(td)
            , fDrawProc(drawProc)
            , fSubmitProc(submitProc) {}
        ~DrawHandlerImport() override {
            fSubmitProc(fTestDrawable);
        }

        void draw(const GrBackendDrawableInfo& info) override {
            GrVkDrawableInfo vkInfo;
            SkAssertResult(info.getVkDrawableInfo(&vkInfo));

            fDrawProc(fTestDrawable, vkInfo);
        }
    private:
        TestDrawable* fTestDrawable;
        DrawProc      fDrawProc;
        SubmitProc    fSubmitProc;

        typedef GpuDrawHandler INHERITED;
    };

    // Helper function to test drawing to a secondary command buffer that we imported into the
    // GrContext using a GrVkSecondaryCBDrawContext.
    static void ImportDraw(TestDrawable* td, const GrVkDrawableInfo& info) {
        SkImageInfo imageInfo = SkImageInfo::Make(td->fWidth, td->fHeight, kRGBA_8888_SkColorType,
                                                  kPremul_SkAlphaType);

        td->fDrawContext = GrVkSecondaryCBDrawContext::Make(td->fContext, imageInfo, info, nullptr);
        if (!td->fDrawContext) {
            return;
        }

        SkCanvas* canvas = td->fDrawContext->getCanvas();
        SkIRect rect = SkIRect::MakeXYWH(td->fWidth/2, 0, td->fWidth/4, td->fHeight);
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        canvas->drawIRect(rect, paint);

        // Draw to an offscreen target so that we end up with a mix of "real" secondary command
        // buffers and the imported secondary command buffer.
        sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(td->fContext, SkBudgeted::kYes,
                                                            imageInfo);
        surf->getCanvas()->clear(SK_ColorRED);

        SkRect dstRect = SkRect::MakeXYWH(3*td->fWidth/4, 0, td->fWidth/4, td->fHeight);
        SkIRect srcRect = SkIRect::MakeWH(td->fWidth/4, td->fHeight);
        canvas->drawImageRect(surf->makeImageSnapshot(), srcRect, dstRect, &paint);

        td->fDrawContext->flush();
    }

    // Helper function to test waiting for the imported secondary command buffer to be submitted on
    // its original context and then cleaning up the GrVkSecondaryCBDrawContext from this GrContext.
    static void ImportSubmitted(TestDrawable* td) {
        // Typical use case here would be to create a fence that we submit to the gpu and then wait
        // on before releasing the GrVkSecondaryCBDrawContext resources. To simulate that for this
        // test (and since we are running single threaded anyways), we will just force a sync of
        // the gpu and cpu here.
        td->fContext->contextPriv().getGpu()->testingOnly_flushGpuAndSync();

        td->fDrawContext->releaseResources();
        // We release the GrContext here manually to test that we waited long enough before
        // releasing the GrVkSecondaryCBDrawContext. This simulates when a client is able to delete
        // the GrContext it used to imported the secondary command buffer. If we had released the
        // GrContext's resources earlier (before waiting on the gpu above), we would get vulkan
        // validation layer errors saying we freed some vulkan objects while they were still in use
        // on the GPU.
        td->fContext->releaseResourcesAndAbandonContext();
    }


    std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi backendApi,
                                                         const SkMatrix& matrix,
                                                         const SkIRect& clipBounds) override {
        if (backendApi != GrBackendApi::kVulkan) {
            return nullptr;
        }
        std::unique_ptr<GpuDrawHandler> draw;
        if (fContext) {
            draw.reset(new DrawHandlerImport(this, ImportDraw, ImportSubmitted));
        } else {
            draw.reset(new DrawHandlerBasic(fInterface, fWidth, fHeight));
        }
        return draw;
    }

    SkRect onGetBounds() override {
        return SkRect::MakeLTRB(fWidth / 2, 0, fWidth, fHeight);
    }

    void onDraw(SkCanvas*) override {
        SkASSERT(false);
    }

private:
    const GrVkInterface* fInterface;
    GrContext*           fContext;
    sk_sp<GrVkSecondaryCBDrawContext> fDrawContext;
    int32_t              fWidth;
    int32_t              fHeight;

    typedef SkDrawable INHERITED;
};

void draw_drawable_test(skiatest::Reporter* reporter, GrContext* context, GrContext* childContext) {
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());

    const SkImageInfo ii = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
                                             kPremul_SkAlphaType);
    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
                                                         ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorBLUE);

    sk_sp<TestDrawable> drawable(new TestDrawable(gpu->vkInterface(), childContext, DEV_W, DEV_H));
    canvas->drawDrawable(drawable.get());

    SkPaint paint;
    paint.setColor(SK_ColorGREEN);
    SkIRect rect = SkIRect::MakeLTRB(0, DEV_H/2, DEV_W, DEV_H);
    canvas->drawIRect(rect, paint);

    // read pixels
    SkBitmap bitmap;
    bitmap.allocPixels(ii);
    canvas->readPixels(bitmap, 0, 0);

    const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
    bool failureFound = false;
    SkPMColor expectedPixel;
    for (int cy = 0; cy < DEV_H && !failureFound; ++cy) {
        for (int cx = 0; cx < DEV_W && !failureFound; ++cx) {
            SkPMColor canvasPixel = canvasPixels[cy * DEV_W + cx];
            if (cy < DEV_H / 2) {
                if (cx < DEV_W / 2) {
                    expectedPixel = 0xFFFF0000; // Blue
                } else {
                    expectedPixel = 0xFF0000FF; // Red
                }
            } else {
                expectedPixel = 0xFF00FF00; // Green
            }
            if (expectedPixel != canvasPixel) {
                failureFound = true;
                ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
                       cx, cy, canvasPixel, expectedPixel);
            }
        }
    }
}

DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkDrawableTest, reporter, ctxInfo) {
    draw_drawable_test(reporter, ctxInfo.grContext(), nullptr);
}

DEF_GPUTEST(VkDrawableImportTest, reporter, options) {
    for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
        sk_gpu_test::GrContextFactory::ContextType contextType =
                (sk_gpu_test::GrContextFactory::ContextType) typeInt;
        if (contextType != sk_gpu_test::GrContextFactory::kVulkan_ContextType) {
            continue;
        }
        sk_gpu_test::GrContextFactory factory(options);
        sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(
                contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR);
        skiatest::ReporterContext ctx(
                   reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
        if (ctxInfo.grContext()) {
            sk_gpu_test::ContextInfo child =
                    factory.getSharedContextInfo(ctxInfo.grContext(), 0);
            if (!child.grContext()) {
                continue;
            }

            draw_drawable_test(reporter, ctxInfo.grContext(), child.grContext());
        }
    }
}

#endif
