Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrContextFactory_DEFINED
      9 #define GrContextFactory_DEFINED
     10 
     11 #if SK_ANGLE
     12     #include "gl/SkANGLEGLContext.h"
     13 #endif
     14 #include "gl/SkDebugGLContext.h"
     15 #if SK_MESA
     16     #include "gl/SkMesaGLContext.h"
     17 #endif
     18 #include "gl/SkNativeGLContext.h"
     19 #include "gl/SkNullGLContext.h"
     20 
     21 #include "GrContext.h"
     22 #include "SkTArray.h"
     23 
     24 /**
     25  * This is a simple class that is useful in test apps that use different
     26  * GrContexts backed by different types of GL contexts. It manages creating the
     27  * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
     28  * factory is destroyed (though the caller can always grab a ref on the returned
     29  * Gr and GL contexts to make them outlive the factory).
     30  */
     31 class GrContextFactory : SkNoncopyable {
     32 public:
     33     /**
     34      * Types of GL contexts supported. For historical and testing reasons the native GrContext will
     35      * not use "GL_NV_path_rendering" even when the driver supports it. There is a separate context
     36      * type that does not remove NVPR support and which will fail when the driver does not support
     37      * the extension.
     38      */
     39     enum GLContextType {
     40       kNative_GLContextType,
     41 #if SK_ANGLE
     42       kANGLE_GLContextType,
     43 #endif
     44 #if SK_MESA
     45       kMESA_GLContextType,
     46 #endif
     47       /** Similar to kNative but does not filter NVPR. It will fail if the GL driver does not
     48           support NVPR */
     49       kNVPR_GLContextType,
     50       kNull_GLContextType,
     51       kDebug_GLContextType,
     52 
     53       kLastGLContextType = kDebug_GLContextType
     54     };
     55 
     56     static const int kGLContextTypeCnt = kLastGLContextType + 1;
     57 
     58     static bool IsRenderingGLContext(GLContextType type) {
     59         switch (type) {
     60             case kNull_GLContextType:
     61             case kDebug_GLContextType:
     62                 return false;
     63             default:
     64                 return true;
     65         }
     66     }
     67 
     68     static const char* GLContextTypeName(GLContextType type) {
     69         switch (type) {
     70             case kNative_GLContextType:
     71                 return "native";
     72             case kNull_GLContextType:
     73                 return "null";
     74 #if SK_ANGLE
     75             case kANGLE_GLContextType:
     76                 return "angle";
     77 #endif
     78 #if SK_MESA
     79             case kMESA_GLContextType:
     80                 return "mesa";
     81 #endif
     82             case kNVPR_GLContextType:
     83                 return "nvpr";
     84             case kDebug_GLContextType:
     85                 return "debug";
     86             default:
     87                 SkFAIL("Unknown GL Context type.");
     88         }
     89     }
     90 
     91     GrContextFactory() {
     92     }
     93 
     94     ~GrContextFactory() { this->destroyContexts(); }
     95 
     96     void destroyContexts() {
     97         for (int i = 0; i < fContexts.count(); ++i) {
     98             fContexts[i].fGLContext->makeCurrent();
     99             fContexts[i].fGrContext->unref();
    100             fContexts[i].fGLContext->unref();
    101         }
    102         fContexts.reset();
    103     }
    104 
    105     /**
    106      * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
    107      */
    108     GrContext* get(GLContextType type) {
    109 
    110         for (int i = 0; i < fContexts.count(); ++i) {
    111             if (fContexts[i].fType == type) {
    112                 fContexts[i].fGLContext->makeCurrent();
    113                 return fContexts[i].fGrContext;
    114             }
    115         }
    116         SkAutoTUnref<SkGLContextHelper> glCtx;
    117         SkAutoTUnref<GrContext> grCtx;
    118         switch (type) {
    119             case kNVPR_GLContextType: // fallthru
    120             case kNative_GLContextType:
    121                 glCtx.reset(SkNEW(SkNativeGLContext));
    122                 break;
    123 #ifdef SK_ANGLE
    124             case kANGLE_GLContextType:
    125                 glCtx.reset(SkNEW(SkANGLEGLContext));
    126                 break;
    127 #endif
    128 #ifdef SK_MESA
    129             case kMESA_GLContextType:
    130                 glCtx.reset(SkNEW(SkMesaGLContext));
    131                 break;
    132 #endif
    133             case kNull_GLContextType:
    134                 glCtx.reset(SkNEW(SkNullGLContext));
    135                 break;
    136             case kDebug_GLContextType:
    137                 glCtx.reset(SkNEW(SkDebugGLContext));
    138                 break;
    139         }
    140         static const int kBogusSize = 1;
    141         if (!glCtx.get()) {
    142             return NULL;
    143         }
    144         if (!glCtx.get()->init(kBogusSize, kBogusSize)) {
    145             return NULL;
    146         }
    147 
    148         // Ensure NVPR is available for the NVPR type and block it from other types.
    149         SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx.get()->gl()));
    150         if (kNVPR_GLContextType == type) {
    151             if (!glInterface->hasExtension("GL_NV_path_rendering")) {
    152                 return NULL;
    153             }
    154         } else {
    155             glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface));
    156             if (!glInterface) {
    157                 return NULL;
    158             }
    159         }
    160 
    161         glCtx->makeCurrent();
    162         GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glInterface.get());
    163         grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx));
    164         if (!grCtx.get()) {
    165             return NULL;
    166         }
    167         GPUContext& ctx = fContexts.push_back();
    168         ctx.fGLContext = glCtx.get();
    169         ctx.fGLContext->ref();
    170         ctx.fGrContext = grCtx.get();
    171         ctx.fGrContext->ref();
    172         ctx.fType = type;
    173         return ctx.fGrContext;
    174     }
    175 
    176     // Returns the GLContext of the given type. If it has not been created yet,
    177     // NULL is returned instead.
    178     SkGLContextHelper* getGLContext(GLContextType type) {
    179         for (int i = 0; i < fContexts.count(); ++i) {
    180             if (fContexts[i].fType == type) {
    181                 return fContexts[i].fGLContext;
    182             }
    183         }
    184 
    185         return NULL;
    186     }
    187 
    188 private:
    189     struct GPUContext {
    190         GLContextType             fType;
    191         SkGLContextHelper*        fGLContext;
    192         GrContext*                fGrContext;
    193     };
    194     SkTArray<GPUContext, true> fContexts;
    195 };
    196 
    197 #endif
    198