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

#ifndef GrContextFactory_DEFINED
#define GrContextFactory_DEFINED

#include "include/gpu/GrContextOptions.h"
#include "include/gpu/GrDirectContext.h"

#include "include/private/SkTArray.h"
#include "tools/gpu/gl/GLTestContext.h"

struct GrVkBackendContext;

namespace sk_gpu_test {
class ContextInfo;

/**
 * This is a simple class that is useful in test apps that use different
 * GrContexts backed by different types of GL contexts. It manages creating the
 * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
 * factory is destroyed (though the caller can always grab a ref on the returned
 * Gr and GL contexts to make them outlive the factory).
 */
class GrContextFactory : SkNoncopyable {
public:
    // The availability of context types is subject to platform and build configuration
    // restrictions.
    enum ContextType {
        kGL_ContextType,             //! OpenGL context.
        kGLES_ContextType,           //! OpenGL ES context.
        kANGLE_D3D9_ES2_ContextType, //! ANGLE on Direct3D9 OpenGL ES 2 context.
        kANGLE_D3D11_ES2_ContextType,//! ANGLE on Direct3D11 OpenGL ES 2 context.
        kANGLE_D3D11_ES3_ContextType,//! ANGLE on Direct3D11 OpenGL ES 3 context.
        kANGLE_GL_ES2_ContextType,   //! ANGLE on OpenGL OpenGL ES 2 context.
        kANGLE_GL_ES3_ContextType,   //! ANGLE on OpenGL OpenGL ES 3 context.
        kCommandBuffer_ContextType,  //! Chromium command buffer OpenGL ES context.
        kVulkan_ContextType,         //! Vulkan
        kMetal_ContextType,          //! Metal
        kDirect3D_ContextType,       //! Direct3D 12
        kDawn_ContextType,           //! Dawn
        kMock_ContextType,           //! Mock context that does not draw.
        kLastContextType = kMock_ContextType
    };

    static const int kContextTypeCnt = kLastContextType + 1;

    /**
     * Overrides for the initial GrContextOptions provided at construction time, and required
     * features that will cause context creation to fail if not present.
     */
    enum class ContextOverrides {
        kNone                          = 0x0,
        kAvoidStencilBuffers           = 0x1,
        kFakeGLESVersionAs2            = 0x2,
        kReducedShaders                = 0x4,
    };

    static bool IsRenderingContext(ContextType type) {
        switch (type) {
            case kMock_ContextType:
                return false;
            default:
                return true;
        }
    }

    static GrBackendApi ContextTypeBackend(ContextType type) {
        switch (type) {
            case kVulkan_ContextType:
                return GrBackendApi::kVulkan;
            case kMetal_ContextType:
                return GrBackendApi::kMetal;
            case kDirect3D_ContextType:
                return GrBackendApi::kDirect3D;
            case kDawn_ContextType:
                return GrBackendApi::kDawn;
            case kMock_ContextType:
                return GrBackendApi::kMock;
            default:
                return GrBackendApi::kOpenGL;
        }
    }

    static const char* ContextTypeName(ContextType contextType) {
        switch (contextType) {
            case kGL_ContextType:
                return "OpenGL";
            case kGLES_ContextType:
                return "OpenGLES";
            case kANGLE_D3D9_ES2_ContextType:
                return "ANGLE D3D9 ES2";
            case kANGLE_D3D11_ES2_ContextType:
                return "ANGLE D3D11 ES2";
            case kANGLE_D3D11_ES3_ContextType:
                return "ANGLE D3D11 ES3";
            case kANGLE_GL_ES2_ContextType:
                return "ANGLE GL ES2";
            case kANGLE_GL_ES3_ContextType:
                return "ANGLE GL ES3";
            case kCommandBuffer_ContextType:
                return "Command Buffer";
            case kVulkan_ContextType:
                return "Vulkan";
            case kMetal_ContextType:
                return "Metal";
            case kDirect3D_ContextType:
                return "Direct3D";
            case kDawn_ContextType:
                return "Dawn";
            case kMock_ContextType:
                return "Mock";
        }
        SK_ABORT("Unreachable");
    }

    explicit GrContextFactory(const GrContextOptions& opts);
    GrContextFactory();

    ~GrContextFactory();

    void destroyContexts();
    void abandonContexts();
    void releaseResourcesAndAbandonContexts();

    /**
     * Get a context initialized with a type of GL context. It also makes the GL context current.
     */
    ContextInfo getContextInfo(ContextType type, ContextOverrides = ContextOverrides::kNone);

    /**
     * Get a context in the same share group as the passed in GrContext, with the same type and
     * overrides. To get multiple contexts in a single share group, pass the same shareContext,
     * with different values for shareIndex.
     */
    ContextInfo getSharedContextInfo(GrDirectContext* shareContext, uint32_t shareIndex = 0);

    /**
     * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
     */
    GrDirectContext* get(ContextType type, ContextOverrides overrides = ContextOverrides::kNone);
    const GrContextOptions& getGlobalOptions() const { return fGlobalOptions; }

private:
    ContextInfo getContextInfoInternal(ContextType type, ContextOverrides overrides,
                                       GrDirectContext* shareContext, uint32_t shareIndex);

    struct Context {
        ContextType       fType;
        ContextOverrides  fOverrides;
        GrContextOptions  fOptions;
        GrBackendApi      fBackend;
        TestContext*      fTestContext;
        GrDirectContext*  fGrContext;
        GrDirectContext*  fShareContext;
        uint32_t          fShareIndex;

        bool              fAbandoned;
    };
    SkTArray<Context, true>         fContexts;
    std::unique_ptr<GLTestContext>  fSentinelGLContext;
    const GrContextOptions          fGlobalOptions;
};

class ContextInfo {
public:
    ContextInfo() = default;
    ContextInfo& operator=(const ContextInfo&) = default;

    GrContextFactory::ContextType type() const { return fType; }
    GrBackendApi backend() const { return GrContextFactory::ContextTypeBackend(fType); }

    GrDirectContext* directContext() const { return fContext; }
    TestContext* testContext() const { return fTestContext; }

#ifdef SK_GL
    GLTestContext* glContext() const {
        SkASSERT(GrBackendApi::kOpenGL == this->backend());
        return static_cast<GLTestContext*>(fTestContext);
    }
#endif

    const GrContextOptions& options() const { return fOptions; }

private:
    ContextInfo(GrContextFactory::ContextType type,
                TestContext* testContext,
                GrDirectContext* context,
                const GrContextOptions& options)
            : fType(type), fTestContext(testContext), fContext(context), fOptions(options) {}

    GrContextFactory::ContextType fType = GrContextFactory::kGL_ContextType;
    // Valid until the factory destroys it via abandonContexts() or destroyContexts().
    TestContext* fTestContext = nullptr;
    GrDirectContext* fContext = nullptr;
    GrContextOptions fOptions;

    friend class GrContextFactory;
};

}  // namespace sk_gpu_test

GR_MAKE_BITFIELD_CLASS_OPS(sk_gpu_test::GrContextFactory::ContextOverrides);

#endif
