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

#include "gm.h"
#include "SkClipStack.h"
#include "SkRRect.h"

#if SK_SUPPORT_GPU
#  include "GrAppliedClip.h"
#  include "GrDrawContext.h"
#  include "GrDrawContextPriv.h"
#  include "GrFixedClip.h"
#  include "GrReducedClip.h"
#  include "GrRenderTargetPriv.h"
#  include "GrResourceProvider.h"
#  include "effects/GrTextureDomain.h"
#endif

constexpr static SkIRect kDeviceRect = {0, 0, 600, 600};
constexpr static SkIRect kLayerRect = {25, 25, 575, 575};
constexpr static SkIRect kCoverRect = {50, 50, 550, 550};

namespace skiagm {

////////////////////////////////////////////////////////////////////////////////////////////////////

class WindowRectanglesBaseGM : public GM {
protected:
    virtual void onCoverClipStack(const SkClipStack&, SkCanvas*) = 0;

private:
    SkISize onISize() override { return SkISize::Make(kDeviceRect.width(), kDeviceRect.height()); }
    void onDraw(SkCanvas*) final;
};

void WindowRectanglesBaseGM::onDraw(SkCanvas* canvas) {
    sk_tool_utils::draw_checkerboard(canvas, 0xffffffff, 0xffc6c3c6, 25);
    canvas->saveLayer(SkRect::Make(kLayerRect), nullptr);

    SkClipStack stack;
    stack.clipRect(SkRect::MakeXYWH(370.75, 80.25, 149, 100), SkMatrix::I(),
                   SkCanvas::kDifference_Op, false);
    stack.clipRect(SkRect::MakeXYWH(80.25, 420.75, 150, 100), SkMatrix::I(),
                   SkCanvas::kDifference_Op, true);
    stack.clipRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(200, 200, 200, 200), 60, 45),
                    SkMatrix::I(), SkCanvas::kDifference_Op, true);

    SkRRect nine;
    nine.setNinePatch(SkRect::MakeXYWH(550 - 30.25 - 100, 370.75, 100, 150), 12, 35, 23, 20);
    stack.clipRRect(nine, SkMatrix::I(), SkCanvas::kDifference_Op, true);

    SkRRect complx;
    SkVector complxRadii[4] = {{6, 4}, {8, 12}, {16, 24}, {48, 32}};
    complx.setRectRadii(SkRect::MakeXYWH(80.25, 80.75, 100, 149), complxRadii);
    stack.clipRRect(complx, SkMatrix::I(), SkCanvas::kDifference_Op, false);

    this->onCoverClipStack(stack, canvas);

    canvas->restore();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Draws a clip that will exercise window rectangles if they are supported.
 */
class WindowRectanglesGM : public WindowRectanglesBaseGM {
private:
    SkString onShortName() final { return SkString("windowrectangles"); }
    void onCoverClipStack(const SkClipStack&, SkCanvas*) final;
};

/**
 * This is a simple helper class for resetting a canvas's clip to our test’s SkClipStack.
 */
class ReplayClipStackVisitor final : public SkCanvasClipVisitor {
public:
    typedef SkCanvas::ClipOp Op;
    ReplayClipStackVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
    void clipRect(const SkRect& r, Op op, bool aa) override { fCanvas->clipRect(r, op, aa); }
    void clipRRect(const SkRRect& rr, Op op, bool aa) override { fCanvas->clipRRect(rr, op, aa); }
    void clipPath(const SkPath&, Op, bool) override { SkFAIL("Not implemented"); }
private:
    SkCanvas* const fCanvas;
};

void WindowRectanglesGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas) {
    SkPaint paint;
    paint.setColor(0xff00aa80);

    // Set up the canvas's clip to match our SkClipStack.
    ReplayClipStackVisitor visitor(canvas);
    SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
    for (const SkClipStack::Element* element = iter.next(); element; element = iter.next()) {
        element->replay(&visitor);
    }

    canvas->drawRect(SkRect::Make(kCoverRect), paint);
}

DEF_GM( return new WindowRectanglesGM(); )

