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     explicit GrContextFactory(const GrContext::Options& opts) : fGlobalOptions(opts) { }
     92     GrContextFactory() { }
     93 
     94     ~GrContextFactory() { this->destroyContexts(); }
     95 
     96     void destroyContexts() {
     97         for (int i = 0; i < fContexts.count(); ++i) {
     98             if (fContexts[i].fGLContext) {  //  could be abandoned.
     99                 fContexts[i].fGLContext->makeCurrent();
    100             }
    101             fContexts[i].fGrContext->unref();
    102             if (fContexts[i].fGLContext) {
    103                 fContexts[i].fGLContext->unref();
    104             }
    105         }
    106         fContexts.reset();
    107     }
    108 
    109     void abandonContexts() {
    110         for (int i = 0; i < fContexts.count(); ++i) {
    111             if (fContexts[i].fGLContext) {
    112                 fContexts[i].fGLContext->testAbandon();
    113                 SkSafeSetNull(fContexts[i].fGLContext);
    114             }
    115             fContexts[i].fGrContext->abandonContext();
    116         }
    117     }
    118 
    119     /**
    120      * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
    121      */
    122     GrContext* get(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard) {
    123         for (int i = 0; i < fContexts.count(); ++i) {
    124             if (forcedGpuAPI != kNone_GrGLStandard &&
    125                 forcedGpuAPI != fContexts[i].fGLContext->gl()->fStandard)
    126                 continue;
    127 
    128             if (fContexts[i].fType == type) {
    129                 fContexts[i].fGLContext->makeCurrent();
    130                 return fContexts[i].fGrContext;
    131             }
    132         }
    133         SkAutoTUnref<SkGLContextHelper> glCtx;
    134         SkAutoTUnref<GrContext> grCtx;
    135         switch (type) {
    136             case kNVPR_GLContextType: // fallthru
    137             case kNative_GLContextType:
    138                 glCtx.reset(SkNEW(SkNativeGLContext));
    139                 break;
    140 #ifdef SK_ANGLE
    141             case kANGLE_GLContextType:
    142                 glCtx.reset(SkNEW(SkANGLEGLContext));
    143                 break;
    144 #endif
    145 #ifdef SK_MESA
    146             case kMESA_GLContextType:
    147                 glCtx.reset(SkNEW(SkMesaGLContext));
    148                 break;
    149 #endif
    150             case kNull_GLContextType:
    151                 glCtx.reset(SkNEW(SkNullGLContext));
    152                 break;
    153             case kDebug_GLContextType:
    154                 glCtx.reset(SkNEW(SkDebugGLContext));
    155                 break;
    156         }
    157         static const int kBogusSize = 1;
    158         if (!glCtx.get()) {
    159             return NULL;
    160         }
    161         if (!glCtx.get()->init(forcedGpuAPI, kBogusSize, kBogusSize)) {
    162             return NULL;
    163         }
    164 
    165         // Ensure NVPR is available for the NVPR type and block it from other types.
    166         SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx.get()->gl()));
    167         if (kNVPR_GLContextType == type) {
    168             if (!glInterface->hasExtension("GL_NV_path_rendering")) {
    169                 return NULL;
    170             }
    171         } else {
    172             glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface));
    173             if (!glInterface) {
    174                 return NULL;
    175             }
    176         }
    177 
    178         glCtx->makeCurrent();
    179         GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glInterface.get());
    180         grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx, &fGlobalOptions));
    181         if (!grCtx.get()) {
    182             return NULL;
    183         }
    184         GPUContext& ctx = fContexts.push_back();
    185         ctx.fGLContext = glCtx.get();
    186         ctx.fGLContext->ref();
    187         ctx.fGrContext = grCtx.get();
    188         ctx.fGrContext->ref();
    189         ctx.fType = type;
    190         return ctx.fGrContext;
    191     }
    192 
    193     // Returns the GLContext of the given type. If it has not been created yet,
    194     // NULL is returned instead.
    195     SkGLContextHelper* getGLContext(GLContextType type) {
    196         for (int i = 0; i < fContexts.count(); ++i) {
    197             if (fContexts[i].fType == type) {
    198                 return fContexts[i].fGLContext;
    199             }
    200         }
    201 
    202         return NULL;
    203     }
    204 
    205     const GrContext::Options& getGlobalOptions() const { return fGlobalOptions; }
    206 
    207 private:
    208     struct GPUContext {
    209         GLContextType             fType;
    210         SkGLContextHelper*        fGLContext;
    211         GrContext*                fGrContext;
    212     };
    213     SkTArray<GPUContext, true>    fContexts;
    214     const GrContext::Options      fGlobalOptions;
    215 };
    216 
    217 #endif
    218