/*
 * Copyright 2023 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"

#if defined(SK_GANESH)

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSurface.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "tests/CtsEnforcement.h"
#include "tools/gpu/ProtectedUtils.h"

static const int kSize = 8;

DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_SmokeTest, reporter, ctxInfo, CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    if (!dContext->supportsProtectedContent()) {
        // Protected content not supported
        return;
    }

    for (bool textureable : { true, false }) {
        for (bool isProtected : { true, false }) {
            if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
                continue;
            }

            sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
                                                                                { kSize, kSize },
                                                                                textureable,
                                                                                isProtected);
            if (!surface) {
                continue;
            }

            sk_sp<SkImage> image = surface->makeImageSnapshot();
            if (!image) {
                ERRORF(reporter, "Could not makeImageSnapshot from a %s surface.",
                       isProtected ? "protected" : "unprotected");
                continue;
            }

            dContext->submit(GrSyncCpu::kYes);

            REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
            ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
        }
    }

    for (bool isProtected : { true, false }) {
        if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
            continue;
        }

        sk_sp<SkImage> image = ProtectedUtils::CreateProtectedSkImage(dContext,
                                                                      { kSize, kSize },
                                                                      SkColors::kBlue,
                                                                      isProtected);
        if (!image) {
            continue;
        }

        dContext->submit(GrSyncCpu::kYes);

        REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
        ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
    }

    for (bool renderable : { true, false }) {
        for (bool isProtected : { true, false }) {
            GrBackendTexture beTex = dContext->createBackendTexture(16,
                                                                    16,
                                                                    kRGBA_8888_SkColorType,
                                                                    SkColors::kTransparent,
                                                                    skgpu::Mipmapped::kNo,
                                                                    GrRenderable(renderable),
                                                                    GrProtected(isProtected));

            REPORTER_ASSERT(reporter, beTex.isValid());
            REPORTER_ASSERT(reporter, beTex.isProtected() == isProtected);

            dContext->flushAndSubmit(GrSyncCpu::kYes);

            {
                sk_sp<SkImage> img = SkImages::BorrowTextureFrom(dContext, beTex,
                                                                 kTopLeft_GrSurfaceOrigin,
                                                                 kRGBA_8888_SkColorType,
                                                                 kPremul_SkAlphaType,
                                                                 /* colorSpace= */ nullptr);

                REPORTER_ASSERT(reporter, img->isProtected() == isProtected);
            }

            if (beTex.isValid()) {
                dContext->deleteBackendTexture(beTex);
            }
        }
    }
}

// Verify that readPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_readPixelsFromSurfaces, reporter, ctxInfo,
                                 CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    if (!dContext->supportsProtectedContent()) {
        // Protected content not supported
        return;
    }

    sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
                                                                        { kSize, kSize },
                                                                        /* textureable= */ true,
                                                                        /* isProtected= */ true);
    if (!surface) {
        return;
    }

    SkBitmap readback;
    readback.allocPixels(surface->imageInfo());
    REPORTER_ASSERT(reporter, !surface->readPixels(readback, 0, 0));
}

// Graphite does not perform Copy-on-Write which is why there is no DEF_GRAPHITE_TEST correlate
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_CopyOnWrite, reporter, ctxInfo, CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    if (!dContext->supportsProtectedContent()) {
        // Protected content not supported
        return;
    }

    SkImageInfo ii = SkImageInfo::Make({ kSize, kSize },
                                       kRGBA_8888_SkColorType,
                                       kPremul_SkAlphaType);

    // We can't use ProtectedUtils::CreateProtectedSkSurface here bc that will wrap a backend
    // texture which blocks the copy-on-write-behavior
    sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext,
                                                        skgpu::Budgeted::kNo,
                                                        ii,
                                                        /* sampleCount= */ 1,
                                                        kBottomLeft_GrSurfaceOrigin,
                                                        /* surfaceProps= */ nullptr,
                                                        /* shouldCreateWithMips= */ false,
                                                        /* isProtected= */ true);
    if (!surface) {
        return;
    }

    SkCanvas* canvas = surface->getCanvas();
    REPORTER_ASSERT(reporter, canvas);

    sk_sp<SkImage> imageBefore = surface->makeImageSnapshot();
    REPORTER_ASSERT(reporter, imageBefore);
    REPORTER_ASSERT(reporter, imageBefore->isProtected());

    SkPaint paint;
    paint.setColor(SK_ColorBLACK);
    canvas->drawRect(SkRect::MakeWH(4, 4), paint);

    sk_sp<SkImage> imageAfter = surface->makeImageSnapshot();
    REPORTER_ASSERT(reporter, imageAfter);
    REPORTER_ASSERT(reporter, imageAfter->isProtected());

    REPORTER_ASSERT(reporter, imageBefore != imageAfter);

    SkBitmap readback;
    readback.allocPixels(imageAfter->imageInfo());
    REPORTER_ASSERT(reporter, !imageAfter->readPixels(dContext, readback.pixmap(), 0, 0));
}


