/*
 * Copyright 2020 Google Inc.
 *
 * 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/SkCanvas.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/gpu/GrContextOptions.h"
#include "include/gpu/GrDirectContext.h"
#include "include/utils/SkRandom.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/ops/TessellationPathRenderer.h"

static constexpr float kStrokeWidth = 100;
static constexpr int kTestWidth = 120 * 4;
static constexpr int kTestHeight = 120 * 3 + 140;

static void draw_strokes(SkCanvas* canvas, SkRandom* rand, const SkPath& path,
                         const SkPath& cubic) {
    SkPaint strokePaint;
    strokePaint.setAntiAlias(true);
    strokePaint.setStrokeWidth(kStrokeWidth);
    strokePaint.setStyle(SkPaint::kStroke_Style);

    SkAutoCanvasRestore arc(canvas, true);
    strokePaint.setStrokeJoin(SkPaint::kBevel_Join);
    strokePaint.setColor(rand->nextU() | 0xff808080);
    canvas->drawPath(path, strokePaint);

    canvas->translate(120, 0);
    strokePaint.setStrokeJoin(SkPaint::kRound_Join);
    strokePaint.setColor(rand->nextU() | 0xff808080);
    canvas->drawPath(path, strokePaint);

    canvas->translate(120, 0);
    strokePaint.setStrokeJoin(SkPaint::kMiter_Join);
    strokePaint.setColor(rand->nextU() | 0xff808080);
    canvas->drawPath(path, strokePaint);

    canvas->translate(120, 0);
    strokePaint.setColor(rand->nextU() | 0xff808080);
    canvas->drawPath(cubic, strokePaint);
}

static void draw_test(SkCanvas* canvas) {
    SkRandom rand;

    if (canvas->recordingContext() &&
        canvas->recordingContext()->priv().caps()->shaderCaps()->tessellationSupport() &&
        canvas->recordingContext()->priv().caps()->shaderCaps()->maxTessellationSegments() == 5) {
        // The caller successfully overrode the max tessellation segments to 5. Indicate this in the
        // background color.
        canvas->clear(SkColorSetARGB(255, 64, 0, 0));
    } else {
        canvas->clear(SK_ColorBLACK);
    }

    SkAutoCanvasRestore arc(canvas, true);
    canvas->translate(60, 60);

    draw_strokes(canvas, &rand,
            SkPath().lineTo(10,0).lineTo(10,10),
            SkPath().cubicTo(10,0, 10,0, 10,10));
    canvas->translate(0, 120);

    draw_strokes(canvas, &rand,
            SkPath().lineTo(0,-10).lineTo(0,10),
            SkPath().cubicTo(0,-10, 0,-10, 0,10));
    canvas->translate(0, 120);

    draw_strokes(canvas, &rand,
            SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,10).lineTo(0,10),
            SkPath().cubicTo(0,-10, 10,10, 0,10));
    canvas->translate(0, 140);

    draw_strokes(canvas, &rand,
            SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,0).lineTo(0,0),
            SkPath().cubicTo(0,-10, 10,0, 0,0));
    canvas->translate(0, 120);
}

DEF_SIMPLE_GM(widebuttcaps, canvas, kTestWidth, kTestHeight) {
    canvas->clear(SK_ColorBLACK);
    draw_test(canvas);
}

class WideButtCaps_tess_segs_5 : public skiagm::GM {
    SkString onShortName() override {
        return SkString("widebuttcaps_tess_segs_5");
    }

    SkISize onISize() override {
        return SkISize::Make(kTestWidth, kTestHeight);
    }

    // Pick a very small, odd (and better yet, prime) number of segments.
    //
    // - Odd because it makes the tessellation strip asymmetric, which will be important to test for
    //   future plans that involve drawing in reverse order.
    //
    // - >=4 because the tessellator code will just assume we have enough to combine a miter join
    //   and line in a single patch. (Requires 4 segments. Spec required minimum is 64.)
    inline static constexpr int kMaxTessellationSegmentsOverride = 5;

    void modifyGrContextOptions(GrContextOptions* options) override {
        options->fMaxTessellationSegmentsOverride = kMaxTessellationSegmentsOverride;
        options->fAlwaysPreferHardwareTessellation = true;
        // Only allow the tessellation path renderer.
        options->fGpuPathRenderers = (GpuPathRenderers)((int)options->fGpuPathRenderers &
                                                        (int)GpuPathRenderers::kTessellation);
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        auto dContext = GrAsDirectContext(canvas->recordingContext());
        if (!dContext) {
            *errorMsg = "GM relies on having access to a live direct context.";
            return DrawResult::kSkip;
        }

        if (!dContext->priv().caps()->shaderCaps()->tessellationSupport() ||
            !skgpu::v1::TessellationPathRenderer::IsSupported(*dContext->priv().caps())) {
            errorMsg->set("Tessellation not supported.");
            return DrawResult::kSkip;
        }
        auto opts = dContext->priv().drawingManager()->testingOnly_getOptionsForPathRendererChain();
        if (!(opts.fGpuPathRenderers & GpuPathRenderers::kTessellation)) {
            errorMsg->set("TessellationPathRenderer disabled.");
            return DrawResult::kSkip;
        }
        if (dContext->priv().caps()->shaderCaps()->maxTessellationSegments() !=
            kMaxTessellationSegmentsOverride) {
            errorMsg->set("modifyGrContextOptions() did not limit maxTessellationSegments. "
                          "(Are you running viewer? If so use '--maxTessellationSegments 5'.)");
            return DrawResult::kFail;
        }
        // Suppress a tessellator warning message that caps.maxTessellationSegments is too small.
        GrRecordingContextPriv::AutoSuppressWarningMessages aswm(dContext);
        draw_test(canvas);
        return DrawResult::kOk;
    }
};

DEF_GM( return new WideButtCaps_tess_segs_5; )
