michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrContextFactory_DEFINED michael@0: #define GrContextFactory_DEFINED michael@0: michael@0: #if SK_ANGLE michael@0: #include "gl/SkANGLEGLContext.h" michael@0: #endif michael@0: #include "gl/SkDebugGLContext.h" michael@0: #if SK_MESA michael@0: #include "gl/SkMesaGLContext.h" michael@0: #endif michael@0: #include "gl/SkNativeGLContext.h" michael@0: #include "gl/SkNullGLContext.h" michael@0: michael@0: #include "GrContext.h" michael@0: #include "SkTArray.h" michael@0: michael@0: /** michael@0: * This is a simple class that is useful in test apps that use different michael@0: * GrContexts backed by different types of GL contexts. It manages creating the michael@0: * GL context and a GrContext that uses it. The GL/Gr contexts persist until the michael@0: * factory is destroyed (though the caller can always grab a ref on the returned michael@0: * Gr and GL contexts to make them outlive the factory). michael@0: */ michael@0: class GrContextFactory : public SkNoncopyable { michael@0: public: michael@0: /** michael@0: * Types of GL contexts supported. For historical and testing reasons the native GrContext will michael@0: * not use "GL_NV_path_rendering" even when the driver supports it. There is a separate context michael@0: * type that does not remove NVPR support and which will fail when the driver does not support michael@0: * the extension. michael@0: */ michael@0: enum GLContextType { michael@0: kNative_GLContextType, michael@0: #if SK_ANGLE michael@0: kANGLE_GLContextType, michael@0: #endif michael@0: #if SK_MESA michael@0: kMESA_GLContextType, michael@0: #endif michael@0: /** Similar to kNative but does not filter NVPR. It will fail if the GL driver does not michael@0: support NVPR */ michael@0: kNVPR_GLContextType, michael@0: kNull_GLContextType, michael@0: kDebug_GLContextType, michael@0: michael@0: kLastGLContextType = kDebug_GLContextType michael@0: }; michael@0: michael@0: static const int kGLContextTypeCnt = kLastGLContextType + 1; michael@0: michael@0: static bool IsRenderingGLContext(GLContextType type) { michael@0: switch (type) { michael@0: case kNull_GLContextType: michael@0: case kDebug_GLContextType: michael@0: return false; michael@0: default: michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: static const char* GLContextTypeName(GLContextType type) { michael@0: switch (type) { michael@0: case kNative_GLContextType: michael@0: return "native"; michael@0: case kNull_GLContextType: michael@0: return "null"; michael@0: #if SK_ANGLE michael@0: case kANGLE_GLContextType: michael@0: return "angle"; michael@0: #endif michael@0: #if SK_MESA michael@0: case kMESA_GLContextType: michael@0: return "mesa"; michael@0: #endif michael@0: case kNVPR_GLContextType: michael@0: return "nvpr"; michael@0: case kDebug_GLContextType: michael@0: return "debug"; michael@0: default: michael@0: GrCrash("Unknown GL Context type."); michael@0: } michael@0: } michael@0: michael@0: GrContextFactory() { michael@0: } michael@0: michael@0: ~GrContextFactory() { this->destroyContexts(); } michael@0: michael@0: void destroyContexts() { michael@0: for (int i = 0; i < fContexts.count(); ++i) { michael@0: fContexts[i].fGLContext->makeCurrent(); michael@0: fContexts[i].fGrContext->unref(); michael@0: fContexts[i].fGLContext->unref(); michael@0: } michael@0: fContexts.reset(); michael@0: } michael@0: michael@0: /** michael@0: * Get a GrContext initialized with a type of GL context. It also makes the GL context current. michael@0: */ michael@0: GrContext* get(GLContextType type) { michael@0: michael@0: for (int i = 0; i < fContexts.count(); ++i) { michael@0: if (fContexts[i].fType == type) { michael@0: fContexts[i].fGLContext->makeCurrent(); michael@0: return fContexts[i].fGrContext; michael@0: } michael@0: } michael@0: SkAutoTUnref glCtx; michael@0: SkAutoTUnref grCtx; michael@0: switch (type) { michael@0: case kNVPR_GLContextType: // fallthru michael@0: case kNative_GLContextType: michael@0: glCtx.reset(SkNEW(SkNativeGLContext)); michael@0: break; michael@0: #ifdef SK_ANGLE michael@0: case kANGLE_GLContextType: michael@0: glCtx.reset(SkNEW(SkANGLEGLContext)); michael@0: break; michael@0: #endif michael@0: #ifdef SK_MESA michael@0: case kMESA_GLContextType: michael@0: glCtx.reset(SkNEW(SkMesaGLContext)); michael@0: break; michael@0: #endif michael@0: case kNull_GLContextType: michael@0: glCtx.reset(SkNEW(SkNullGLContext)); michael@0: break; michael@0: case kDebug_GLContextType: michael@0: glCtx.reset(SkNEW(SkDebugGLContext)); michael@0: break; michael@0: } michael@0: static const int kBogusSize = 1; michael@0: if (!glCtx.get()) { michael@0: return NULL; michael@0: } michael@0: if (!glCtx.get()->init(kBogusSize, kBogusSize)) { michael@0: return NULL; michael@0: } michael@0: michael@0: // Ensure NVPR is available for the NVPR type and block it from other types. michael@0: SkAutoTUnref glInterface(SkRef(glCtx.get()->gl())); michael@0: if (kNVPR_GLContextType == type) { michael@0: if (!glInterface->hasExtension("GL_NV_path_rendering")) { michael@0: return NULL; michael@0: } michael@0: } else { michael@0: glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface)); michael@0: if (!glInterface) { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: glCtx->makeCurrent(); michael@0: GrBackendContext p3dctx = reinterpret_cast(glInterface.get()); michael@0: grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx)); michael@0: if (!grCtx.get()) { michael@0: return NULL; michael@0: } michael@0: GPUContext& ctx = fContexts.push_back(); michael@0: ctx.fGLContext = glCtx.get(); michael@0: ctx.fGLContext->ref(); michael@0: ctx.fGrContext = grCtx.get(); michael@0: ctx.fGrContext->ref(); michael@0: ctx.fType = type; michael@0: return ctx.fGrContext; michael@0: } michael@0: michael@0: // Returns the GLContext of the given type. If it has not been created yet, michael@0: // NULL is returned instead. michael@0: SkGLContextHelper* getGLContext(GLContextType type) { michael@0: for (int i = 0; i < fContexts.count(); ++i) { michael@0: if (fContexts[i].fType == type) { michael@0: return fContexts[i].fGLContext; michael@0: } michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: michael@0: private: michael@0: struct GPUContext { michael@0: GLContextType fType; michael@0: SkGLContextHelper* fGLContext; michael@0: GrContext* fGrContext; michael@0: }; michael@0: SkTArray fContexts; michael@0: }; michael@0: michael@0: #endif