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

#include "SkTypes.h"

#if SK_SUPPORT_GPU

#include "GrContextFactory.h"
#include "GrContextPriv.h"
#include "GrCaps.h"
#include "SkExecutor.h"
#include "Test.h"

using namespace sk_gpu_test;

DEF_GPUTEST(GrContextFactory_NVPRContextOptionHasPathRenderingSupport, reporter, options) {
    // Test that if NVPR is requested, the context always has path rendering
    // or the context creation fails.
    for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
        GrContextFactory testFactory(options);
        // Test that if NVPR is possible, caps are in sync.
        GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
        GrContext* context = testFactory.get(ctxType,
                                           GrContextFactory::ContextOverrides::kRequireNVPRSupport);
        if (!context) {
            continue;
        }
        REPORTER_ASSERT(reporter,
                        context->contextPriv().caps()->shaderCaps()->pathRenderingSupport());
    }
}

DEF_GPUTEST(GrContextFactory_NoPathRenderingIfNVPRDisabled, reporter, options) {
    // Test that if NVPR is explicitly disabled, the context has no path rendering support.

    for (int i = 0; i <= GrContextFactory::kLastContextType; ++i) {
        GrContextFactory testFactory(options);
        GrContextFactory::ContextType ctxType = (GrContextFactory::ContextType)i;
        GrContext* context =
            testFactory.get(ctxType, GrContextFactory::ContextOverrides::kDisableNVPR);
        if (context) {
            REPORTER_ASSERT(reporter,
                            !context->contextPriv().caps()->shaderCaps()->pathRenderingSupport());
        }
    }
}

DEF_GPUTEST(GrContextFactory_RequiredSRGBSupport, reporter, options) {
    // Test that if sRGB support is requested, the context always has that capability
    // or the context creation fails. Also test that if the creation fails, a context
    // created without that flag would not have had sRGB support.
    for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
        GrContextFactory testFactory(options);
        // Test that if sRGB is requested, caps are in sync.
        GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
        GrContext* context =
            testFactory.get(ctxType, GrContextFactory::ContextOverrides::kRequireSRGBSupport);

        if (context) {
            REPORTER_ASSERT(reporter, context->contextPriv().caps()->srgbSupport());
        } else {
            context = testFactory.get(ctxType);
            if (context) {
                REPORTER_ASSERT(reporter, !context->contextPriv().caps()->srgbSupport());
            }
        }
    }
}

DEF_GPUTEST(GrContextFactory_abandon, reporter, options) {
    for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
        GrContextFactory testFactory(options);
        GrContextFactory::ContextType ctxType = (GrContextFactory::ContextType) i;
        ContextInfo info1 = testFactory.getContextInfo(ctxType);
        if (!info1.grContext()) {
            continue;
        }
        REPORTER_ASSERT(reporter, info1.testContext());
         // Ref for comparison. The API does not explicitly say that this stays alive.
        info1.grContext()->ref();
        testFactory.abandonContexts();

        // Test that we get different context after abandon.
        ContextInfo info2 = testFactory.getContextInfo(ctxType);
        REPORTER_ASSERT(reporter, info2.grContext());
        REPORTER_ASSERT(reporter, info2.testContext());

        REPORTER_ASSERT(reporter, info1.grContext() != info2.grContext());
        // The GL context should also change, but it also could get the same address.

        info1.grContext()->unref();
    }
}

DEF_GPUTEST(GrContextFactory_sharedContexts, reporter, options) {
    for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
        GrContextFactory testFactory(options);
        GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
        ContextInfo info1 = testFactory.getContextInfo(ctxType);
        if (!info1.grContext()) {
            continue;
        }

        // Ref for passing in. The API does not explicitly say that this stays alive.
        info1.grContext()->ref();
        testFactory.abandonContexts();

        // Test that creating a context in a share group with an abandoned context fails.
        ContextInfo info2 = testFactory.getSharedContextInfo(info1.grContext());
        REPORTER_ASSERT(reporter, !info2.grContext());
        info1.grContext()->unref();

        // Create a new base context
        ContextInfo info3 = testFactory.getContextInfo(ctxType);
        if (!info3.grContext()) {
            // Vulkan NexusPlayer bot fails here. Sigh.
            continue;
        }

        // Creating a context in a share group may fail, but should never crash.
        ContextInfo info4 = testFactory.getSharedContextInfo(info3.grContext());
        if (!info4.grContext()) {
            continue;
        }
        REPORTER_ASSERT(reporter, info3.grContext() != info4.grContext());
        REPORTER_ASSERT(reporter, info3.testContext() != info4.testContext());

        // Passing a different index should create a new (unique) context.
        ContextInfo info5 = testFactory.getSharedContextInfo(info3.grContext(), 1);
        REPORTER_ASSERT(reporter, info5.grContext());
        REPORTER_ASSERT(reporter, info5.testContext());
        REPORTER_ASSERT(reporter, info5.grContext() != info4.grContext());
        REPORTER_ASSERT(reporter, info5.testContext() != info4.testContext());
    }
}

DEF_GPUTEST(GrContextFactory_executorAndTaskGroup, reporter, options) {
    for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
        // Verify that contexts have a task group iff we supply an executor with context options
        GrContextOptions contextOptions = options;
        contextOptions.fExecutor = nullptr;
        GrContextFactory serialFactory(contextOptions);

        std::unique_ptr<SkExecutor> threadPool = SkExecutor::MakeFIFOThreadPool(1);
        contextOptions.fExecutor = threadPool.get();
        GrContextFactory threadedFactory(contextOptions);

        GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
        ContextInfo serialInfo = serialFactory.getContextInfo(ctxType);
        if (GrContext* serialContext = serialInfo.grContext()) {
            REPORTER_ASSERT(reporter, nullptr == serialContext->contextPriv().getTaskGroup());
        }

        ContextInfo threadedInfo = threadedFactory.getContextInfo(ctxType);
        if (GrContext* threadedContext = threadedInfo.grContext()) {
            REPORTER_ASSERT(reporter, nullptr != threadedContext->contextPriv().getTaskGroup());
        }
    }
}

DEF_GPUTEST_FOR_ALL_CONTEXTS(GrContextDump, reporter, ctxInfo) {
    // Ensure that GrContext::dump doesn't assert (which is possible, if the JSON code is wrong)
    SkString result = ctxInfo.grContext()->contextPriv().dump();
    REPORTER_ASSERT(reporter, !result.isEmpty());
}

#endif