////////////////////////////////////////////////////////////////////////////////////////////////////

#if SK_SUPPORT_GPU

constexpr static int kNumWindows = 8;

/**
 * Visualizes the mask (alpha or stencil) for a clip with several window rectangles. The purpose of
 * this test is to verify that window rectangles are being used during clip mask generation, and to
 * visualize where the window rectangles are placed.
 *
 * We use window rectangles when generating the clip mask because there is no need to invest time
 * defining those regions where window rectangles will be in effect during the actual draw anyway.
 *
 * This test works by filling the entire clip mask with a small checkerboard pattern before drawing
 * it, and then covering the mask with a solid color once it has been generated. The regions inside
 * window rectangles or outside the scissor should still have the initial checkerboard intact.
 */
class WindowRectanglesMaskGM : public WindowRectanglesBaseGM {
private:
    constexpr static int kMaskCheckerSize = 5;
    SkString onShortName() final { return SkString("windowrectangles_mask"); }
    void onCoverClipStack(const SkClipStack&, SkCanvas*) final;
    void visualizeAlphaMask(GrContext*, GrDrawContext*, const GrReducedClip&, const GrPaint&);
    void visualizeStencilMask(GrContext*, GrDrawContext*, const GrReducedClip&, const GrPaint&);
    void stencilCheckerboard(GrDrawContext*, bool flip);
    void fail(SkCanvas*);
};

/**
 * Base class for GrClips that visualize a clip mask.
 */
class MaskOnlyClipBase : public GrClip {
private:
    bool quickContains(const SkRect&) const final { return false; }
    bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final { return false; }
    void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
        rect->set(0, 0, width, height);
        if (iior) {
            *iior = false;
        }
    }
};

/**
 * This class clips a cover by an alpha mask. We use it to visualize the alpha clip mask.
 */
class AlphaOnlyClip final : public MaskOnlyClipBase {
public:
    AlphaOnlyClip(GrTexture* mask, int x, int y) {
        int w = mask->width(), h = mask->height();
        fFP = GrDeviceSpaceTextureDecalFragmentProcessor::Make(mask, SkIRect::MakeWH(w, h), {x, y});
    }
private:
    bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip* out) const override {
        out->addCoverageFP(fFP);
        return true;
    }
    sk_sp<GrFragmentProcessor> fFP;
};

/**
 * This class clips a cover by the stencil clip bit. We use it to visualize the stencil mask.
 */
class StencilOnlyClip final : public MaskOnlyClipBase {
private:
    bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip* out) const override {
        out->addStencilClip();
        return true;
    }
};

void WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas) {
    GrContext* ctx = canvas->getGrContext();
    GrDrawContext* dc = canvas->internal_private_accessTopLayerDrawContext();

    if (!ctx || !dc ||
        dc->accessRenderTarget()->renderTargetPriv().maxWindowRectangles() < kNumWindows) {
        this->fail(canvas);
        return;
    }

    const GrReducedClip reducedClip(stack, SkRect::Make(kCoverRect), kNumWindows);

    GrPaint paint;
    paint.setAntiAlias(true);
    if (!dc->isStencilBufferMultisampled()) {
        paint.setColor4f(GrColor4f(0, 0.25f, 1, 1));
        this->visualizeAlphaMask(ctx, dc, reducedClip, paint);
    } else {
        paint.setColor4f(GrColor4f(1, 0.25f, 0.25f, 1));
        this->visualizeStencilMask(ctx, dc, reducedClip, paint);
    }
}

