Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
#define GR_EGL_NO_IMAGE
#define GR_EGL_GL_TEXTURE_LEVEL
#define GR_GL_NO_ERROR
#define GR_EGL_NONE
#define GR_GL_TEXTURE_EXTERNAL
void(* GrGLFuncPtr)()
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
sk_sp< SkImage > image
Definition examples.cpp:29
SK_API sk_sp< const GrGLInterface > MakeEGL()
GLTestContext * CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, GLTestContext *shareContext)