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#include "GrContext.h"
12
13#include "gl/SkGLContext.h"
14#include "SkTArray.h"
15
16/**
17 * This is a simple class that is useful in test apps that use different
18 * GrContexts backed by different types of GL contexts. It manages creating the
19 * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
20 * factory is destroyed (though the caller can always grab a ref on the returned
21 * Gr and GL contexts to make them outlive the factory).
22 */
23class GrContextFactory : SkNoncopyable {
24public:
25    /**
26     * Types of GL contexts supported. For historical and testing reasons the native GrContext will
27     * not use "GL_NV_path_rendering" even when the driver supports it. There is a separate context
28     * type that does not remove NVPR support and which will fail when the driver does not support
29     * the extension.
30     */
31    enum GLContextType {
32      kNative_GLContextType,
33#if SK_ANGLE
34      kANGLE_GLContextType,
35#endif
36#if SK_MESA
37      kMESA_GLContextType,
38#endif
39      /** Similar to kNative but does not filter NVPR. It will fail if the GL driver does not
40          support NVPR */
41      kNVPR_GLContextType,
42      kNull_GLContextType,
43      kDebug_GLContextType,
44
45      kLastGLContextType = kDebug_GLContextType
46    };
47
48    static const int kGLContextTypeCnt = kLastGLContextType + 1;
49
50    static bool IsRenderingGLContext(GLContextType type) {
51        switch (type) {
52            case kNull_GLContextType:
53            case kDebug_GLContextType:
54                return false;
55            default:
56                return true;
57        }
58    }
59
60    static const char* GLContextTypeName(GLContextType type) {
61        switch (type) {
62            case kNative_GLContextType:
63                return "native";
64            case kNull_GLContextType:
65                return "null";
66#if SK_ANGLE
67            case kANGLE_GLContextType:
68                return "angle";
69#endif
70#if SK_MESA
71            case kMESA_GLContextType:
72                return "mesa";
73#endif
74            case kNVPR_GLContextType:
75                return "nvpr";
76            case kDebug_GLContextType:
77                return "debug";
78            default:
79                SkFAIL("Unknown GL Context type.");
80        }
81    }
82
83    explicit GrContextFactory(const GrContext::Options& opts) : fGlobalOptions(opts) { }
84    GrContextFactory() { }
85
86    ~GrContextFactory() { this->destroyContexts(); }
87
88    void destroyContexts() {
89        for (int i = 0; i < fContexts.count(); ++i) {
90            if (fContexts[i].fGLContext) {  //  could be abandoned.
91                fContexts[i].fGLContext->makeCurrent();
92            }
93            fContexts[i].fGrContext->unref();
94            if (fContexts[i].fGLContext) {
95                fContexts[i].fGLContext->unref();
96            }
97        }
98        fContexts.reset();
99    }
100
101    void abandonContexts() {
102        for (int i = 0; i < fContexts.count(); ++i) {
103            if (fContexts[i].fGLContext) {
104                fContexts[i].fGLContext->testAbandon();
105                SkSafeSetNull(fContexts[i].fGLContext);
106            }
107            fContexts[i].fGrContext->abandonContext();
108        }
109    }
110
111    /**
112     * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
113     */
114    GrContext* get(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard);
115
116
117    // Returns the GLContext of the given type. If it has not been created yet,
118    // NULL is returned instead.
119    SkGLContext* getGLContext(GLContextType type) {
120        for (int i = 0; i < fContexts.count(); ++i) {
121            if (fContexts[i].fType == type) {
122                return fContexts[i].fGLContext;
123            }
124        }
125
126        return NULL;
127    }
128
129    const GrContext::Options& getGlobalOptions() const { return fGlobalOptions; }
130
131private:
132    struct GPUContext {
133        GLContextType             fType;
134        SkGLContext*              fGLContext;
135        GrContext*                fGrContext;
136    };
137    SkTArray<GPUContext, true>    fContexts;
138    const GrContext::Options      fGlobalOptions;
139};
140
141#endif
142