• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "tools/gpu/gl/angle/GLTestContext_angle.h"
9 
10 #include "include/core/SkTime.h"
11 #include "include/gpu/gl/GrGLAssembleInterface.h"
12 #include "include/gpu/gl/GrGLInterface.h"
13 #include "src/core/SkTraceEvent.h"
14 #include "src/gpu/gl/GrGLDefines.h"
15 #include "src/gpu/gl/GrGLUtil.h"
16 #include "src/ports/SkOSLibrary.h"
17 #include "third_party/externals/angle2/include/platform/Platform.h"
18 
19 #include <vector>
20 
21 #define EGL_EGL_PROTOTYPES 1
22 #include <EGL/egl.h>
23 #include <EGL/eglext.h>
24 
25 #define EGL_PLATFORM_ANGLE_ANGLE                0x3202
26 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
27 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
28 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
29 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
30 
31 #define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
32 
33 using sk_gpu_test::ANGLEBackend;
34 using sk_gpu_test::ANGLEContextVersion;
35 
36 namespace {
37 struct Libs {
38     void* fGLLib;
39     void* fEGLLib;
40 };
41 
context_restorer()42 std::function<void()> context_restorer() {
43     auto display = eglGetCurrentDisplay();
44     auto dsurface = eglGetCurrentSurface(EGL_DRAW);
45     auto rsurface = eglGetCurrentSurface(EGL_READ);
46     auto context = eglGetCurrentContext();
47     return [display, dsurface, rsurface, context] {
48         eglMakeCurrent(display, dsurface, rsurface, context);
49     };
50 }
51 
angle_get_gl_proc(void * ctx,const char name[])52 static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
53     const Libs* libs = reinterpret_cast<const Libs*>(ctx);
54     GrGLFuncPtr proc = (GrGLFuncPtr) SkGetProcedureAddress(libs->fGLLib, name);
55     if (proc) {
56         return proc;
57     }
58     proc = (GrGLFuncPtr) SkGetProcedureAddress(libs->fEGLLib, name);
59     if (proc) {
60         return proc;
61     }
62     return eglGetProcAddress(name);
63 }
64 
get_angle_egl_display(void * nativeDisplay,ANGLEBackend type)65 void* get_angle_egl_display(void* nativeDisplay, ANGLEBackend type) {
66     PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
67     eglGetPlatformDisplayEXT =
68         (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
69 
70     // We expect ANGLE to support this extension
71     if (!eglGetPlatformDisplayEXT) {
72         return EGL_NO_DISPLAY;
73     }
74 
75     EGLint typeNum = 0;
76     switch (type) {
77         case ANGLEBackend::kD3D9:
78             typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
79             break;
80         case ANGLEBackend::kD3D11:
81             typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
82             break;
83         case ANGLEBackend::kOpenGL:
84             typeNum = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
85             break;
86     }
87     const EGLint attribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, typeNum, EGL_NONE };
88     return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
89 }
90 
91 class ANGLEGLContext : public sk_gpu_test::GLTestContext {
92 public:
93     ANGLEGLContext(ANGLEBackend, ANGLEContextVersion, ANGLEGLContext* shareContext, void* display);
94     ~ANGLEGLContext() override;
95 
96     GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
97     void destroyEGLImage(GrEGLImage) const override;
98     GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
99     std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
100 
101 private:
102     void destroyGLContext();
103 
104     void onPlatformMakeNotCurrent() const override;
105     void onPlatformMakeCurrent() const override;
106     std::function<void()> onPlatformGetAutoContextRestore() const override;
107     GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
108 
109     void*                       fContext;
110     void*                       fDisplay;
111     void*                       fSurface;
112     ANGLEBackend                fType;
113     ANGLEContextVersion         fVersion;
114     bool                        fOwnsDisplay;
115 
116     angle::ResetDisplayPlatformFunc fResetPlatform = nullptr;
117 
118     PFNEGLCREATEIMAGEKHRPROC    fCreateImage = nullptr;
119     PFNEGLDESTROYIMAGEKHRPROC   fDestroyImage = nullptr;
120 
121 #ifdef SK_BUILD_FOR_WIN
122     HWND                        fWindow;
123     HDC                         fDeviceContext;
124     static ATOM                 gWC;
125 #endif
126 };
127 
128 #ifdef SK_BUILD_FOR_WIN
129 ATOM ANGLEGLContext::gWC = 0;
130 
131 enum class IsWine { kUnknown, kNo, kYes };
132 
is_wine()133 static IsWine is_wine() {
134     HMODULE ntdll = GetModuleHandle("ntdll.dll");
135     if (!ntdll) {
136         SkDebugf("No ntdll.dll on Windows?!\n");
137         return IsWine::kUnknown;
138     }
139     return GetProcAddress(ntdll, "wine_get_version") == nullptr ? IsWine::kNo : IsWine::kYes;
140 }
141 
142 #endif
143 
ANGLE_getTraceCategoryEnabledFlag(angle::PlatformMethods * platform,const char * category_group)144 static const unsigned char* ANGLE_getTraceCategoryEnabledFlag(angle::PlatformMethods* platform,
145                                                               const char* category_group) {
146     return SkEventTracer::GetInstance()->getCategoryGroupEnabled(category_group);
147 }
148 
ANGLE_addTraceEvent(angle::PlatformMethods * platform,char phase,const unsigned char * category_group_enabled,const char * name,unsigned long long id,double timestamp,int num_args,const char ** arg_names,const unsigned char * arg_types,const unsigned long long * arg_values,unsigned char flags)149 static angle::TraceEventHandle ANGLE_addTraceEvent(angle::PlatformMethods* platform,
150                                                    char phase,
151                                                    const unsigned char* category_group_enabled,
152                                                    const char* name,
153                                                    unsigned long long id,
154                                                    double timestamp,
155                                                    int num_args,
156                                                    const char** arg_names,
157                                                    const unsigned char* arg_types,
158                                                    const unsigned long long* arg_values,
159                                                    unsigned char flags) {
160     static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "Non-64-bit trace event args!");
161     return SkEventTracer::GetInstance()->addTraceEvent(
162             phase, category_group_enabled, name, id, num_args, arg_names, arg_types,
163             reinterpret_cast<const uint64_t*>(arg_values), flags);
164 }
165 
ANGLE_updateTraceEventDuration(angle::PlatformMethods * platform,const unsigned char * category_group_enabled,const char * name,angle::TraceEventHandle handle)166 static void ANGLE_updateTraceEventDuration(angle::PlatformMethods* platform,
167                                            const unsigned char* category_group_enabled,
168                                            const char* name,
169                                            angle::TraceEventHandle handle) {
170     SkEventTracer::GetInstance()->updateTraceEventDuration(category_group_enabled, name, handle);
171 }
172 
ANGLE_monotonicallyIncreasingTime(angle::PlatformMethods * platform)173 static double ANGLE_monotonicallyIncreasingTime(angle::PlatformMethods* platform) {
174     return SkTime::GetSecs();
175 }
176 
ANGLEGLContext(ANGLEBackend type,ANGLEContextVersion version,ANGLEGLContext * shareContext,void * display)177 ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
178                                ANGLEGLContext* shareContext, void* display)
179     : fContext(EGL_NO_CONTEXT)
180     , fDisplay(display)
181     , fSurface(EGL_NO_SURFACE)
182     , fType(type)
183     , fVersion(version)
184     , fOwnsDisplay(false) {
185 #ifdef SK_BUILD_FOR_WIN
186     fWindow = nullptr;
187     fDeviceContext = nullptr;
188 
189     static IsWine gIsWine = is_wine();
190     if (gIsWine == IsWine::kYes && type != ANGLEBackend::kOpenGL) {
191         // D3D backends of ANGLE don't really work well under Wine with our tests and are likely to
192         // crash. This makes it easier to test using the GL ANGLE backend under Wine on Linux
193         // without lots of spurious Wine debug spew and crashes.
194         return;
195     }
196 
197     if (EGL_NO_DISPLAY == fDisplay) {
198         HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr);
199 
200         if (!gWC) {
201             WNDCLASS wc;
202             wc.cbClsExtra = 0;
203             wc.cbWndExtra = 0;
204             wc.hbrBackground = nullptr;
205             wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
206             wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
207             wc.hInstance = hInstance;
208             wc.lpfnWndProc = (WNDPROC) DefWindowProc;
209             wc.lpszClassName = TEXT("ANGLE-win");
210             wc.lpszMenuName = nullptr;
211             wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
212 
213             gWC = RegisterClass(&wc);
214             if (!gWC) {
215                 SkDebugf("Could not register window class.\n");
216                 return;
217             }
218         }
219         if (!(fWindow = CreateWindow(TEXT("ANGLE-win"),
220                                         TEXT("The Invisible Man"),
221                                         WS_OVERLAPPEDWINDOW,
222                                         0, 0, 1, 1,
223                                         nullptr, nullptr,
224                                         hInstance, nullptr))) {
225             SkDebugf("Could not create window.\n");
226             return;
227         }
228 
229         if (!(fDeviceContext = GetDC(fWindow))) {
230             SkDebugf("Could not get device context.\n");
231             this->destroyGLContext();
232             return;
233         }
234 
235         fDisplay = get_angle_egl_display(fDeviceContext, type);
236         fOwnsDisplay = true;
237     }
238 #else
239     SkASSERT(EGL_NO_DISPLAY == fDisplay);
240     fDisplay = get_angle_egl_display(EGL_DEFAULT_DISPLAY, type);
241     fOwnsDisplay = true;
242 #endif
243     if (EGL_NO_DISPLAY == fDisplay) {
244         SkDebugf("Could not create EGL display!");
245         return;
246     }
247 
248     // Add ANGLE platform hooks to connect to Skia's tracing implementation
249     angle::GetDisplayPlatformFunc getPlatform = reinterpret_cast<angle::GetDisplayPlatformFunc>(
250             eglGetProcAddress("ANGLEGetDisplayPlatform"));
251     if (getPlatform) {
252         fResetPlatform = reinterpret_cast<angle::ResetDisplayPlatformFunc>(
253                 eglGetProcAddress("ANGLEResetDisplayPlatform"));
254         SkASSERT(fResetPlatform);
255 
256         angle::PlatformMethods* platformMethods = nullptr;
257         if (getPlatform(fDisplay, angle::g_PlatformMethodNames, angle::g_NumPlatformMethods,
258                         nullptr, &platformMethods)) {
259             platformMethods->addTraceEvent               = ANGLE_addTraceEvent;
260             platformMethods->getTraceCategoryEnabledFlag = ANGLE_getTraceCategoryEnabledFlag;
261             platformMethods->updateTraceEventDuration    = ANGLE_updateTraceEventDuration;
262             platformMethods->monotonicallyIncreasingTime = ANGLE_monotonicallyIncreasingTime;
263         }
264     }
265 
266     EGLint majorVersion;
267     EGLint minorVersion;
268     if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
269         SkDebugf("Could not initialize display!");
270         this->destroyGLContext();
271         return;
272     }
273 
274     EGLint numConfigs;
275     static const EGLint configAttribs[] = {
276         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
277         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
278         EGL_RED_SIZE, 8,
279         EGL_GREEN_SIZE, 8,
280         EGL_BLUE_SIZE, 8,
281         EGL_ALPHA_SIZE, 8,
282         EGL_NONE
283     };
284 
285     EGLConfig surfaceConfig;
286     if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
287         SkDebugf("Could not create choose config!");
288         this->destroyGLContext();
289         return;
290     }
291 
292     int versionNum = ANGLEContextVersion::kES2 == version ? 2 : 3;
293     std::vector<EGLint> contextAttribs = {
294         EGL_CONTEXT_CLIENT_VERSION, versionNum,
295     };
296 
297     const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
298     if (strstr(extensions, "EGL_ANGLE_create_context_backwards_compatible")) {
299         contextAttribs.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
300         contextAttribs.push_back(EGL_FALSE);
301     }
302 
303     contextAttribs.push_back(EGL_NONE);
304 
305     EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
306     fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs.data());
307     if (EGL_NO_CONTEXT == fContext) {
308         SkDebugf("Could not create context!");
309         this->destroyGLContext();
310         return;
311     }
312 
313     static const EGLint surfaceAttribs[] = {
314         EGL_WIDTH, 1,
315         EGL_HEIGHT, 1,
316         EGL_NONE
317     };
318 
319     fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
320 
321     SkScopeExit restorer(context_restorer());
322     if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
323         SkDebugf("Could not set the context.");
324         this->destroyGLContext();
325         return;
326     }
327 
328     sk_sp<const GrGLInterface> gl = sk_gpu_test::CreateANGLEGLInterface();
329     if (nullptr == gl.get()) {
330         SkDebugf("Could not create ANGLE GL interface!\n");
331         this->destroyGLContext();
332         return;
333     }
334     if (!gl->validate()) {
335         SkDebugf("Could not validate ANGLE GL interface!\n");
336         this->destroyGLContext();
337         return;
338     }
339 
340 #ifdef SK_DEBUG
341     // Verify that the interface we requested was actually returned to us
342     const GrGLubyte* rendererUByte;
343     GR_GL_CALL_RET(gl.get(), rendererUByte, GetString(GR_GL_RENDERER));
344     const char* renderer = reinterpret_cast<const char*>(rendererUByte);
345     switch (type) {
346     case ANGLEBackend::kD3D9:
347         SkASSERT(strstr(renderer, "Direct3D9"));
348         break;
349     case ANGLEBackend::kD3D11:
350         SkASSERT(strstr(renderer, "Direct3D11"));
351         break;
352     case ANGLEBackend::kOpenGL:
353         SkASSERT(strstr(renderer, "OpenGL"));
354         break;
355     }
356 #endif
357     if (strstr(extensions, "EGL_KHR_image")) {
358         fCreateImage = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
359         fDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
360     }
361 
362     this->init(std::move(gl));
363 }
364 
~ANGLEGLContext()365 ANGLEGLContext::~ANGLEGLContext() {
366     this->teardown();
367     this->destroyGLContext();
368 }
369 
texture2DToEGLImage(GrGLuint texID) const370 GrEGLImage ANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
371     if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
372         return GR_EGL_NO_IMAGE;
373     }
374     EGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
375                          GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
376                          GR_EGL_NONE };
377     // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
378     GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
379     return fCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs);
380 }
381 
destroyEGLImage(GrEGLImage image) const382 void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const { fDestroyImage(fDisplay, image); }
383 
eglImageToExternalTexture(GrEGLImage image) const384 GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
385     while (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
386     if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
387         return 0;
388     }
389     typedef GrGLvoid (EGLAPIENTRY *EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
390     EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
391         (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
392     if (!glEGLImageTargetTexture2D) {
393         return 0;
394     }
395     GrGLuint texID;
396     GR_GL_CALL(this->gl(), GenTextures(1, &texID));
397     if (!texID) {
398         return 0;
399     }
400     GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
401     if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
402         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
403         return 0;
404     }
405     glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
406     if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
407         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
408         return 0;
409     }
410     return texID;
411 }
412 
makeNew() const413 std::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const {
414     // For EGLImage sharing between contexts to work in ANGLE the two contexts
415     // need to share the same display
416     std::unique_ptr<sk_gpu_test::GLTestContext> ctx =
417         sk_gpu_test::MakeANGLETestContext(fType, fVersion, nullptr, fDisplay);
418     if (ctx) {
419         ctx->makeCurrent();
420     }
421     return ctx;
422 }
423 
destroyGLContext()424 void ANGLEGLContext::destroyGLContext() {
425     if (EGL_NO_DISPLAY != fDisplay) {
426         if (eglGetCurrentContext() == fContext) {
427             // This will ensure that the context is immediately deleted.
428             eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
429         }
430 
431         if (EGL_NO_CONTEXT != fContext) {
432             eglDestroyContext(fDisplay, fContext);
433             fContext = EGL_NO_CONTEXT;
434         }
435 
436         if (EGL_NO_SURFACE != fSurface) {
437             eglDestroySurface(fDisplay, fSurface);
438             fSurface = EGL_NO_SURFACE;
439         }
440 
441         if (fResetPlatform) {
442             fResetPlatform(fDisplay);
443         }
444 
445         if (fOwnsDisplay) {
446             // Only terminate the display if we created it. If we were a context created by makeNew,
447             // the parent context might still have work to do on the display. If we terminate now,
448             // that context might be deleted once it no longer becomes current, and we may hit
449             // undefined behavior in this destructor when calling eglDestroy[Context|Surface] on a
450             // terminated display.
451             eglTerminate(fDisplay);
452         }
453         fDisplay = EGL_NO_DISPLAY;
454         fOwnsDisplay = false;
455     }
456 
457 #ifdef SK_BUILD_FOR_WIN
458     if (fWindow) {
459         if (fDeviceContext) {
460             ReleaseDC(fWindow, fDeviceContext);
461             fDeviceContext = 0;
462         }
463 
464         DestroyWindow(fWindow);
465         fWindow = 0;
466     }
467 #endif
468 }
469 
onPlatformMakeNotCurrent() const470 void ANGLEGLContext::onPlatformMakeNotCurrent() const {
471     if (!eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
472         SkDebugf("Could not reset the context 0x%x.\n", eglGetError());
473     }
474 }
475 
onPlatformMakeCurrent() const476 void ANGLEGLContext::onPlatformMakeCurrent() const {
477     if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
478         SkDebugf("Could not set the context 0x%x.\n", eglGetError());
479     }
480 }
481 
onPlatformGetAutoContextRestore() const482 std::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const {
483     if (eglGetCurrentContext() == fContext) {
484         return nullptr;
485     }
486     return context_restorer();
487 }
488 
onPlatformGetProcAddress(const char * name) const489 GrGLFuncPtr ANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
490     return eglGetProcAddress(name);
491 }
492 }  // anonymous namespace
493 
494 namespace sk_gpu_test {
CreateANGLEGLInterface()495 sk_sp<const GrGLInterface> CreateANGLEGLInterface() {
496     static Libs gLibs = { nullptr, nullptr };
497 
498     if (nullptr == gLibs.fGLLib) {
499         // We load the ANGLE library and never let it go
500 #if defined _WIN32
501         gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.dll");
502         gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.dll");
503 #elif defined SK_BUILD_FOR_MAC
504         gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.dylib");
505         gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.dylib");
506 #else
507         gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.so");
508         gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.so");
509 #endif
510     }
511 
512     if (nullptr == gLibs.fGLLib || nullptr == gLibs.fEGLLib) {
513         // We can't setup the interface correctly w/o the so
514         return nullptr;
515     }
516 
517     return GrGLMakeAssembledGLESInterface(&gLibs, angle_get_gl_proc);
518 }
519 
MakeANGLETestContext(ANGLEBackend type,ANGLEContextVersion version,GLTestContext * shareContext,void * display)520 std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
521                                                     GLTestContext* shareContext, void* display) {
522 #if defined(SK_BUILD_FOR_WIN) && defined(_M_ARM64)
523     // Windows-on-ARM only has D3D11. This will fail correctly, but it produces huge amounts of
524     // debug output for every unit test from both ANGLE and our context factory.
525     if (ANGLEBackend::kD3D11 != type) {
526         return nullptr;
527     }
528 #endif
529 
530     ANGLEGLContext* angleShareContext = reinterpret_cast<ANGLEGLContext*>(shareContext);
531     std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version,
532                                                           angleShareContext, display));
533     if (!ctx->isValid()) {
534         return nullptr;
535     }
536     return ctx;
537 }
538 }  // namespace sk_gpu_test
539