1cb93a386Sopenharmony_ci
2cb93a386Sopenharmony_ci/*
3cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
4cb93a386Sopenharmony_ci *
5cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
6cb93a386Sopenharmony_ci * found in the LICENSE file.
7cb93a386Sopenharmony_ci */
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
10cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
11cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h"
12cb93a386Sopenharmony_ci#ifdef SK_GL
13cb93a386Sopenharmony_ci#include "tools/gpu/gl/GLTestContext.h"
14cb93a386Sopenharmony_ci#endif
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ci#if SK_ANGLE
17cb93a386Sopenharmony_ci#include "tools/gpu/gl/angle/GLTestContext_angle.h"
18cb93a386Sopenharmony_ci#endif
19cb93a386Sopenharmony_ci#include "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h"
20cb93a386Sopenharmony_ci#ifdef SK_VULKAN
21cb93a386Sopenharmony_ci#include "tools/gpu/vk/VkTestContext.h"
22cb93a386Sopenharmony_ci#endif
23cb93a386Sopenharmony_ci#ifdef SK_METAL
24cb93a386Sopenharmony_ci#include "tools/gpu/mtl/MtlTestContext.h"
25cb93a386Sopenharmony_ci#endif
26cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D
27cb93a386Sopenharmony_ci#include "tools/gpu/d3d/D3DTestContext.h"
28cb93a386Sopenharmony_ci#endif
29cb93a386Sopenharmony_ci#ifdef SK_DAWN
30cb93a386Sopenharmony_ci#include "tools/gpu/dawn/DawnTestContext.h"
31cb93a386Sopenharmony_ci#endif
32cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
33cb93a386Sopenharmony_ci#include "tools/gpu/mock/MockTestContext.h"
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_WIN) && defined(SK_ENABLE_DISCRETE_GPU)
36cb93a386Sopenharmony_ciextern "C" {
37cb93a386Sopenharmony_ci    // NVIDIA documents that the presence and value of this symbol programmatically enable the high
38cb93a386Sopenharmony_ci    // performance GPU in laptops with switchable graphics.
39cb93a386Sopenharmony_ci    //   https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
40cb93a386Sopenharmony_ci    // From testing, including this symbol, even if it is set to 0, we still get the NVIDIA GPU.
41cb93a386Sopenharmony_ci    // _declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci    // AMD has a similar mechanism, although I don't have an AMD laptop, so this is untested.
44cb93a386Sopenharmony_ci    //   https://community.amd.com/thread/169965
45cb93a386Sopenharmony_ci    // __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci#endif
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_cinamespace sk_gpu_test {
50cb93a386Sopenharmony_ciGrContextFactory::GrContextFactory() { }
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ciGrContextFactory::GrContextFactory(const GrContextOptions& opts)
53cb93a386Sopenharmony_ci    : fGlobalOptions(opts) {
54cb93a386Sopenharmony_ci}
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ciGrContextFactory::~GrContextFactory() {
57cb93a386Sopenharmony_ci    this->destroyContexts();
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_civoid GrContextFactory::destroyContexts() {
61cb93a386Sopenharmony_ci    // We must delete the test contexts in reverse order so that any child context is finished and
62cb93a386Sopenharmony_ci    // deleted before a parent context. This relies on the fact that when we make a new context we
63cb93a386Sopenharmony_ci    // append it to the end of fContexts array.
64cb93a386Sopenharmony_ci    // TODO: Look into keeping a dependency dag for contexts and deletion order
65cb93a386Sopenharmony_ci    for (int i = fContexts.count() - 1; i >= 0; --i) {
66cb93a386Sopenharmony_ci        Context& context = fContexts[i];
67cb93a386Sopenharmony_ci        SkScopeExit restore(nullptr);
68cb93a386Sopenharmony_ci        if (context.fTestContext) {
69cb93a386Sopenharmony_ci            restore = context.fTestContext->makeCurrentAndAutoRestore();
70cb93a386Sopenharmony_ci        }
71cb93a386Sopenharmony_ci        if (!context.fGrContext->unique()) {
72cb93a386Sopenharmony_ci            context.fGrContext->releaseResourcesAndAbandonContext();
73cb93a386Sopenharmony_ci            context.fAbandoned = true;
74cb93a386Sopenharmony_ci        }
75cb93a386Sopenharmony_ci        context.fGrContext->unref();
76cb93a386Sopenharmony_ci        delete context.fTestContext;
77cb93a386Sopenharmony_ci    }
78cb93a386Sopenharmony_ci    fContexts.reset();
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_civoid GrContextFactory::abandonContexts() {
82cb93a386Sopenharmony_ci    // We must abandon the test contexts in reverse order so that any child context is finished and
83cb93a386Sopenharmony_ci    // abandoned before a parent context. This relies on the fact that when we make a new context we
84cb93a386Sopenharmony_ci    // append it to the end of fContexts array.
85cb93a386Sopenharmony_ci    // TODO: Look into keeping a dependency dag for contexts and deletion order
86cb93a386Sopenharmony_ci    for (int i = fContexts.count() - 1; i >= 0; --i) {
87cb93a386Sopenharmony_ci        Context& context = fContexts[i];
88cb93a386Sopenharmony_ci        if (!context.fAbandoned) {
89cb93a386Sopenharmony_ci            if (context.fTestContext) {
90cb93a386Sopenharmony_ci                auto restore = context.fTestContext->makeCurrentAndAutoRestore();
91cb93a386Sopenharmony_ci                context.fTestContext->testAbandon();
92cb93a386Sopenharmony_ci            }
93cb93a386Sopenharmony_ci            GrBackendApi api = context.fGrContext->backend();
94cb93a386Sopenharmony_ci            bool requiresEarlyAbandon = api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn;
95cb93a386Sopenharmony_ci            if (requiresEarlyAbandon) {
96cb93a386Sopenharmony_ci                context.fGrContext->abandonContext();
97cb93a386Sopenharmony_ci            }
98cb93a386Sopenharmony_ci            if (context.fTestContext) {
99cb93a386Sopenharmony_ci                delete(context.fTestContext);
100cb93a386Sopenharmony_ci                context.fTestContext = nullptr;
101cb93a386Sopenharmony_ci            }
102cb93a386Sopenharmony_ci            if (!requiresEarlyAbandon) {
103cb93a386Sopenharmony_ci                context.fGrContext->abandonContext();
104cb93a386Sopenharmony_ci            }
105cb93a386Sopenharmony_ci            context.fAbandoned = true;
106cb93a386Sopenharmony_ci        }
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_civoid GrContextFactory::releaseResourcesAndAbandonContexts() {
111cb93a386Sopenharmony_ci    // We must abandon the test contexts in reverse order so that any child context is finished and
112cb93a386Sopenharmony_ci    // abandoned before a parent context. This relies on the fact that when we make a new context we
113cb93a386Sopenharmony_ci    // append it to the end of fContexts array.
114cb93a386Sopenharmony_ci    // TODO: Look into keeping a dependency dag for contexts and deletion order
115cb93a386Sopenharmony_ci    for (int i = fContexts.count() - 1; i >= 0; --i) {
116cb93a386Sopenharmony_ci        Context& context = fContexts[i];
117cb93a386Sopenharmony_ci        SkScopeExit restore(nullptr);
118cb93a386Sopenharmony_ci        if (!context.fAbandoned) {
119cb93a386Sopenharmony_ci            if (context.fTestContext) {
120cb93a386Sopenharmony_ci                restore = context.fTestContext->makeCurrentAndAutoRestore();
121cb93a386Sopenharmony_ci            }
122cb93a386Sopenharmony_ci            context.fGrContext->releaseResourcesAndAbandonContext();
123cb93a386Sopenharmony_ci            if (context.fTestContext) {
124cb93a386Sopenharmony_ci                delete context.fTestContext;
125cb93a386Sopenharmony_ci                context.fTestContext = nullptr;
126cb93a386Sopenharmony_ci            }
127cb93a386Sopenharmony_ci            context.fAbandoned = true;
128cb93a386Sopenharmony_ci        }
129cb93a386Sopenharmony_ci    }
130cb93a386Sopenharmony_ci}
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ciGrDirectContext* GrContextFactory::get(ContextType type, ContextOverrides overrides) {
133cb93a386Sopenharmony_ci    return this->getContextInfo(type, overrides).directContext();
134cb93a386Sopenharmony_ci}
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ciContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOverrides overrides,
137cb93a386Sopenharmony_ci                                                     GrDirectContext* shareContext,
138cb93a386Sopenharmony_ci                                                     uint32_t shareIndex) {
139cb93a386Sopenharmony_ci    // (shareIndex != 0) -> (shareContext != nullptr)
140cb93a386Sopenharmony_ci    SkASSERT((shareIndex == 0) || (shareContext != nullptr));
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    for (int i = 0; i < fContexts.count(); ++i) {
143cb93a386Sopenharmony_ci        Context& context = fContexts[i];
144cb93a386Sopenharmony_ci        if (context.fType == type &&
145cb93a386Sopenharmony_ci            context.fOverrides == overrides &&
146cb93a386Sopenharmony_ci            context.fShareContext == shareContext &&
147cb93a386Sopenharmony_ci            context.fShareIndex == shareIndex &&
148cb93a386Sopenharmony_ci            !context.fAbandoned) {
149cb93a386Sopenharmony_ci            context.fTestContext->makeCurrent();
150cb93a386Sopenharmony_ci            return ContextInfo(context.fType, context.fTestContext, context.fGrContext,
151cb93a386Sopenharmony_ci                               context.fOptions);
152cb93a386Sopenharmony_ci        }
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    // If we're trying to create a context in a share group, find the primary context
156cb93a386Sopenharmony_ci    Context* primaryContext = nullptr;
157cb93a386Sopenharmony_ci    if (shareContext) {
158cb93a386Sopenharmony_ci        for (int i = 0; i < fContexts.count(); ++i) {
159cb93a386Sopenharmony_ci            if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
160cb93a386Sopenharmony_ci                primaryContext = &fContexts[i];
161cb93a386Sopenharmony_ci                break;
162cb93a386Sopenharmony_ci            }
163cb93a386Sopenharmony_ci        }
164cb93a386Sopenharmony_ci        SkASSERT(primaryContext && primaryContext->fType == type);
165cb93a386Sopenharmony_ci    }
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci    std::unique_ptr<TestContext> testCtx;
168cb93a386Sopenharmony_ci    GrBackendApi backend = ContextTypeBackend(type);
169cb93a386Sopenharmony_ci    switch (backend) {
170cb93a386Sopenharmony_ci#ifdef SK_GL
171cb93a386Sopenharmony_ci        case GrBackendApi::kOpenGL: {
172cb93a386Sopenharmony_ci            GLTestContext* glShareContext = primaryContext
173cb93a386Sopenharmony_ci                    ? static_cast<GLTestContext*>(primaryContext->fTestContext) : nullptr;
174cb93a386Sopenharmony_ci            GLTestContext* glCtx;
175cb93a386Sopenharmony_ci            switch (type) {
176cb93a386Sopenharmony_ci                case kGL_ContextType:
177cb93a386Sopenharmony_ci                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard, glShareContext);
178cb93a386Sopenharmony_ci                    break;
179cb93a386Sopenharmony_ci                case kGLES_ContextType:
180cb93a386Sopenharmony_ci                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard, glShareContext);
181cb93a386Sopenharmony_ci                    break;
182cb93a386Sopenharmony_ci#if SK_ANGLE
183cb93a386Sopenharmony_ci                case kANGLE_D3D9_ES2_ContextType:
184cb93a386Sopenharmony_ci                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2,
185cb93a386Sopenharmony_ci                                                 glShareContext).release();
186cb93a386Sopenharmony_ci                    // Chrome will only run on D3D9 with NVIDIA for 2012 and earlier drivers.
187cb93a386Sopenharmony_ci                    // (<= 269.73). We get shader link failures when testing on recent drivers
188cb93a386Sopenharmony_ci                    // using this backend.
189cb93a386Sopenharmony_ci                    if (glCtx) {
190cb93a386Sopenharmony_ci                        GrGLDriverInfo info = GrGLGetDriverInfo(glCtx->gl());
191cb93a386Sopenharmony_ci                        if (info.fANGLEVendor == GrGLVendor::kNVIDIA) {
192cb93a386Sopenharmony_ci                            delete glCtx;
193cb93a386Sopenharmony_ci                            return ContextInfo();
194cb93a386Sopenharmony_ci                        }
195cb93a386Sopenharmony_ci                    }
196cb93a386Sopenharmony_ci                    break;
197cb93a386Sopenharmony_ci                case kANGLE_D3D11_ES2_ContextType:
198cb93a386Sopenharmony_ci                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES2,
199cb93a386Sopenharmony_ci                                                 glShareContext).release();
200cb93a386Sopenharmony_ci                    break;
201cb93a386Sopenharmony_ci                case kANGLE_D3D11_ES3_ContextType:
202cb93a386Sopenharmony_ci                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES3,
203cb93a386Sopenharmony_ci                                                 glShareContext).release();
204cb93a386Sopenharmony_ci                    break;
205cb93a386Sopenharmony_ci                case kANGLE_GL_ES2_ContextType:
206cb93a386Sopenharmony_ci                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES2,
207cb93a386Sopenharmony_ci                                                 glShareContext).release();
208cb93a386Sopenharmony_ci                    break;
209cb93a386Sopenharmony_ci                case kANGLE_GL_ES3_ContextType:
210cb93a386Sopenharmony_ci                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3,
211cb93a386Sopenharmony_ci                                                 glShareContext).release();
212cb93a386Sopenharmony_ci                    break;
213cb93a386Sopenharmony_ci#endif
214cb93a386Sopenharmony_ci#ifndef SK_NO_COMMAND_BUFFER
215cb93a386Sopenharmony_ci                case kCommandBuffer_ES2_ContextType:
216cb93a386Sopenharmony_ci                    glCtx = CommandBufferGLTestContext::Create(2, glShareContext);
217cb93a386Sopenharmony_ci                    break;
218cb93a386Sopenharmony_ci                case kCommandBuffer_ES3_ContextType:
219cb93a386Sopenharmony_ci                    glCtx = CommandBufferGLTestContext::Create(3, glShareContext);
220cb93a386Sopenharmony_ci                    break;
221cb93a386Sopenharmony_ci#endif
222cb93a386Sopenharmony_ci                default:
223cb93a386Sopenharmony_ci                    return ContextInfo();
224cb93a386Sopenharmony_ci            }
225cb93a386Sopenharmony_ci            if (!glCtx) {
226cb93a386Sopenharmony_ci                return ContextInfo();
227cb93a386Sopenharmony_ci            }
228cb93a386Sopenharmony_ci            if (glCtx->gl()->fStandard == kGLES_GrGLStandard &&
229cb93a386Sopenharmony_ci                (overrides & ContextOverrides::kFakeGLESVersionAs2)) {
230cb93a386Sopenharmony_ci                glCtx->overrideVersion("OpenGL ES 2.0", "OpenGL ES GLSL ES 1.00");
231cb93a386Sopenharmony_ci            }
232cb93a386Sopenharmony_ci            testCtx.reset(glCtx);
233cb93a386Sopenharmony_ci            break;
234cb93a386Sopenharmony_ci        }
235cb93a386Sopenharmony_ci#endif  // SK_GL
236cb93a386Sopenharmony_ci#ifdef SK_VULKAN
237cb93a386Sopenharmony_ci        case GrBackendApi::kVulkan: {
238cb93a386Sopenharmony_ci            VkTestContext* vkSharedContext = primaryContext
239cb93a386Sopenharmony_ci                    ? static_cast<VkTestContext*>(primaryContext->fTestContext) : nullptr;
240cb93a386Sopenharmony_ci            SkASSERT(kVulkan_ContextType == type);
241cb93a386Sopenharmony_ci            testCtx.reset(CreatePlatformVkTestContext(vkSharedContext));
242cb93a386Sopenharmony_ci            if (!testCtx) {
243cb93a386Sopenharmony_ci                return ContextInfo();
244cb93a386Sopenharmony_ci            }
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_ci            // We previously had an issue where the VkDevice destruction would occasionally hang
247cb93a386Sopenharmony_ci            // on systems with NVIDIA GPUs and having an existing GL context fixed it. Now (March
248cb93a386Sopenharmony_ci            // 2020) we still need the GL context to keep Vulkan/TSAN bots from running incredibly
249cb93a386Sopenharmony_ci            // slow. Perhaps this prevents repeated driver loading/unloading? Note that keeping
250cb93a386Sopenharmony_ci            // a persistent VkTestContext around instead was tried and did not work.
251cb93a386Sopenharmony_ci            if (!fSentinelGLContext) {
252cb93a386Sopenharmony_ci                fSentinelGLContext.reset(CreatePlatformGLTestContext(kGL_GrGLStandard));
253cb93a386Sopenharmony_ci                if (!fSentinelGLContext) {
254cb93a386Sopenharmony_ci                    fSentinelGLContext.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
255cb93a386Sopenharmony_ci                }
256cb93a386Sopenharmony_ci            }
257cb93a386Sopenharmony_ci            break;
258cb93a386Sopenharmony_ci        }
259cb93a386Sopenharmony_ci#endif
260cb93a386Sopenharmony_ci#ifdef SK_METAL
261cb93a386Sopenharmony_ci        case GrBackendApi::kMetal: {
262cb93a386Sopenharmony_ci            MtlTestContext* mtlSharedContext = primaryContext
263cb93a386Sopenharmony_ci                    ? static_cast<MtlTestContext*>(primaryContext->fTestContext) : nullptr;
264cb93a386Sopenharmony_ci            SkASSERT(kMetal_ContextType == type);
265cb93a386Sopenharmony_ci            testCtx.reset(CreatePlatformMtlTestContext(mtlSharedContext));
266cb93a386Sopenharmony_ci            if (!testCtx) {
267cb93a386Sopenharmony_ci                return ContextInfo();
268cb93a386Sopenharmony_ci            }
269cb93a386Sopenharmony_ci            break;
270cb93a386Sopenharmony_ci        }
271cb93a386Sopenharmony_ci#endif
272cb93a386Sopenharmony_ci#ifdef SK_DIRECT3D
273cb93a386Sopenharmony_ci        case GrBackendApi::kDirect3D: {
274cb93a386Sopenharmony_ci            D3DTestContext* d3dSharedContext = primaryContext
275cb93a386Sopenharmony_ci                    ? static_cast<D3DTestContext*>(primaryContext->fTestContext) : nullptr;
276cb93a386Sopenharmony_ci            SkASSERT(kDirect3D_ContextType == type);
277cb93a386Sopenharmony_ci            testCtx.reset(CreatePlatformD3DTestContext(d3dSharedContext));
278cb93a386Sopenharmony_ci            if (!testCtx) {
279cb93a386Sopenharmony_ci                return ContextInfo();
280cb93a386Sopenharmony_ci            }
281cb93a386Sopenharmony_ci            break;
282cb93a386Sopenharmony_ci        }
283cb93a386Sopenharmony_ci#endif
284cb93a386Sopenharmony_ci#ifdef SK_DAWN
285cb93a386Sopenharmony_ci        case GrBackendApi::kDawn: {
286cb93a386Sopenharmony_ci            DawnTestContext* dawnSharedContext = primaryContext
287cb93a386Sopenharmony_ci                    ? static_cast<DawnTestContext*>(primaryContext->fTestContext) : nullptr;
288cb93a386Sopenharmony_ci            testCtx.reset(CreatePlatformDawnTestContext(dawnSharedContext));
289cb93a386Sopenharmony_ci            if (!testCtx) {
290cb93a386Sopenharmony_ci                return ContextInfo();
291cb93a386Sopenharmony_ci            }
292cb93a386Sopenharmony_ci            break;
293cb93a386Sopenharmony_ci        }
294cb93a386Sopenharmony_ci#endif
295cb93a386Sopenharmony_ci        case GrBackendApi::kMock: {
296cb93a386Sopenharmony_ci            TestContext* sharedContext = primaryContext ? primaryContext->fTestContext : nullptr;
297cb93a386Sopenharmony_ci            SkASSERT(kMock_ContextType == type);
298cb93a386Sopenharmony_ci            testCtx.reset(CreateMockTestContext(sharedContext));
299cb93a386Sopenharmony_ci            if (!testCtx) {
300cb93a386Sopenharmony_ci                return ContextInfo();
301cb93a386Sopenharmony_ci            }
302cb93a386Sopenharmony_ci            break;
303cb93a386Sopenharmony_ci        }
304cb93a386Sopenharmony_ci        default:
305cb93a386Sopenharmony_ci            return ContextInfo();
306cb93a386Sopenharmony_ci    }
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_ci    SkASSERT(testCtx && testCtx->backend() == backend);
309cb93a386Sopenharmony_ci    GrContextOptions grOptions = fGlobalOptions;
310cb93a386Sopenharmony_ci    if (ContextOverrides::kAvoidStencilBuffers & overrides) {
311cb93a386Sopenharmony_ci        grOptions.fAvoidStencilBuffers = true;
312cb93a386Sopenharmony_ci    }
313cb93a386Sopenharmony_ci    if (ContextOverrides::kReducedShaders & overrides) {
314cb93a386Sopenharmony_ci        grOptions.fReducedShaderVariations = true;
315cb93a386Sopenharmony_ci    }
316cb93a386Sopenharmony_ci    sk_sp<GrDirectContext> grCtx;
317cb93a386Sopenharmony_ci    {
318cb93a386Sopenharmony_ci        auto restore = testCtx->makeCurrentAndAutoRestore();
319cb93a386Sopenharmony_ci        grCtx = testCtx->makeContext(grOptions);
320cb93a386Sopenharmony_ci    }
321cb93a386Sopenharmony_ci    if (!grCtx) {
322cb93a386Sopenharmony_ci        return ContextInfo();
323cb93a386Sopenharmony_ci    }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    if (shareContext) {
326cb93a386Sopenharmony_ci        SkASSERT(grCtx->directContextID() != shareContext->directContextID());
327cb93a386Sopenharmony_ci    }
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    // We must always add new contexts by pushing to the back so that when we delete them we delete
330cb93a386Sopenharmony_ci    // them in reverse order in which they were made.
331cb93a386Sopenharmony_ci    Context& context = fContexts.push_back();
332cb93a386Sopenharmony_ci    context.fBackend = backend;
333cb93a386Sopenharmony_ci    context.fTestContext = testCtx.release();
334cb93a386Sopenharmony_ci    context.fGrContext = SkRef(grCtx.get());
335cb93a386Sopenharmony_ci    context.fType = type;
336cb93a386Sopenharmony_ci    context.fOverrides = overrides;
337cb93a386Sopenharmony_ci    context.fAbandoned = false;
338cb93a386Sopenharmony_ci    context.fShareContext = shareContext;
339cb93a386Sopenharmony_ci    context.fShareIndex = shareIndex;
340cb93a386Sopenharmony_ci    context.fOptions = grOptions;
341cb93a386Sopenharmony_ci    context.fTestContext->makeCurrent();
342cb93a386Sopenharmony_ci    return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
343cb93a386Sopenharmony_ci}
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ciContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
346cb93a386Sopenharmony_ci    return this->getContextInfoInternal(type, overrides, nullptr, 0);
347cb93a386Sopenharmony_ci}
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ciContextInfo GrContextFactory::getSharedContextInfo(GrDirectContext* shareContext,
350cb93a386Sopenharmony_ci                                                   uint32_t shareIndex) {
351cb93a386Sopenharmony_ci    SkASSERT(shareContext);
352cb93a386Sopenharmony_ci    for (int i = 0; i < fContexts.count(); ++i) {
353cb93a386Sopenharmony_ci        if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
354cb93a386Sopenharmony_ci            return this->getContextInfoInternal(fContexts[i].fType, fContexts[i].fOverrides,
355cb93a386Sopenharmony_ci                                                shareContext, shareIndex);
356cb93a386Sopenharmony_ci        }
357cb93a386Sopenharmony_ci    }
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ci    return ContextInfo();
360cb93a386Sopenharmony_ci}
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci}  // namespace sk_gpu_test
363