gfx/gl/GLLibraryEGL.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:c95b50f9ede9
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "GLLibraryEGL.h"
6
7 #include "gfxCrashReporterUtils.h"
8 #include "mozilla/Preferences.h"
9 #include "nsDirectoryServiceDefs.h"
10 #include "nsDirectoryServiceUtils.h"
11 #include "nsPrintfCString.h"
12 #ifdef XP_WIN
13 #include "nsWindowsHelpers.h"
14 #endif
15 #include "prenv.h"
16 #include "GLContext.h"
17 #include "gfxPrefs.h"
18
19 namespace mozilla {
20 namespace gl {
21
22 GLLibraryEGL sEGLLibrary;
23
24 // should match the order of EGLExtensions, and be null-terminated.
25 static const char *sEGLExtensionNames[] = {
26 "EGL_KHR_image_base",
27 "EGL_KHR_image_pixmap",
28 "EGL_KHR_gl_texture_2D_image",
29 "EGL_KHR_lock_surface",
30 "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
31 "EGL_EXT_create_context_robustness",
32 "EGL_KHR_image",
33 "EGL_KHR_fence_sync",
34 nullptr
35 };
36
37 #if defined(ANDROID)
38
39 static PRLibrary* LoadApitraceLibrary()
40 {
41 if (!gfxPrefs::UseApitrace()) {
42 return nullptr;
43 }
44
45 static PRLibrary* sApitraceLibrary = nullptr;
46
47 if (sApitraceLibrary)
48 return sApitraceLibrary;
49
50 nsCString logFile = Preferences::GetCString("gfx.apitrace.logfile");
51
52 if (logFile.IsEmpty()) {
53 logFile = "firefox.trace";
54 }
55
56 // The firefox process can't write to /data/local, but it can write
57 // to $GRE_HOME/
58 nsAutoCString logPath;
59 logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
60
61 // apitrace uses the TRACE_FILE environment variable to determine where
62 // to log trace output to
63 printf_stderr("Logging GL tracing output to %s", logPath.get());
64 setenv("TRACE_FILE", logPath.get(), false);
65
66 printf_stderr("Attempting load of %s\n", APITRACE_LIB);
67
68 sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB);
69
70 return sApitraceLibrary;
71 }
72
73 #endif // ANDROID
74
75 #ifdef XP_WIN
76 // see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
77 static PRLibrary*
78 LoadLibraryForEGLOnWindows(const nsAString& filename)
79 {
80 nsCOMPtr<nsIFile> file;
81 nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
82 if (NS_FAILED(rv))
83 return nullptr;
84
85 file->Append(filename);
86 PRLibrary* lib = nullptr;
87 rv = file->Load(&lib);
88 if (NS_FAILED(rv)) {
89 nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail",
90 NS_LossyConvertUTF16toASCII(filename).get());
91 NS_WARNING(msg.get());
92 }
93 return lib;
94 }
95 #endif // XP_WIN
96
97 bool
98 GLLibraryEGL::EnsureInitialized()
99 {
100 if (mInitialized) {
101 return true;
102 }
103
104 mozilla::ScopedGfxFeatureReporter reporter("EGL");
105
106 #ifdef XP_WIN
107 #ifdef MOZ_WEBGL
108 if (!mEGLLibrary) {
109 // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and
110 // we should look for them there. We have to load the libs in this
111 // order, because libEGL.dll depends on libGLESv2.dll which depends on the DXSDK
112 // libraries. This matters especially for WebRT apps which are in a different directory.
113 // See bug 760323 and bug 749459
114
115 #ifndef MOZ_D3DCOMPILER_DLL
116 #error MOZ_D3DCOMPILER_DLL should have been defined by the Makefile
117 #endif
118 // Windows 8.1 has d3dcompiler_47.dll in the system directory.
119 // Try it first. Note that _46 will never be in the system
120 // directory and we ship with at least _43. So there is no point
121 // trying _46 and _43 in the system directory.
122 if (!LoadLibrarySystem32(L"d3dcompiler_47.dll")) {
123 // Fall back to the version that we shipped with.
124 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_DLL)));
125 }
126 // intentionally leak the D3DCOMPILER_DLL library
127
128 LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll"));
129 // intentionally leak the libGLESv2.dll library
130
131 mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll"));
132
133 if (!mEGLLibrary)
134 return false;
135 }
136 #endif // MOZ_WEBGL
137 #else // !Windows
138
139 // On non-Windows (Android) we use system copies of libEGL. We look for
140 // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
141
142 #if defined(ANDROID)
143 if (!mEGLLibrary)
144 mEGLLibrary = LoadApitraceLibrary();
145 #endif
146
147 if (!mEGLLibrary) {
148 printf_stderr("Attempting load of libEGL.so\n");
149 mEGLLibrary = PR_LoadLibrary("libEGL.so");
150 }
151 #if defined(XP_UNIX)
152 if (!mEGLLibrary) {
153 mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
154 }
155 #endif
156
157 if (!mEGLLibrary) {
158 NS_WARNING("Couldn't load EGL LIB.");
159 return false;
160 }
161
162 #endif // !Windows
163
164 #define SYMBOL(name) \
165 { (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } }
166
167 GLLibraryLoader::SymLoadStruct earlySymbols[] = {
168 SYMBOL(GetDisplay),
169 SYMBOL(GetCurrentSurface),
170 SYMBOL(GetCurrentContext),
171 SYMBOL(MakeCurrent),
172 SYMBOL(DestroyContext),
173 SYMBOL(CreateContext),
174 SYMBOL(DestroySurface),
175 SYMBOL(CreateWindowSurface),
176 SYMBOL(CreatePbufferSurface),
177 SYMBOL(CreatePixmapSurface),
178 SYMBOL(BindAPI),
179 SYMBOL(Initialize),
180 SYMBOL(ChooseConfig),
181 SYMBOL(GetError),
182 SYMBOL(GetConfigs),
183 SYMBOL(GetConfigAttrib),
184 SYMBOL(WaitNative),
185 SYMBOL(GetProcAddress),
186 SYMBOL(SwapBuffers),
187 SYMBOL(CopyBuffers),
188 SYMBOL(QueryString),
189 SYMBOL(QueryContext),
190 SYMBOL(BindTexImage),
191 SYMBOL(ReleaseTexImage),
192 SYMBOL(QuerySurface),
193 { nullptr, { nullptr } }
194 };
195
196 if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) {
197 NS_WARNING("Couldn't find required entry points in EGL library (early init)");
198 return false;
199 }
200
201 mEGLDisplay = fGetDisplay(EGL_DEFAULT_DISPLAY);
202 if (!fInitialize(mEGLDisplay, nullptr, nullptr))
203 return false;
204
205 const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
206 if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) {
207 mIsANGLE = true;
208 }
209
210 InitExtensions();
211
212 GLLibraryLoader::PlatformLookupFunction lookupFunction =
213 (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
214
215 if (IsExtensionSupported(KHR_lock_surface)) {
216 GLLibraryLoader::SymLoadStruct lockSymbols[] = {
217 { (PRFuncPtr*) &mSymbols.fLockSurface, { "eglLockSurfaceKHR", nullptr } },
218 { (PRFuncPtr*) &mSymbols.fUnlockSurface, { "eglUnlockSurfaceKHR", nullptr } },
219 { nullptr, { nullptr } }
220 };
221
222 bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
223 &lockSymbols[0],
224 lookupFunction);
225 if (!success) {
226 NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
227
228 MarkExtensionUnsupported(KHR_lock_surface);
229
230 mSymbols.fLockSurface = nullptr;
231 mSymbols.fUnlockSurface = nullptr;
232 }
233 }
234
235 if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
236 GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
237 { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", nullptr } },
238 { nullptr, { nullptr } }
239 };
240
241 bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
242 &d3dSymbols[0],
243 lookupFunction);
244 if (!success) {
245 NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!");
246
247 MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
248
249 mSymbols.fQuerySurfacePointerANGLE = nullptr;
250 }
251 }
252
253 if (IsExtensionSupported(KHR_fence_sync)) {
254 GLLibraryLoader::SymLoadStruct syncSymbols[] = {
255 { (PRFuncPtr*) &mSymbols.fCreateSync, { "eglCreateSyncKHR", nullptr } },
256 { (PRFuncPtr*) &mSymbols.fDestroySync, { "eglDestroySyncKHR", nullptr } },
257 { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "eglClientWaitSyncKHR", nullptr } },
258 { (PRFuncPtr*) &mSymbols.fGetSyncAttrib, { "eglGetSyncAttribKHR", nullptr } },
259 { nullptr, { nullptr } }
260 };
261
262 bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
263 &syncSymbols[0],
264 lookupFunction);
265 if (!success) {
266 NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
267
268 MarkExtensionUnsupported(KHR_fence_sync);
269
270 mSymbols.fCreateSync = nullptr;
271 mSymbols.fDestroySync = nullptr;
272 mSymbols.fClientWaitSync = nullptr;
273 mSymbols.fGetSyncAttrib = nullptr;
274 }
275 }
276
277 if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
278 GLLibraryLoader::SymLoadStruct imageSymbols[] = {
279 { (PRFuncPtr*) &mSymbols.fCreateImage, { "eglCreateImageKHR", nullptr } },
280 { (PRFuncPtr*) &mSymbols.fDestroyImage, { "eglDestroyImageKHR", nullptr } },
281 { nullptr, { nullptr } }
282 };
283
284 bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
285 &imageSymbols[0],
286 lookupFunction);
287 if (!success) {
288 NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
289
290 MarkExtensionUnsupported(KHR_image);
291 MarkExtensionUnsupported(KHR_image_base);
292 MarkExtensionUnsupported(KHR_image_pixmap);
293
294 mSymbols.fCreateImage = nullptr;
295 mSymbols.fDestroyImage = nullptr;
296 }
297 } else {
298 MarkExtensionUnsupported(KHR_image_pixmap);
299 }
300
301 mInitialized = true;
302 reporter.SetSuccessful();
303 return true;
304 }
305
306 void
307 GLLibraryEGL::InitExtensions()
308 {
309 const char *extensions = (const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
310
311 if (!extensions) {
312 NS_WARNING("Failed to load EGL extension list!");
313 return;
314 }
315
316 bool debugMode = false;
317 #ifdef DEBUG
318 if (PR_GetEnv("MOZ_GL_DEBUG"))
319 debugMode = true;
320
321 static bool firstRun = true;
322 #else
323 // Non-DEBUG, so never spew.
324 const bool firstRun = false;
325 #endif
326
327 GLContext::InitializeExtensionsBitSet(mAvailableExtensions, extensions, sEGLExtensionNames, firstRun && debugMode);
328
329 #ifdef DEBUG
330 firstRun = false;
331 #endif
332 }
333
334 void
335 GLLibraryEGL::DumpEGLConfig(EGLConfig cfg)
336 {
337 int attrval;
338 int err;
339
340 #define ATTR(_x) do { \
341 fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
342 if ((err = fGetError()) != 0x3000) { \
343 printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
344 } else { \
345 printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
346 } \
347 } while(0)
348
349 printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
350
351 ATTR(BUFFER_SIZE);
352 ATTR(ALPHA_SIZE);
353 ATTR(BLUE_SIZE);
354 ATTR(GREEN_SIZE);
355 ATTR(RED_SIZE);
356 ATTR(DEPTH_SIZE);
357 ATTR(STENCIL_SIZE);
358 ATTR(CONFIG_CAVEAT);
359 ATTR(CONFIG_ID);
360 ATTR(LEVEL);
361 ATTR(MAX_PBUFFER_HEIGHT);
362 ATTR(MAX_PBUFFER_PIXELS);
363 ATTR(MAX_PBUFFER_WIDTH);
364 ATTR(NATIVE_RENDERABLE);
365 ATTR(NATIVE_VISUAL_ID);
366 ATTR(NATIVE_VISUAL_TYPE);
367 ATTR(PRESERVED_RESOURCES);
368 ATTR(SAMPLES);
369 ATTR(SAMPLE_BUFFERS);
370 ATTR(SURFACE_TYPE);
371 ATTR(TRANSPARENT_TYPE);
372 ATTR(TRANSPARENT_RED_VALUE);
373 ATTR(TRANSPARENT_GREEN_VALUE);
374 ATTR(TRANSPARENT_BLUE_VALUE);
375 ATTR(BIND_TO_TEXTURE_RGB);
376 ATTR(BIND_TO_TEXTURE_RGBA);
377 ATTR(MIN_SWAP_INTERVAL);
378 ATTR(MAX_SWAP_INTERVAL);
379 ATTR(LUMINANCE_SIZE);
380 ATTR(ALPHA_MASK_SIZE);
381 ATTR(COLOR_BUFFER_TYPE);
382 ATTR(RENDERABLE_TYPE);
383 ATTR(CONFORMANT);
384
385 #undef ATTR
386 }
387
388 void
389 GLLibraryEGL::DumpEGLConfigs()
390 {
391 int nc = 0;
392 fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
393 EGLConfig *ec = new EGLConfig[nc];
394 fGetConfigs(mEGLDisplay, ec, nc, &nc);
395
396 for (int i = 0; i < nc; ++i) {
397 printf_stderr ("========= EGL Config %d ========\n", i);
398 DumpEGLConfig(ec[i]);
399 }
400
401 delete [] ec;
402 }
403
404 #ifdef DEBUG
405 /*static*/ void
406 GLLibraryEGL::BeforeGLCall(const char* glFunction)
407 {
408 if (GLContext::DebugMode()) {
409 if (GLContext::DebugMode() & GLContext::DebugTrace)
410 printf_stderr("[egl] > %s\n", glFunction);
411 }
412 }
413
414 /*static*/ void
415 GLLibraryEGL::AfterGLCall(const char* glFunction)
416 {
417 if (GLContext::DebugMode() & GLContext::DebugTrace) {
418 printf_stderr("[egl] < %s\n", glFunction);
419 }
420 }
421 #endif
422
423 } /* namespace gl */
424 } /* namespace mozilla */
425

mercurial