namespace {

struct AsyncContext {
    bool fCalled = false;
    std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
};

static void async_callback(void* c, std::unique_ptr<const SkSurface::AsyncReadResult> result) {
    auto context = static_cast<AsyncContext*>(c);
    context->fResult = std::move(result);
    context->fCalled = true;
}

}  // anonymous namespace

// Verify that asyncRescaleAndReadPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_asyncRescaleAndReadPixelsFromSurfaces, reporter, ctxInfo,
                                 CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    if (!dContext->supportsProtectedContent()) {
        // Protected content not supported
        return;
    }

    sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
                                                                        { kSize, kSize },
                                                                        /* textureable= */ true,
                                                                        /* isProtected= */ true);
    if (!surface) {
        return;
    }

    AsyncContext cbContext;

    surface->asyncRescaleAndReadPixels(surface->imageInfo(),
                                       SkIRect::MakeWH(surface->width(), surface->height()),
                                       SkSurface::RescaleGamma::kSrc,
                                       SkSurface::RescaleMode::kNearest,
                                       async_callback, &cbContext);
    dContext->submit();
    while (!cbContext.fCalled) {
        dContext->checkAsyncWorkCompletion();
    }
    REPORTER_ASSERT(reporter, !cbContext.fResult);
}

DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_pictureShader, reporter,
                                 ctxInfo, CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    if (!dContext->supportsProtectedContent()) {
        // Protected content not supported
        return;
    }

    sk_sp<SkImage> protectedImage = ProtectedUtils::CreateProtectedSkImage(dContext,
                                                                           { kSize, kSize },
                                                                           SkColors::kBlue,
                                                                           /* isProtected= */ true);
    dContext->flushAndSubmit(GrSyncCpu::kYes);

    REPORTER_ASSERT(reporter, protectedImage);
    REPORTER_ASSERT(reporter, protectedImage->isProtected());

    sk_sp<SkPicture> protectedPicture;
    {
        SkPictureRecorder recorder;
        recorder.beginRecording(100, 100)->drawImage(protectedImage.get(), 0, 0);
        protectedPicture = recorder.finishRecordingAsPicture();
        REPORTER_ASSERT(reporter, protectedPicture);
    }

    SkPaint protectedPaint;
    protectedPaint.setShader(protectedPicture->makeShader(SkTileMode::kRepeat,
                                                          SkTileMode::kRepeat,
                                                          SkFilterMode::kNearest));

    SkImageInfo ii = SkImageInfo::Make({ kSize, kSize },
                                       kRGBA_8888_SkColorType,
                                       kPremul_SkAlphaType);

    for (bool isProtected : { true, false }) {
        sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext,
                                                            skgpu::Budgeted::kNo,
                                                            ii,
                                                            /* sampleCount= */ 1,
                                                            kBottomLeft_GrSurfaceOrigin,
                                                            /* surfaceProps= */ nullptr,
                                                            /* shouldCreateWithMips= */ false,
                                                            isProtected);

        REPORTER_ASSERT(reporter, surface);

        // For the un-protected surface, drawing the SkPicture containing the protected
        // image should cause the final draw of the generated image to the surface to fail
        // while the generation of the internal (protected) image should succeed.
        surface->getCanvas()->drawPaint(protectedPaint);
    }

    dContext->flushAndSubmit(GrSyncCpu::kYes);
}

#endif  // defined(SK_GANESH)
