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

#include "tests/Test.h"

#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recording.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "tests/TestUtils.h"
#include "tools/ToolUtils.h"

using namespace skgpu::graphite;

namespace {

const SkISize kSurfaceSize = { 64, 64 };

constexpr SkColor4f kBackgroundColor = SkColors::kWhite;

bool run_test(skiatest::Reporter* reporter,
              Context* context,
              Recorder* recorder) {
    SkImageInfo ii = SkImageInfo::Make(kSurfaceSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    SkBitmap result0, result1;
    result0.allocPixels(ii);
    result1.allocPixels(ii);
    SkPixmap pm0, pm1;

    SkAssertResult(result0.peekPixels(&pm0));
    SkAssertResult(result1.peekPixels(&pm1));

    sk_sp<SkSurface> surface = SkSurface::MakeGraphite(recorder, ii);
    if (!surface) {
        ERRORF(reporter, "Surface creation failed");
        return false;
    }

    SkCanvas* canvas = surface->getCanvas();

    // Set up a recording to clear the surface
    canvas->clear(kBackgroundColor);
    std::unique_ptr<Recording> clearRecording = recorder->snap();
    if (!clearRecording) {
        ERRORF(reporter, "Recording creation failed");
        return false;
    }

    // Draw some text and get recording
    SkPaint paint;
    paint.setAntiAlias(true);

    SkFont font(ToolUtils::create_portable_typeface("serif", SkFontStyle()));
    font.setSubpixel(true);
    font.setSize(12);

    const char* text0 = "Hamburge";
    const size_t text0Len = strlen(text0);

    canvas->drawSimpleText(text0, text0Len, SkTextEncoding::kUTF8, 3, 20, font, paint);
    std::unique_ptr<Recording> text0Recording = recorder->snap();

    // Draw some more text and get recording
    const char* text1 = "burgefons";
    const size_t text1Len = strlen(text1);

    canvas->drawSimpleText(text1, text1Len, SkTextEncoding::kUTF8, 3, 40, font, paint);
    std::unique_ptr<Recording> text1Recording = recorder->snap();

    // Playback 0, then 1, and read pixels
    InsertRecordingInfo info;
    info.fRecording = clearRecording.get();
    context->insertRecording(info);
    info.fRecording = text0Recording.get();
    context->insertRecording(info);
    info.fRecording = text1Recording.get();
    context->insertRecording(info);
    context->submit();

    // For now, we cast and call directly into Surface. Once we have a better idea of
    // what the public API for synchronous graphite readPixels we can update this call to use
    // that instead.
    if (!static_cast<skgpu::graphite::Surface*>(surface.get())->onReadPixels(context,
                                                                             recorder,
                                                                             pm0,
                                                                             0,
                                                                             0)) {
        ERRORF(reporter, "readPixels failed");
        return false;
    }

    // Playback 1, then 0, and read pixels
    info.fRecording = clearRecording.get();
    context->insertRecording(info);
    info.fRecording = text1Recording.get();
    context->insertRecording(info);
    info.fRecording = text0Recording.get();
    context->insertRecording(info);
    context->submit();

    if (!static_cast<skgpu::graphite::Surface*>(surface.get())->onReadPixels(context,
                                                                             recorder,
                                                                             pm1,
                                                                             0,
                                                                             0)) {
        ERRORF(reporter, "readPixels failed");
        return false;
    }

    // Compare and contrast
    float tol = 1.f/256;
    const float tols[4] = {tol, tol, tol, tol};
    auto error = std::function<ComparePixmapsErrorReporter>([&](int x, int y,
                                                                const float diffs[4]) {
        SkASSERT(x >= 0 && y >= 0);
        ERRORF(reporter,
               "Error at %d, %d. Diff in floats: (%f, %f, %f, %f)",
               x, y, diffs[0], diffs[1], diffs[2], diffs[3]);
    });
    ComparePixels(pm0, pm1, tols, error);

    return true;
}

} // anonymous namespace

// This test captures two recordings A and B, plays them back as A then B, and B then A,
// and verifies that the result is the same.
DEF_GRAPHITE_TEST_FOR_CONTEXTS(RecordingOrderTest_Graphite, reporter, context) {
    std::unique_ptr<Recorder> recorder = context->makeRecorder();

    (void) run_test(reporter, context, recorder.get());
}
