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