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