/*
 * 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 SkMatrix&, const SkIRect&,
                             const SkImageInfo&, 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,
                          const SkMatrix& matrix,
                          const SkIRect& clipBounds,
                          const SkImageInfo& bufferInfo)
            : INHERITED()
            , fTestDrawable(td)
            , fDrawProc(drawProc)
            , fSubmitProc(submitProc)
            , fMatrix(matrix)
            , fClipBounds(clipBounds)
            , fBufferInfo(bufferInfo) {}
        ~DrawHandlerImport() override {
            fSubmitProc(fTestDrawable);
        }

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

            fDrawProc(fTestDrawable, fMatrix, fClipBounds, fBufferInfo, vkInfo);
        }
    private:
        TestDrawable*     fTestDrawable;
        DrawProc          fDrawProc;
        SubmitProc        fSubmitProc;
        const SkMatrix    fMatrix;
        const SkIRect     fClipBounds;
        const SkImageInfo fBufferInfo;

        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 SkMatrix& matrix, const SkIRect& clipBounds,
                           const SkImageInfo& bufferInfo, const GrVkDrawableInfo& info) {
        td->fDrawContext = GrVkSecondaryCBDrawContext::Make(td->fContext, bufferInfo, info, nullptr);
        if (!td->fDrawContext) {
            return;
        }

        SkCanvas* canvas = td->fDrawContext->getCanvas();
        canvas->clipRect(SkRect::Make(clipBounds));
        canvas->setMatrix(matrix);

        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,
                                                            bufferInfo);
        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,
                                                         const SkImageInfo& bufferInfo) override {
        if (backendApi != GrBackendApi::kVulkan) {
            return nullptr;
        }
        std::unique_ptr<GpuDrawHandler> draw;
        if (fContext) {
            draw.reset(new DrawHandlerImport(this, ImportDraw, ImportSubmitted, matrix,
                                             clipBounds, bufferInfo));
        } 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
