/*
 * 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/GrDirectContextPriv.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* rContext, 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 = rContext->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 dContext = GrAsDirectContext(rContext);

        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;
            }

            if (dContext) {
                // 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); )

}  // namespace skiagm
