Flutter Engine
The Flutter Engine
CreatePlatformGLTestContext_egl.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011 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
12
13#include <vector>
14
15#define EGL_PROTECTED_CONTENT_EXT 0x32C0
16#define GL_GLEXT_PROTOTYPES
17#include <EGL/egl.h>
18#include <EGL/eglext.h>
19
20extern bool gCreateProtectedContext;
21
22namespace {
23
24std::function<void()> context_restorer() {
25 auto display = eglGetCurrentDisplay();
26 auto dsurface = eglGetCurrentSurface(EGL_DRAW);
27 auto rsurface = eglGetCurrentSurface(EGL_READ);
28 auto context = eglGetCurrentContext();
29 return [display, dsurface, rsurface, context] {
30 eglMakeCurrent(display, dsurface, rsurface, context);
31 };
32}
33
34class EGLGLTestContext : public sk_gpu_test::GLTestContext {
35public:
36 EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
37 ~EGLGLTestContext() override;
38
39 GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
40 void destroyEGLImage(GrEGLImage) const override;
41 GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
42 std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
43
44private:
45 void destroyGLContext();
46
47 void onPlatformMakeNotCurrent() const override;
48 void onPlatformMakeCurrent() const override;
49 std::function<void()> onPlatformGetAutoContextRestore() const override;
50 GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
51
52 PFNEGLCREATEIMAGEKHRPROC fEglCreateImageProc = nullptr;
53 PFNEGLDESTROYIMAGEKHRPROC fEglDestroyImageProc = nullptr;
54
55 EGLContext fContext;
56 EGLDisplay fDisplay;
57 EGLSurface fSurface;
58};
59
60static EGLContext create_gles_egl_context(EGLDisplay display,
61 EGLConfig surfaceConfig,
62 EGLContext eglShareContext,
63 EGLint eglContextClientVersion,
64 bool createProtected) {
65
66 std::vector<EGLint> contextAttribs = {
67 EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion,
68 };
69
70 if (createProtected) {
71 contextAttribs.push_back(EGL_PROTECTED_CONTENT_EXT);
72 contextAttribs.push_back(EGL_TRUE);
73 }
74
75 contextAttribs.push_back(EGL_NONE);
76
77 return eglCreateContext(display, surfaceConfig, eglShareContext, contextAttribs.data());
78}
79
80static EGLContext create_gl_egl_context(EGLDisplay display,
81 EGLConfig surfaceConfig,
82 EGLContext eglShareContext,
83 bool createProtected) {
84
85 std::vector<EGLint> contextAttribs;
86
87 if (createProtected) {
88 contextAttribs.push_back(EGL_PROTECTED_CONTENT_EXT);
89 contextAttribs.push_back(EGL_TRUE);
90 }
91
92 contextAttribs.push_back(EGL_NONE);
93
94 return eglCreateContext(display, surfaceConfig, eglShareContext, contextAttribs.data());
95}
96
97EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext)
98 : fContext(EGL_NO_CONTEXT)
99 , fDisplay(EGL_NO_DISPLAY)
100 , fSurface(EGL_NO_SURFACE) {
101
102 EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
103
104 static const GrGLStandard kStandards[] = {
107 };
108
109 size_t apiLimit = std::size(kStandards);
110 size_t api = 0;
111 if (forcedGpuAPI == kGL_GrGLStandard) {
112 apiLimit = 1;
113 } else if (forcedGpuAPI == kGLES_GrGLStandard) {
114 api = 1;
115 }
116 SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kStandards[api] == forcedGpuAPI);
117
119
120 for (; nullptr == gl.get() && api < apiLimit; ++api) {
121 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
122
123 EGLint majorVersion;
124 EGLint minorVersion;
125 eglInitialize(fDisplay, &majorVersion, &minorVersion);
126
127 const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
128
129#if 0
130 SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR));
131 SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS));
132 SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
133 SkDebugf("EXTENSIONS %s\n", extensions);
134#endif
135 bool gles = kGLES_GrGLStandard == kStandards[api];
136
137 if (!eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) {
138 continue;
139 }
140
141 EGLint numConfigs = 0;
142 const EGLint configAttribs[] = {
143 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
144 EGL_RENDERABLE_TYPE, gles ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
145 EGL_RED_SIZE, 8,
146 EGL_GREEN_SIZE, 8,
147 EGL_BLUE_SIZE, 8,
148 EGL_ALPHA_SIZE, 8,
149 EGL_NONE
150 };
151
152 EGLConfig surfaceConfig;
153 if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
154 SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError());
155 continue;
156 }
157
158 if (0 == numConfigs) {
159 SkDebugf("No suitable EGL config found.\n");
160 continue;
161 }
162
163 bool createProtected = gCreateProtectedContext;
164 if (createProtected && !strstr(extensions, "EGL_EXT_protected_content")) {
165 SkDebugf("Missing EGL_EXT_protected_content support!\n");
166 createProtected = false;
167 }
168
169 if (gles) {
170#if defined(GR_EGL_TRY_GLES3_THEN_GLES2)
171 // Some older devices (Nexus7/Tegra3) crash when you try this. So it is (for now)
172 // hidden behind this flag.
173 fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 3,
174 createProtected);
175 if (EGL_NO_CONTEXT == fContext) {
176 fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 2,
177 createProtected);
178 }
179#else
180 fContext = create_gles_egl_context(fDisplay, surfaceConfig, eglShareContext, 2,
181 createProtected);
182#endif
183 } else {
184 fContext = create_gl_egl_context(fDisplay, surfaceConfig, eglShareContext,
185 createProtected);
186 }
187 if (EGL_NO_CONTEXT == fContext) {
188 SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError());
189 continue;
190 }
191
192 static const EGLint kSurfaceAttribs[] = {
193 EGL_WIDTH, 1,
194 EGL_HEIGHT, 1,
195 createProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
196 createProtected ? EGL_TRUE : EGL_NONE,
197 EGL_NONE
198 };
199
200 fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs);
201 if (EGL_NO_SURFACE == fSurface) {
202 SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError());
203 this->destroyGLContext();
204 continue;
205 }
206
207 SkScopeExit restorer(context_restorer());
208 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
209 SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
210 this->destroyGLContext();
211 continue;
212 }
213
214#if defined(SK_GL)
216 if (!gl) {
217 SkDebugf("Failed to create gl interface.\n");
218 this->destroyGLContext();
219 continue;
220 }
221
222 if (!gl->validate()) {
223 SkDebugf("Failed to validate gl interface.\n");
224 this->destroyGLContext();
225 continue;
226 }
227 if (strstr(extensions, "EGL_KHR_image")) {
228 fEglCreateImageProc = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
229 fEglDestroyImageProc =
230 (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
231 }
232
233 this->init(std::move(gl));
234#else
235 // Allow the GLTestContext creation to succeed without a GrGLInterface to support
236 // GrContextFactory's persistent GL context workaround for Vulkan. We won't need the
237 // GrGLInterface since we're not running the GL backend.
238 this->init(nullptr);
239#endif
240 break;
241 }
242}
243
244EGLGLTestContext::~EGLGLTestContext() {
245 this->teardown();
246 this->destroyGLContext();
247}
248
249void EGLGLTestContext::destroyGLContext() {
250 if (fDisplay) {
251 if (fContext) {
252 if (eglGetCurrentContext() == fContext) {
253 // This will ensure that the context is immediately deleted.
254 eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
255 }
256 eglDestroyContext(fDisplay, fContext);
257 fContext = EGL_NO_CONTEXT;
258 }
259
260 if (fSurface) {
261 eglDestroySurface(fDisplay, fSurface);
262 fSurface = EGL_NO_SURFACE;
263 }
264
265 //TODO should we close the display?
266 fDisplay = EGL_NO_DISPLAY;
267 }
268}
269
270GrEGLImage EGLGLTestContext::texture2DToEGLImage(GrGLuint texID) const {
271#if defined(SK_GL)
272 if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image") || !fEglCreateImageProc) {
273 return GR_EGL_NO_IMAGE;
274 }
275 EGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0, GR_EGL_NONE };
276 GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>(texID);
277 return fEglCreateImageProc(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs);
278#else
279 (void)fEglCreateImageProc;
280 return nullptr;
281#endif
282}
283
284void EGLGLTestContext::destroyEGLImage(GrEGLImage image) const {
285 fEglDestroyImageProc(fDisplay, image);
286}
287
288GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
289#if defined(SK_GL)
290 while (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
291 if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
292 return 0;
293 }
294 typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
295
296 EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
297 (EGLImageTargetTexture2DProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
298 if (!glEGLImageTargetTexture2D) {
299 return 0;
300 }
301 GrGLuint texID;
302 GR_GL_CALL(this->gl(), GenTextures(1, &texID));
303 if (!texID) {
304 return 0;
305 }
306 GR_GL_CALL_NOERRCHECK(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
307 if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
308 GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
309 return 0;
310 }
311 glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
312 if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
313 GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
314 return 0;
315 }
316 return texID;
317#else
318 return 0;
319#endif
320}
321
322std::unique_ptr<sk_gpu_test::GLTestContext> EGLGLTestContext::makeNew() const {
323 std::unique_ptr<sk_gpu_test::GLTestContext> ctx(new EGLGLTestContext(this->gl()->fStandard,
324 nullptr));
325 if (ctx) {
326 ctx->makeCurrent();
327 }
328 return ctx;
329}
330
331void EGLGLTestContext::onPlatformMakeNotCurrent() const {
332 if (!eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )) {
333 SkDebugf("Could not reset the context.\n");
334 }
335}
336
337void EGLGLTestContext::onPlatformMakeCurrent() const {
338 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
339 SkDebugf("Could not set the context.\n");
340 }
341}
342
343std::function<void()> EGLGLTestContext::onPlatformGetAutoContextRestore() const {
344 if (eglGetCurrentContext() == fContext) {
345 return nullptr;
346 }
347 return context_restorer();
348}
349
350GrGLFuncPtr EGLGLTestContext::onPlatformGetProcAddress(const char* procName) const {
351 return eglGetProcAddress(procName);
352}
353
354} // anonymous namespace
355
356namespace sk_gpu_test {
357GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
358 GLTestContext *shareContext) {
359 EGLGLTestContext* eglShareContext = reinterpret_cast<EGLGLTestContext*>(shareContext);
360 EGLGLTestContext *ctx = new EGLGLTestContext(forcedGpuAPI, eglShareContext);
361 if (!ctx->isValid()) {
362 delete ctx;
363 return nullptr;
364 }
365 return ctx;
366}
367} // namespace sk_gpu_test
bool gCreateProtectedContext
#define EGL_PROTECTED_CONTENT_EXT
#define GR_EGL_GL_TEXTURE_2D
Definition: GrGLDefines.h:1118
#define GR_EGL_NO_IMAGE
Definition: GrGLDefines.h:1124
#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
GrGLStandard
Definition: GrGLTypes.h:19
@ kNone_GrGLStandard
Definition: GrGLTypes.h:20
@ kGLES_GrGLStandard
Definition: GrGLTypes.h:22
@ kGL_GrGLStandard
Definition: GrGLTypes.h:21
unsigned int GrGLenum
Definition: GrGLTypes.h:102
void * GrEGLImage
Definition: GrGLTypes.h:165
void * GrGLeglImage
Definition: GrGLTypes.h:128
void GrGLvoid
Definition: GrGLTypes.h:120
void * GrEGLClientBuffer
Definition: GrGLTypes.h:168
#define GR_GL_CALL_NOERRCHECK(IFACE, X)
Definition: GrGLUtil.h:389
#define GR_GL_CALL(IFACE, X)
Definition: GrGLUtil.h:381
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
const Context & fContext
Dart_NativeFunction function
Definition: fuchsia.cc:51
SK_API sk_sp< const GrGLInterface > MakeEGL()
static bool init()
sk_sp< const SkImage > image
Definition: SkRecords.h:269
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
gl
Definition: malisc.py:41
GLTestContext * CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, GLTestContext *shareContext)