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

#include "tests/Test.h"

#ifdef SK_GL
#include "include/core/SkAlphaType.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrTypes.h"
#include "include/gpu/gl/GrGLFunctions.h"
#include "include/gpu/gl/GrGLInterface.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "include/private/SkTDArray.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/gl/GrGLCaps.h"
#include "src/gpu/ganesh/gl/GrGLDefines_impl.h"
#include "src/gpu/ganesh/gl/GrGLGpu.h"
#include "src/gpu/ganesh/gl/GrGLUtil.h"
#include "tests/CtsEnforcement.h"
#include "tools/gpu/gl/GLTestContext.h"

struct GrContextOptions;

DEF_GANESH_TEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest,
                                          reporter,
                                          ctxInfo,
                                          CtsEnforcement::kApiLevel_T) {
#define GL(F) GR_GL_CALL(ctxInfo.glContext()->gl(), F)

    auto dContext = ctxInfo.directContext();
    GrGpu* gpu = dContext->priv().getGpu();
    GrGLGpu* glGpu = static_cast<GrGLGpu*>(dContext->priv().getGpu());

    struct Target {
        GrGLenum fName;
        GrGLenum fQuery;
    };
    SkTDArray<Target> targets;
    targets.push_back({GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BINDING_2D});
    bool supportExternal;
    if ((supportExternal = glGpu->glCaps().shaderCaps()->fExternalTextureSupport)) {
        targets.push_back({GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_BINDING_EXTERNAL});
    }
    bool supportRectangle;
    if ((supportRectangle = glGpu->glCaps().rectangleTextureSupport())) {
        targets.push_back({GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_BINDING_RECTANGLE});
    }
    GrGLint numUnits = 0;
    GL(GetIntegerv(GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numUnits));
    SkTDArray<GrGLuint> claimedIDs;
    claimedIDs.resize(numUnits * targets.size());
    GL(GenTextures(claimedIDs.size(), claimedIDs.begin()));

    auto resetBindings = [&] {
        int i = 0;
        for (int u = 0; u < numUnits; ++u) {
            GL(ActiveTexture(GR_GL_TEXTURE0 + u));
            for (auto target : targets) {
                GL(BindTexture(target.fName, claimedIDs[i++]));
            }
        }
    };
    auto checkBindings = [&] {
        int i = 0;
        for (int u = 0; u < numUnits; ++u) {
            GL(ActiveTexture(GR_GL_TEXTURE0 + u));
            for (auto target : targets) {
                GrGLint boundID = -1;
                GL(GetIntegerv(target.fQuery, &boundID));
                if (boundID != (int) claimedIDs[i] && boundID != 0) {
                    ERRORF(reporter, "Unit %d, target 0x%04x has ID %d bound. Expected %d or 0.", u,
                           target.fName, boundID, claimedIDs[i]);
                    return;
                }
                ++i;
            }
        }
    };

    // Initialize texture unit/target combo bindings to 0.
    dContext->flushAndSubmit();
    resetBindings();
    dContext->resetContext();

    // Test creating a texture and then resetting bindings.
    static constexpr SkISize kDims = {10, 10};
    GrBackendFormat format = gpu->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
                                                                  GrRenderable::kNo);
    auto tex = gpu->createTexture(kDims,
                                  format,
                                  GrTextureType::k2D,
                                  GrRenderable::kNo,
                                  1,
                                  GrMipmapped::kNo,
                                  SkBudgeted::kNo,
                                  GrProtected::kNo,
                                  /*label=*/"TextureBindingsResetTest");
    REPORTER_ASSERT(reporter, tex);
    dContext->resetGLTextureBindings();
    checkBindings();
    resetBindings();
    dContext->resetContext();

    // Test drawing and then resetting bindings. This should force a MIP regeneration if MIP
    // maps are supported as well.
    auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    auto surf = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, info, 1, nullptr);
    surf->getCanvas()->clear(0x80FF0000);
    auto img = surf->makeImageSnapshot();
    surf->getCanvas()->clear(SK_ColorBLUE);
    surf->getCanvas()->save();
    surf->getCanvas()->scale(0.25, 0.25);
    surf->getCanvas()->drawImage(img.get(), 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3}), nullptr);
    surf->getCanvas()->restore();
    surf->flushAndSubmit();
    dContext->resetGLTextureBindings();
    checkBindings();
    resetBindings();
    dContext->resetContext();

    if (supportExternal) {
        GrBackendTexture texture2D = dContext->createBackendTexture(10,
                                                                    10,
                                                                    kRGBA_8888_SkColorType,
                                                                    SkColors::kTransparent,
                                                                    GrMipmapped::kNo,
                                                                    GrRenderable::kNo,
                                                                    GrProtected::kNo);
        GrGLTextureInfo info2D;
        REPORTER_ASSERT(reporter, texture2D.getGLTextureInfo(&info2D));
        GrEGLImage eglImage = ctxInfo.glContext()->texture2DToEGLImage(info2D.fID);
        REPORTER_ASSERT(reporter, eglImage);
        GrGLTextureInfo infoExternal;
        infoExternal.fID = ctxInfo.glContext()->eglImageToExternalTexture(eglImage);
        infoExternal.fTarget = GR_GL_TEXTURE_EXTERNAL;
        infoExternal.fFormat = info2D.fFormat;
        REPORTER_ASSERT(reporter, infoExternal.fID);
        GrBackendTexture backendTexture(10, 10, GrMipmapped::kNo, infoExternal);
        // Above texture creation will have messed with GL state and bindings.
        resetBindings();
        dContext->resetContext();
        img = SkImage::MakeFromTexture(dContext, backendTexture, kTopLeft_GrSurfaceOrigin,
                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
        REPORTER_ASSERT(reporter, img);
        surf->getCanvas()->drawImage(img, 0, 0);
        img.reset();
        surf->flushAndSubmit();
        dContext->resetGLTextureBindings();
        checkBindings();
        resetBindings();
        GL(DeleteTextures(1, &infoExternal.fID));
        ctxInfo.glContext()->destroyEGLImage(eglImage);
        dContext->deleteBackendTexture(texture2D);
        dContext->resetContext();
    }

    if (supportRectangle) {
        format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE);
        GrBackendTexture rectangleTexture = dContext->createBackendTexture(
                10, 10, format, GrMipmapped::kNo, GrRenderable::kNo);
        if (rectangleTexture.isValid()) {
            img = SkImage::MakeFromTexture(dContext, rectangleTexture, kTopLeft_GrSurfaceOrigin,
                                           kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
            REPORTER_ASSERT(reporter, img);
            surf->getCanvas()->drawImage(img, 0, 0);
            img.reset();
            surf->flushAndSubmit();
            dContext->resetGLTextureBindings();
            checkBindings();
            resetBindings();
            dContext->deleteBackendTexture(rectangleTexture);
        }
    }

    GL(DeleteTextures(claimedIDs.size(), claimedIDs.begin()));

#undef GL
}

#endif  // SK_GL
