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 "include/gpu/GrContextOptions.h"
12 #include "include/gpu/GrDirectContext.h"
13 
14 #include "include/private/SkTArray.h"
15 #include "tools/gpu/gl/GLTestContext.h"
16 
17 struct GrVkBackendContext;
18 
19 namespace sk_gpu_test {
20 class ContextInfo;
21 
22 /**
23  * This is a simple class that is useful in test apps that use different
24  * GrContexts backed by different types of GL contexts. It manages creating the
25  * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
26  * factory is destroyed (though the caller can always grab a ref on the returned
27  * Gr and GL contexts to make them outlive the factory).
28  */
29 class GrContextFactory : SkNoncopyable {
30 public:
31     // The availability of context types is subject to platform and build configuration
32     // restrictions.
33     enum ContextType {
34         kGL_ContextType,             //! OpenGL context.
35         kGLES_ContextType,           //! OpenGL ES context.
36         kANGLE_D3D9_ES2_ContextType, //! ANGLE on Direct3D9 OpenGL ES 2 context.
37         kANGLE_D3D11_ES2_ContextType,//! ANGLE on Direct3D11 OpenGL ES 2 context.
38         kANGLE_D3D11_ES3_ContextType,//! ANGLE on Direct3D11 OpenGL ES 3 context.
39         kANGLE_GL_ES2_ContextType,   //! ANGLE on OpenGL OpenGL ES 2 context.
40         kANGLE_GL_ES3_ContextType,   //! ANGLE on OpenGL OpenGL ES 3 context.
41         kCommandBuffer_ContextType,  //! Chromium command buffer OpenGL ES context.
42         kVulkan_ContextType,         //! Vulkan
43         kMetal_ContextType,          //! Metal
44         kDirect3D_ContextType,       //! Direct3D 12
45         kDawn_ContextType,           //! Dawn
46         kMock_ContextType,           //! Mock context that does not draw.
47         kLastContextType = kMock_ContextType
48     };
49 
50     static const int kContextTypeCnt = kLastContextType + 1;
51 
52     /**
53      * Overrides for the initial GrContextOptions provided at construction time, and required
54      * features that will cause context creation to fail if not present.
55      */
56     enum class ContextOverrides {
57         kNone                          = 0x0,
58         kAvoidStencilBuffers           = 0x1,
59         kFakeGLESVersionAs2            = 0x2,
60         kReducedShaders                = 0x4,
61     };
62 
IsRenderingContext(ContextType type)63     static bool IsRenderingContext(ContextType type) {
64         switch (type) {
65             case kMock_ContextType:
66                 return false;
67             default:
68                 return true;
69         }
70     }
71 
ContextTypeBackend(ContextType type)72     static GrBackendApi ContextTypeBackend(ContextType type) {
73         switch (type) {
74             case kVulkan_ContextType:
75                 return GrBackendApi::kVulkan;
76             case kMetal_ContextType:
77                 return GrBackendApi::kMetal;
78             case kDirect3D_ContextType:
79                 return GrBackendApi::kDirect3D;
80             case kDawn_ContextType:
81                 return GrBackendApi::kDawn;
82             case kMock_ContextType:
83                 return GrBackendApi::kMock;
84             default:
85                 return GrBackendApi::kOpenGL;
86         }
87     }
88 
ContextTypeName(ContextType contextType)89     static const char* ContextTypeName(ContextType contextType) {
90         switch (contextType) {
91             case kGL_ContextType:
92                 return "OpenGL";
93             case kGLES_ContextType:
94                 return "OpenGLES";
95             case kANGLE_D3D9_ES2_ContextType:
96                 return "ANGLE D3D9 ES2";
97             case kANGLE_D3D11_ES2_ContextType:
98                 return "ANGLE D3D11 ES2";
99             case kANGLE_D3D11_ES3_ContextType:
100                 return "ANGLE D3D11 ES3";
101             case kANGLE_GL_ES2_ContextType:
102                 return "ANGLE GL ES2";
103             case kANGLE_GL_ES3_ContextType:
104                 return "ANGLE GL ES3";
105             case kCommandBuffer_ContextType:
106                 return "Command Buffer";
107             case kVulkan_ContextType:
108                 return "Vulkan";
109             case kMetal_ContextType:
110                 return "Metal";
111             case kDirect3D_ContextType:
112                 return "Direct3D";
113             case kDawn_ContextType:
114                 return "Dawn";
115             case kMock_ContextType:
116                 return "Mock";
117         }
118         SK_ABORT("Unreachable");
119     }
120 
121     explicit GrContextFactory(const GrContextOptions& opts);
122     GrContextFactory();
123 
124     ~GrContextFactory();
125 
126     void destroyContexts();
127     void abandonContexts();
128     void releaseResourcesAndAbandonContexts();
129 
130     /**
131      * Get a context initialized with a type of GL context. It also makes the GL context current.
132      */
133     ContextInfo getContextInfo(ContextType type, ContextOverrides = ContextOverrides::kNone);
134 
135     /**
136      * Get a context in the same share group as the passed in GrContext, with the same type and
137      * overrides. To get multiple contexts in a single share group, pass the same shareContext,
138      * with different values for shareIndex.
139      */
140     ContextInfo getSharedContextInfo(GrDirectContext* shareContext, uint32_t shareIndex = 0);
141 
142     /**
143      * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
144      */
145     GrDirectContext* get(ContextType type, ContextOverrides overrides = ContextOverrides::kNone);
getGlobalOptions()146     const GrContextOptions& getGlobalOptions() const { return fGlobalOptions; }
147 
148 private:
149     ContextInfo getContextInfoInternal(ContextType type, ContextOverrides overrides,
150                                        GrDirectContext* shareContext, uint32_t shareIndex);
151 
152     struct Context {
153         ContextType       fType;
154         ContextOverrides  fOverrides;
155         GrContextOptions  fOptions;
156         GrBackendApi      fBackend;
157         TestContext*      fTestContext;
158         GrDirectContext*  fGrContext;
159         GrDirectContext*  fShareContext;
160         uint32_t          fShareIndex;
161 
162         bool              fAbandoned;
163     };
164     SkTArray<Context, true>         fContexts;
165     std::unique_ptr<GLTestContext>  fSentinelGLContext;
166     const GrContextOptions          fGlobalOptions;
167 };
168 
169 class ContextInfo {
170 public:
171     ContextInfo() = default;
172     ContextInfo& operator=(const ContextInfo&) = default;
173 
type()174     GrContextFactory::ContextType type() const { return fType; }
backend()175     GrBackendApi backend() const { return GrContextFactory::ContextTypeBackend(fType); }
176 
directContext()177     GrDirectContext* directContext() const { return fContext; }
testContext()178     TestContext* testContext() const { return fTestContext; }
179 
180 #ifdef SK_GL
glContext()181     GLTestContext* glContext() const {
182         SkASSERT(GrBackendApi::kOpenGL == this->backend());
183         return static_cast<GLTestContext*>(fTestContext);
184     }
185 #endif
186 
options()187     const GrContextOptions& options() const { return fOptions; }
188 
189 private:
ContextInfo(GrContextFactory::ContextType type,TestContext * testContext,GrDirectContext * context,const GrContextOptions & options)190     ContextInfo(GrContextFactory::ContextType type,
191                 TestContext* testContext,
192                 GrDirectContext* context,
193                 const GrContextOptions& options)
194             : fType(type), fTestContext(testContext), fContext(context), fOptions(options) {}
195 
196     GrContextFactory::ContextType fType = GrContextFactory::kGL_ContextType;
197     // Valid until the factory destroys it via abandonContexts() or destroyContexts().
198     TestContext* fTestContext = nullptr;
199     GrDirectContext* fContext = nullptr;
200     GrContextOptions fOptions;
201 
202     friend class GrContextFactory;
203 };
204 
205 }  // namespace sk_gpu_test
206 
207 GR_MAKE_BITFIELD_CLASS_OPS(sk_gpu_test::GrContextFactory::ContextOverrides);
208 
209 #endif
210