void WindowRectanglesMaskGM::visualizeAlphaMask(GrContext* ctx, GrDrawContext* dc,
                                                const GrReducedClip& reducedClip,
                                                const GrPaint& paint) {
    sk_sp<GrDrawContext> maskDC(
        ctx->makeDrawContextWithFallback(SkBackingFit::kExact, kLayerRect.width(),
                                         kLayerRect.height(), kAlpha_8_GrPixelConfig, nullptr));
    if (!maskDC ||
        !ctx->resourceProvider()->attachStencilAttachment(maskDC->accessRenderTarget())) {
        return;
    }

    // Draw a checker pattern into the alpha mask so we can visualize the regions left untouched by
    // the clip mask generation.
    this->stencilCheckerboard(maskDC.get(), true);
    maskDC->clear(nullptr, GrColorPackA4(0xff), true);
    maskDC->drawContextPriv().drawAndStencilRect(StencilOnlyClip(), &GrUserStencilSettings::kUnused,
                                                 SkRegion::kDifference_Op, false, false,
                                                 SkMatrix::I(),
                                                 SkRect::MakeIWH(maskDC->width(), maskDC->height()));
    reducedClip.drawAlphaClipMask(maskDC.get());
    sk_sp<GrTexture> mask(maskDC->asTexture());

    int x = kCoverRect.x() - kLayerRect.x(),
        y = kCoverRect.y() - kLayerRect.y();

    // Now visualize the alpha mask by drawing a rect over the area where it is defined. The regions
    // inside window rectangles or outside the scissor should still have the initial checkerboard
    // intact. (This verifies we didn't spend any time modifying those pixels in the mask.)
    AlphaOnlyClip clip(mask.get(), x, y);
    dc->drawRect(clip, paint, SkMatrix::I(),
                 SkRect::Make(SkIRect::MakeXYWH(x, y, mask->width(), mask->height())));
}

void WindowRectanglesMaskGM::visualizeStencilMask(GrContext* ctx, GrDrawContext* dc,
                                                  const GrReducedClip& reducedClip,
                                                  const GrPaint& paint) {
    if (!ctx->resourceProvider()->attachStencilAttachment(dc->accessRenderTarget())) {
        return;
    }

    // Draw a checker pattern into the stencil buffer so we can visualize the regions left untouched
    // by the clip mask generation.
    this->stencilCheckerboard(dc, false);
    reducedClip.drawStencilClipMask(ctx, dc, {kLayerRect.x(), kLayerRect.y()});

    // Now visualize the stencil mask by covering the entire render target. The regions inside
    // window rectangless or outside the scissor should still have the initial checkerboard intact.
    // (This verifies we didn't spend any time modifying those pixels in the mask.)
    dc->drawPaint(StencilOnlyClip(), paint, SkMatrix::I());
}

void WindowRectanglesMaskGM::stencilCheckerboard(GrDrawContext* dc, bool flip) {
    constexpr static GrUserStencilSettings kSetClip(
        GrUserStencilSettings::StaticInit<
        0,
        GrUserStencilTest::kAlways,
        0,
        GrUserStencilOp::kSetClipBit,
        GrUserStencilOp::kKeep,
        0>()
    );

    dc->drawContextPriv().clearStencilClip(GrFixedClip::Disabled(), false);

    for (int y = 0; y < kLayerRect.height(); y += kMaskCheckerSize) {
        for (int x = (y & 1) == flip ? 0 : kMaskCheckerSize;
             x < kLayerRect.width(); x += 2 * kMaskCheckerSize) {
            SkIRect checker = SkIRect::MakeXYWH(x, y, kMaskCheckerSize, kMaskCheckerSize);
            dc->drawContextPriv().stencilRect(GrNoClip(), &kSetClip, false, SkMatrix::I(),
                                              SkRect::Make(checker));
        }
    }
}

void WindowRectanglesMaskGM::fail(SkCanvas* canvas) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setTextAlign(SkPaint::kCenter_Align);
    paint.setTextSize(20);
    sk_tool_utils::set_portable_typeface(&paint);

    SkString errorMsg;
    errorMsg.printf("Requires GPU with %i window rectangles", kNumWindows);

    canvas->clipRect(SkRect::Make(kCoverRect));
    canvas->clear(SK_ColorWHITE);
    canvas->drawText(errorMsg.c_str(), errorMsg.size(), SkIntToScalar(kCoverRect.centerX()),
                     SkIntToScalar(kCoverRect.centerY() - 10), paint);
}

DEF_GM( return new WindowRectanglesMaskGM(); )

#endif

}
