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

#include "gm/gm.h"

#include "include/core/SkPath.h"
#include "include/gpu/GrContextOptions.h"
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/ccpr/GrCCPathCache.h"
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
#include "tools/ToolUtils.h"

namespace skiagm {

#define ERR_MSG_ASSERT(COND) \
    do { \
        if (!(COND)) { \
            errorMsg->printf("preservefillrule.cpp(%i): assert(%s)", \
                             __LINE__, #COND); \
            return DrawResult::kFail; \
        } \
    } while (false)


/**
 * This test ensures that the ccpr path cache preserves fill rules properly, both in the case where
 * we copy paths into a8 literal coverage atlases, as well as in the case where we just reuse a
 * stashed fp16 coverage count atlas.
 */
class PreserveFillRuleGM : public GpuGM {
public:
    // fStarSize affects whether ccpr copies the paths to an a8 literal coverage atlas, or just
    // leaves them stashed in an fp16 coverage count atlas. The threshold for copying to a8 is
    // currently 256x256 total pixels copied. If this ever changes, there is code in onDraw that
    // will detect the unexpected behavior and draw a failure message.
    PreserveFillRuleGM(bool literalCoverageAtlas)
            : fLiteralCoverageAtlas(literalCoverageAtlas)
            , fStarSize((fLiteralCoverageAtlas) ? 200 : 20) {
    }

private:
    SkString onShortName() override {
        SkString name("preservefillrule");
        name += (fLiteralCoverageAtlas) ? "_big" : "_little";
        return name;
    }
    SkISize onISize() override { return SkISize::Make(fStarSize * 2, fStarSize * 2); }

    void modifyGrContextOptions(GrContextOptions* ctxOptions) override {
        ctxOptions->fGpuPathRenderers = GpuPathRenderers::kCoverageCounting;
        ctxOptions->fAllowPathMaskCaching = true;
    }

    DrawResult onDraw(GrRecordingContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
                      SkString* errorMsg) override {
        using CoverageType = GrCCAtlas::CoverageType;

        if (rtc->numSamples() > 1) {
            errorMsg->set("ccpr is currently only used for coverage AA");
            return DrawResult::kSkip;
        }

        auto* ccpr = ctx->priv().drawingManager()->getCoverageCountingPathRenderer();
        if (!ccpr) {
            errorMsg->set("ccpr only");
            return DrawResult::kSkip;
        }

        auto pathCache = ccpr->testingOnly_getPathCache();
        if (!pathCache) {
            errorMsg->set("ccpr is not in caching mode. "
                          "Are you using viewer? Launch with \"--cachePathMasks true\".");
            return DrawResult::kFail;
        }

        auto starRect = SkRect::MakeWH(fStarSize, fStarSize);
        SkPath star7_winding = ToolUtils::make_star(starRect, 7);
        star7_winding.setFillType(SkPathFillType::kWinding);

        SkPath star7_evenOdd = star7_winding;
        star7_evenOdd.transform(SkMatrix::Translate(0, fStarSize));
        star7_evenOdd.setFillType(SkPathFillType::kEvenOdd);

        SkPath star5_winding = ToolUtils::make_star(starRect, 5);
        star5_winding.transform(SkMatrix::Translate(fStarSize, 0));
        star5_winding.setFillType(SkPathFillType::kWinding);

        SkPath star5_evenOdd = star5_winding;
        star5_evenOdd.transform(SkMatrix::Translate(0, fStarSize));
        star5_evenOdd.setFillType(SkPathFillType::kEvenOdd);

        SkPaint paint;
        paint.setColor(SK_ColorGREEN);
        paint.setAntiAlias(true);

        for (int i = 0; i < 3; ++i) {
            canvas->clear(SK_ColorWHITE);
            canvas->drawPath(star7_winding, paint);
            canvas->drawPath(star7_evenOdd, paint);
            canvas->drawPath(star5_winding, paint);
            canvas->drawPath(star5_evenOdd, paint);
            rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr);

            // Ensure the path cache is behaving in such a way that we are actually testing what we
            // think we are.
            int numCachedPaths = 0;
            for (GrCCPathCacheEntry* entry : pathCache->testingOnly_getLRU()) {
                if (0 == i) {
                    // We don't cache an atlas on the first hit.
                    ERR_MSG_ASSERT(!entry->cachedAtlas());
                } else {
                    // The stars should be cached in an atlas now.
                    ERR_MSG_ASSERT(entry->cachedAtlas());

                    CoverageType atlasCoverageType = entry->cachedAtlas()->coverageType();
                    if (i < 2) {
                        // We never copy to an a8 atlas before the second hit.
                        ERR_MSG_ASSERT(ccpr->coverageType() == atlasCoverageType);
                    } else if (fLiteralCoverageAtlas) {
                        // Verify fStarSize is large enough that the paths got copied to an a8
                        // atlas.
                        ERR_MSG_ASSERT(CoverageType::kA8_LiteralCoverage == atlasCoverageType);
                    } else {
                        // Verify fStarSize is small enough that the paths did *NOT* get copied to
                        // an a8 atlas.
                        ERR_MSG_ASSERT(ccpr->coverageType() == atlasCoverageType);
                    }
                }
                ++numCachedPaths;
            }
            // Verify all 4 paths are tracked by the path cache.
            ERR_MSG_ASSERT(4 == numCachedPaths);
        }

        return DrawResult::kOk;
    }

private:
    const bool fLiteralCoverageAtlas;
    const int fStarSize;
};

DEF_GM( return new PreserveFillRuleGM(true); )
DEF_GM( return new PreserveFillRuleGM(false); )

}
