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

#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradient.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/DecodeUtils.h"

#include <cstdint>
#include <utility>

class SkImage;
struct GrContextOptions;

// The gradient shader will use the texture strip atlas if it has too many colors. Make sure
// abandoning the context works.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TextureStripAtlasManagerGradientTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    auto context = ctxInfo.directContext();

    static const SkColor4f gColors[] = {SkColors::kRed, SkColors::kGreen, SkColors::kBlue,
                                        SkColors::kCyan, SkColors::kMagenta, SkColors::kYellow,
                                        SkColors::kBlack};
    static const float gPos[] = { 0, 0.17f, 0.32f, 0.49f, 0.66f, 0.83f, 1.0f };

    SkPaint p;
    p.setShader(SkShaders::TwoPointConicalGradient(SkPoint::Make(0, 0), 1.0f,
                                                   SkPoint::Make(10.0f, 20.0f), 2.0f,
                                                   {{gColors, gPos, SkTileMode::kClamp}, {}}));

    SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128);
    auto surface(SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, info));
    SkCanvas* canvas = surface->getCanvas();

    SkRect r = SkRect::MakeXYWH(10, 10, 100, 100);

    canvas->drawRect(r, p);

    context->abandonContext();
}

// The table color filter uses the texture strip atlas. Make sure abandoning the context works.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TextureStripAtlasManagerColorFilterTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    auto context = ctxInfo.directContext();

    sk_sp<SkImage> img = ToolUtils::GetResourceAsImage("images/mandrill_128.png");

    uint8_t identity[256];
    for (int i = 0; i < 256; i++) {
        identity[i] = i;
    }

    SkPaint p;
    p.setColorFilter(SkColorFilters::Table(identity));

    SkImageInfo info = SkImageInfo::MakeN32Premul(128, 128);
    auto surface(SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, info));
    SkCanvas* canvas = surface->getCanvas();

    canvas->drawImage(std::move(img), 0, 0, SkSamplingOptions(), &p);

    context->abandonContext();
}
