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

#include "GrContextFactory.h"
#include "gl/GLTestContext.h"

#if SK_ANGLE
    #include "gl/angle/GLTestContext_angle.h"
#endif
#if SK_COMMAND_BUFFER
    #include "gl/command_buffer/GLTestContext_command_buffer.h"
#endif
#include "gl/debug/DebugGLTestContext.h"
#if SK_MESA
    #include "gl/mesa/GLTestContext_mesa.h"
#endif
#ifdef SK_VULKAN
#include "vk/VkTestContext.h"
#endif
#include "gl/null/NullGLTestContext.h"
#include "gl/GrGLGpu.h"
#include "GrCaps.h"

namespace sk_gpu_test {
GrContextFactory::GrContextFactory() { }

GrContextFactory::GrContextFactory(const GrContextOptions& opts)
    : fGlobalOptions(opts) {
    // In this factory, instanced rendering is specified with kUseInstanced_ContextOptions.
    SkASSERT(!fGlobalOptions.fEnableInstancedRendering);
}

GrContextFactory::~GrContextFactory() {
    this->destroyContexts();
}

void GrContextFactory::destroyContexts() {
    for (Context& context : fContexts) {
        if (context.fTestContext) {
            context.fTestContext->makeCurrent();
        }
        if (!context.fGrContext->unique()) {
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
        }
        context.fGrContext->unref();
        delete context.fTestContext;
    }
    fContexts.reset();
}

void GrContextFactory::abandonContexts() {
    for (Context& context : fContexts) {
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                context.fTestContext->makeCurrent();
                context.fTestContext->testAbandon();
                delete(context.fTestContext);
                context.fTestContext = nullptr;
            }
            context.fGrContext->abandonContext();
            context.fAbandoned = true;
        }
    }
}

void GrContextFactory::releaseResourcesAndAbandonContexts() {
    for (Context& context : fContexts) {
        if (!context.fAbandoned) {
            if (context.fTestContext) {
                context.fTestContext->makeCurrent();
            }
            context.fGrContext->releaseResourcesAndAbandonContext();
            context.fAbandoned = true;
            if (context.fTestContext) {
                delete context.fTestContext;
                context.fTestContext = nullptr;
            }
        }
    }
}

#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
const GrContextFactory::ContextType GrContextFactory::kNativeGL_ContextType =
    GrContextFactory::kGL_ContextType;
#else
const GrContextFactory::ContextType GrContextFactory::kNativeGL_ContextType =
    GrContextFactory::kGLES_ContextType;
#endif

ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOptions options) {
    for (int i = 0; i < fContexts.count(); ++i) {
        Context& context = fContexts[i];
        if (context.fType == type &&
            context.fOptions == options &&
            !context.fAbandoned) {
            context.fTestContext->makeCurrent();
            return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
        }
    }
    SkAutoTDelete<TestContext> testCtx;
    sk_sp<GrContext> grCtx;
    GrBackendContext backendContext = 0;
    sk_sp<const GrGLInterface> glInterface;
    GrBackend backend = ContextTypeBackend(type);
    switch (backend) {
        case kOpenGL_GrBackend: {
            GLTestContext* glCtx;
            switch (type) {
                case kGL_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard);
                    break;
                case kGLES_ContextType:
                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard);
                    break;
#if SK_ANGLE
#   ifdef SK_BUILD_FOR_WIN
                case kANGLE_ContextType:
                    glCtx = CreateANGLEDirect3DGLTestContext();
                    break;
#   endif
                case kANGLE_GL_ContextType:
                    glCtx = CreateANGLEOpenGLGLTestContext();
                    break;
#endif
#if SK_COMMAND_BUFFER
                case kCommandBuffer_ContextType:
                    glCtx = CommandBufferGLTestContext::Create();
                    break;
#endif
#if SK_MESA
                case kMESA_ContextType:
                    glCtx = CreateMesaGLTestContext();
                    break;
#endif
                case kNullGL_ContextType:
                    glCtx = CreateNullGLTestContext(kEnableNVPR_ContextOptions & options);
                    break;
                case kDebugGL_ContextType:
                    glCtx = CreateDebugGLTestContext();
                    break;
                default:
                    return ContextInfo();
            }
            if (!glCtx) {
                return ContextInfo();
            }
            testCtx.reset(glCtx);
            glInterface.reset(SkRef(glCtx->gl()));
            // Block NVPR from non-NVPR types. We don't block NVPR from contexts that will use
            // instanced rendering because that would prevent us from testing mixed samples.
            if (!((kEnableNVPR_ContextOptions | kUseInstanced_ContextOptions) & options)) {
                glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
                if (!glInterface) {
                    return ContextInfo();
                }
            }
            backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
            break;
        }
#ifdef SK_VULKAN
        case kVulkan_GrBackend:
            SkASSERT(kVulkan_ContextType == type);
            if (kEnableNVPR_ContextOptions & options) {
                return ContextInfo();
            }
            testCtx.reset(CreatePlatformVkTestContext());
            if (!testCtx) {
                return ContextInfo();
            }

            // There is some bug (either in Skia or the NV Vulkan driver) where VkDevice
            // destruction will hang occaisonally. For some reason having an existing GL
            // context fixes this.
            if (!fSentinelGLContext) {
                fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
                if (!fSentinelGLContext) {
                    fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
                }
            }
            backendContext = testCtx->backendContext();
            break;
#endif
        default:
            return ContextInfo();
    }
    testCtx->makeCurrent();
    SkASSERT(testCtx && testCtx->backend() == backend);
    GrContextOptions grOptions = fGlobalOptions;
    if (kUseInstanced_ContextOptions & options) {
        grOptions.fEnableInstancedRendering = true;
    }
    grCtx.reset(GrContext::Create(backend, backendContext, grOptions));
    if (!grCtx.get()) {
        return ContextInfo();
    }
    if (kEnableNVPR_ContextOptions & options) {
        if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
            return ContextInfo();
        }
    }
    if (kUseInstanced_ContextOptions & options) {
        if (GrCaps::InstancedSupport::kNone == grCtx->caps()->instancedSupport()) {
            return ContextInfo();
        }
    }
    if (kRequireSRGBSupport_ContextOptions & options) {
        if (!grCtx->caps()->srgbSupport()) {
            return ContextInfo();
        }
    }

    Context& context = fContexts.push_back();
    context.fBackend = backend;
    context.fTestContext = testCtx.release();
    context.fGrContext = SkRef(grCtx.get());
    context.fType = type;
    context.fOptions = options;
    context.fAbandoned = false;
    return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
}
}  // namespace sk_gpu_test
