2012-03-17 02:24:12 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "GLLibraryEGL.h"
|
|
|
|
|
2016-05-02 18:56:31 +03:00
|
|
|
#include "gfxConfig.h"
|
2012-03-17 02:24:12 +04:00
|
|
|
#include "gfxCrashReporterUtils.h"
|
2020-04-05 06:50:33 +03:00
|
|
|
#include "gfxEnv.h"
|
2015-10-12 06:21:03 +03:00
|
|
|
#include "gfxUtils.h"
|
2012-03-17 02:24:12 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2014-05-31 08:39:16 +04:00
|
|
|
#include "mozilla/Assertions.h"
|
2016-05-27 02:05:13 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2016-07-16 01:12:46 +03:00
|
|
|
#include "mozilla/Tokenizer.h"
|
|
|
|
#include "mozilla/ScopeExit.h"
|
2019-07-26 04:10:23 +03:00
|
|
|
#include "mozilla/StaticPrefs_gfx.h"
|
|
|
|
#include "mozilla/StaticPrefs_webgl.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2017-03-15 15:14:17 +03:00
|
|
|
#include "mozilla/webrender/RenderThread.h"
|
2012-05-15 22:55:50 +04:00
|
|
|
#include "nsDirectoryServiceDefs.h"
|
2012-07-07 08:44:48 +04:00
|
|
|
#include "nsDirectoryServiceUtils.h"
|
2015-07-23 20:11:04 +03:00
|
|
|
#include "nsIGfxInfo.h"
|
2012-07-07 08:44:48 +04:00
|
|
|
#include "nsPrintfCString.h"
|
2014-03-26 17:41:57 +04:00
|
|
|
#ifdef XP_WIN
|
2018-01-09 13:07:50 +03:00
|
|
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
2014-03-26 17:41:57 +04:00
|
|
|
# include "nsWindowsHelpers.h"
|
2018-01-09 13:07:50 +03:00
|
|
|
|
|
|
|
# include <d3d11.h>
|
2014-03-26 17:41:57 +04:00
|
|
|
#endif
|
2015-10-12 06:21:03 +03:00
|
|
|
#include "OGLShaderProgram.h"
|
2012-07-17 19:26:12 +04:00
|
|
|
#include "prenv.h"
|
2017-03-29 17:14:19 +03:00
|
|
|
#include "prsystem.h"
|
2013-02-14 03:26:24 +04:00
|
|
|
#include "GLContext.h"
|
2015-10-12 06:21:03 +03:00
|
|
|
#include "GLContextProvider.h"
|
2020-04-05 06:50:33 +03:00
|
|
|
#include "GLReadTexImageHelper.h"
|
2015-10-12 06:21:03 +03:00
|
|
|
#include "ScopedGLHelpers.h"
|
2018-05-09 16:26:15 +03:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
|
|
# include <gdk/gdk.h>
|
|
|
|
# ifdef MOZ_WAYLAND
|
|
|
|
# include <gdk/gdkwayland.h>
|
|
|
|
# include <dlfcn.h>
|
2019-07-01 09:38:32 +03:00
|
|
|
# include "mozilla/widget/nsWaylandDisplay.h"
|
2018-05-09 16:26:15 +03:00
|
|
|
# endif // MOZ_WIDGET_GTK
|
|
|
|
#endif // MOZ_WAYLAND
|
2012-03-17 02:24:12 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gl {
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// should match the order of EGLExtensions, and be null-terminated.
|
|
|
|
static const char* sEGLLibraryExtensionNames[] = {
|
|
|
|
"EGL_ANDROID_get_native_client_buffer", "EGL_ANGLE_device_creation",
|
|
|
|
"EGL_ANGLE_device_creation_d3d11", "EGL_ANGLE_platform_angle",
|
|
|
|
"EGL_ANGLE_platform_angle_d3d"};
|
2014-05-30 20:15:40 +04:00
|
|
|
|
2012-06-13 01:39:18 +04:00
|
|
|
// should match the order of EGLExtensions, and be null-terminated.
|
2016-06-11 04:37:07 +03:00
|
|
|
static const char* sEGLExtensionNames[] = {
|
2012-06-13 01:39:18 +04:00
|
|
|
"EGL_KHR_image_base",
|
|
|
|
"EGL_KHR_image_pixmap",
|
|
|
|
"EGL_KHR_gl_texture_2D_image",
|
|
|
|
"EGL_ANGLE_surface_d3d_texture_2d_share_handle",
|
|
|
|
"EGL_EXT_create_context_robustness",
|
|
|
|
"EGL_KHR_image",
|
2012-06-13 01:39:43 +04:00
|
|
|
"EGL_KHR_fence_sync",
|
2020-08-24 20:50:48 +03:00
|
|
|
"EGL_KHR_wait_sync",
|
2015-07-10 21:47:48 +03:00
|
|
|
"EGL_ANDROID_native_fence_sync",
|
2015-07-20 02:03:10 +03:00
|
|
|
"EGL_ANDROID_image_crop",
|
2017-02-10 07:31:36 +03:00
|
|
|
"EGL_ANGLE_d3d_share_handle_client_buffer",
|
|
|
|
"EGL_KHR_create_context",
|
2017-05-29 07:15:07 +03:00
|
|
|
"EGL_KHR_stream",
|
|
|
|
"EGL_KHR_stream_consumer_gltexture",
|
|
|
|
"EGL_EXT_device_query",
|
|
|
|
"EGL_NV_stream_consumer_gltexture_yuv",
|
2018-02-24 02:47:41 +03:00
|
|
|
"EGL_ANGLE_stream_producer_d3d_texture",
|
2018-07-04 01:40:58 +03:00
|
|
|
"EGL_KHR_surfaceless_context",
|
2018-09-27 08:31:30 +03:00
|
|
|
"EGL_KHR_create_context_no_error",
|
2020-01-30 13:46:54 +03:00
|
|
|
"EGL_MOZ_create_context_provoking_vertex_dont_care",
|
|
|
|
"EGL_EXT_swap_buffers_with_damage",
|
2020-05-22 21:15:13 +03:00
|
|
|
"EGL_KHR_swap_buffers_with_damage",
|
Bug 1575765 - Implement KHR_partial_update for webrender. r=sotaro,jgilbert
KHR_partial_update allows us to avoid rerendering the entire
backbuffer every frame, and instead only render what has changed on
the current frame, as well as the difference between the current
backbuffer and the current frontbuffer. It works similarily to
EXT_buffer_age, which we already support, with the additional
requirement that we must call eglSetDamageRegion each frame before
rendering to the backbuffer.
Modify GLContextEGL::GetBufferAge() so that it queries the age if
either EXT_buffer_age or KHR_partial_update are available. This will
now automatically be queried by webrender through the
PartialPresentCompositor trait. Add a new function to that trait,
set_buffer_damage_region(), whose RenderCompositorEGL implementation
calls eglSetDamageRegion(). Call this from composite_simple(), once
the damage rect has been calculated but before rendering to the
backbuffer.
Additionally, change both RenderCompositorEGL and
RenderCompositorOGL's implementations of
ShouldDrawPreviousPartialPresentRegions() to unconditionally return
true, rather than checking for the existence of EXT_buffer_age (or
adding a new check for KHR_partial_update). The lack of these
extensions does not mean that webrender is able to skip rendering
previous frames' damage. Rather the opposite, it means we cannot
render *only* the previous frames' damage, and must instead always
render the entire buffer.
Differential Revision: https://phabricator.services.mozilla.com/D91203
2020-10-02 13:23:56 +03:00
|
|
|
"EGL_EXT_buffer_age",
|
|
|
|
"EGL_KHR_partial_update"};
|
2012-06-13 01:39:18 +04:00
|
|
|
|
2019-02-20 02:43:39 +03:00
|
|
|
PRLibrary* LoadApitraceLibrary() {
|
|
|
|
const char* path = nullptr;
|
|
|
|
|
|
|
|
#ifdef ANDROID
|
|
|
|
// We only need to explicitly dlopen egltrace
|
|
|
|
// on android as we can use LD_PRELOAD or other tricks
|
|
|
|
// on other platforms. We look for it in /data/local
|
|
|
|
// as that's writeable by all users.
|
|
|
|
path = "/data/local/tmp/egltrace.so";
|
|
|
|
#endif
|
|
|
|
if (!path) return nullptr;
|
2012-05-15 22:55:50 +04:00
|
|
|
|
2015-02-19 00:50:31 +03:00
|
|
|
// Initialization of gfx prefs here is only needed during the unit tests...
|
2019-07-22 05:10:14 +03:00
|
|
|
if (!StaticPrefs::gfx_apitrace_enabled_AtStartup()) {
|
2013-07-30 22:54:29 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2013-07-20 12:48:55 +04:00
|
|
|
static PRLibrary* sApitraceLibrary = nullptr;
|
2012-03-17 02:24:12 +04:00
|
|
|
if (sApitraceLibrary) return sApitraceLibrary;
|
|
|
|
|
2017-07-31 07:28:48 +03:00
|
|
|
nsAutoCString logFile;
|
|
|
|
Preferences::GetCString("gfx.apitrace.logfile", logFile);
|
2012-03-17 02:24:12 +04:00
|
|
|
if (logFile.IsEmpty()) {
|
|
|
|
logFile = "firefox.trace";
|
|
|
|
}
|
|
|
|
|
|
|
|
// The firefox process can't write to /data/local, but it can write
|
|
|
|
// to $GRE_HOME/
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString logPath;
|
2012-03-17 02:24:12 +04:00
|
|
|
logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
|
|
|
|
|
2019-02-20 02:43:39 +03:00
|
|
|
#ifndef XP_WIN // Windows is missing setenv and forbids PR_LoadLibrary.
|
2012-03-17 02:24:12 +04:00
|
|
|
// apitrace uses the TRACE_FILE environment variable to determine where
|
|
|
|
// to log trace output to
|
|
|
|
printf_stderr("Logging GL tracing output to %s", logPath.get());
|
|
|
|
setenv("TRACE_FILE", logPath.get(), false);
|
|
|
|
|
2019-02-20 02:43:39 +03:00
|
|
|
printf_stderr("Attempting load of %s\n", path);
|
|
|
|
sApitraceLibrary = PR_LoadLibrary(path);
|
|
|
|
#endif
|
2012-03-17 02:24:12 +04:00
|
|
|
|
|
|
|
return sApitraceLibrary;
|
|
|
|
}
|
|
|
|
|
2012-07-07 08:44:48 +04:00
|
|
|
#ifdef XP_WIN
|
|
|
|
// see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
|
|
|
|
static PRLibrary* LoadLibraryForEGLOnWindows(const nsAString& filename) {
|
2017-12-16 18:13:30 +03:00
|
|
|
nsAutoString path(gfx::gfxVars::GREDirectory());
|
2017-03-29 17:14:19 +03:00
|
|
|
path.Append(PR_GetDirectorySeparator());
|
2017-12-16 18:13:30 +03:00
|
|
|
path.Append(filename);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-03-29 17:14:19 +03:00
|
|
|
PRLibSpec lspec;
|
2017-12-16 18:13:30 +03:00
|
|
|
lspec.type = PR_LibSpec_PathnameU;
|
|
|
|
lspec.value.pathname_u = path.get();
|
2017-03-29 17:14:19 +03:00
|
|
|
return PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL);
|
2012-07-07 08:44:48 +04:00
|
|
|
}
|
2015-07-23 20:11:04 +03:00
|
|
|
|
2012-07-07 08:44:48 +04:00
|
|
|
#endif // XP_WIN
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
static std::shared_ptr<EglDisplay> GetAndInitDisplay(GLLibraryEGL& egl,
|
|
|
|
void* displayType) {
|
|
|
|
const auto display = egl.fGetDisplay(displayType);
|
|
|
|
if (!display) return nullptr;
|
|
|
|
return EglDisplay::Create(egl, display, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::shared_ptr<EglDisplay> GetAndInitWARPDisplay(GLLibraryEGL& egl,
|
|
|
|
void* displayType) {
|
|
|
|
const EGLint attrib_list[] = {LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
|
|
|
|
LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
|
|
|
|
// Requires:
|
|
|
|
LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
|
|
|
LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
|
|
|
LOCAL_EGL_NONE};
|
|
|
|
const EGLDisplay display = egl.fGetPlatformDisplayEXT(
|
2015-07-23 20:11:04 +03:00
|
|
|
LOCAL_EGL_PLATFORM_ANGLE_ANGLE, displayType, attrib_list);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-04-06 23:47:25 +03:00
|
|
|
if (display == EGL_NO_DISPLAY) {
|
|
|
|
const EGLint err = egl.fGetError();
|
|
|
|
if (err != LOCAL_EGL_SUCCESS) {
|
2016-06-16 18:15:29 +03:00
|
|
|
gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
|
2016-05-06 17:19:31 +03:00
|
|
|
MOZ_CRASH("GFX: Unexpected GL error.");
|
2016-04-06 23:47:25 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-07-23 20:11:04 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
return EglDisplay::Create(egl, display, true);
|
2015-07-23 20:11:04 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
|
|
|
|
ID3D11Device* const d3d11Device) {
|
|
|
|
EGLDeviceEXT eglDevice =
|
|
|
|
fCreateDeviceANGLE(LOCAL_EGL_D3D11_DEVICE_ANGLE, d3d11Device, nullptr);
|
2018-01-09 13:07:50 +03:00
|
|
|
if (!eglDevice) {
|
|
|
|
gfxCriticalNote << "Failed to get EGLDeviceEXT of D3D11Device";
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
2018-01-09 13:07:50 +03:00
|
|
|
}
|
|
|
|
// Create an EGLDisplay using the EGLDevice
|
2020-08-07 10:14:46 +03:00
|
|
|
const EGLint attrib_list[] = {LOCAL_EGL_NONE};
|
|
|
|
const auto display = fGetPlatformDisplayEXT(LOCAL_EGL_PLATFORM_DEVICE_EXT,
|
|
|
|
eglDevice, attrib_list);
|
2018-01-09 13:07:50 +03:00
|
|
|
if (!display) {
|
|
|
|
gfxCriticalNote << "Failed to get EGLDisplay of D3D11Device";
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
2018-01-09 13:07:50 +03:00
|
|
|
}
|
2017-11-29 07:13:40 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
if (!display) {
|
|
|
|
const EGLint err = fGetError();
|
2017-11-29 07:13:40 +03:00
|
|
|
if (err != LOCAL_EGL_SUCCESS) {
|
|
|
|
gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
|
|
|
|
MOZ_CRASH("GFX: Unexpected GL error.");
|
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-11-29 07:13:40 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
const auto ret = EglDisplay::Create(*this, display, false);
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
const EGLint err = fGetError();
|
2018-03-22 04:57:55 +03:00
|
|
|
if (err != LOCAL_EGL_SUCCESS) {
|
|
|
|
gfxCriticalError()
|
|
|
|
<< "Failed to initialize EGLDisplay for WebRender error: "
|
|
|
|
<< gfx::hexa(err);
|
2018-01-09 13:07:50 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
return ret;
|
2017-11-29 07:13:40 +03:00
|
|
|
}
|
|
|
|
|
2016-06-11 05:01:00 +03:00
|
|
|
static bool IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|
|
|
nsACString* const out_failureId) {
|
2017-03-15 15:14:17 +03:00
|
|
|
if (wr::RenderThread::IsInRenderThread()) {
|
2017-01-13 23:16:52 +03:00
|
|
|
// We can only enter here with WebRender, so assert that this is a
|
|
|
|
// WebRender-enabled build.
|
2016-12-21 04:40:49 +03:00
|
|
|
return true;
|
|
|
|
}
|
2015-07-23 20:11:04 +03:00
|
|
|
int32_t angleSupport;
|
2016-06-06 20:37:59 +03:00
|
|
|
nsCString failureId;
|
2015-10-12 06:21:03 +03:00
|
|
|
gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_ANGLE,
|
|
|
|
failureId, &angleSupport);
|
2016-07-28 00:14:19 +03:00
|
|
|
if (failureId.IsEmpty() && angleSupport != nsIGfxInfo::FEATURE_STATUS_OK) {
|
|
|
|
// This shouldn't happen, if we see this it's because we've missed
|
|
|
|
// some failure paths
|
2020-07-01 11:29:29 +03:00
|
|
|
failureId = "FEATURE_FAILURE_ACCL_ANGLE_NOT_OK"_ns;
|
2016-07-28 00:14:19 +03:00
|
|
|
}
|
|
|
|
if (out_failureId->IsEmpty()) {
|
2016-06-11 05:01:00 +03:00
|
|
|
*out_failureId = failureId;
|
2016-06-06 23:52:42 +03:00
|
|
|
}
|
2015-07-23 20:11:04 +03:00
|
|
|
return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
|
|
|
|
}
|
|
|
|
|
2017-05-24 10:20:02 +03:00
|
|
|
class AngleErrorReporting {
|
2016-07-16 01:12:46 +03:00
|
|
|
public:
|
2018-04-13 16:01:28 +03:00
|
|
|
AngleErrorReporting() : mFailureId(nullptr) {
|
|
|
|
// No static constructor
|
2016-07-16 01:12:46 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-07-16 01:12:46 +03:00
|
|
|
void SetFailureId(nsACString* const aFailureId) { mFailureId = aFailureId; }
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-05-24 10:20:02 +03:00
|
|
|
void logError(const char* errorMessage) {
|
2016-07-24 18:11:09 +03:00
|
|
|
if (!mFailureId) {
|
2018-11-30 13:46:48 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-16 01:12:46 +03:00
|
|
|
nsCString str(errorMessage);
|
|
|
|
Tokenizer tokenizer(str);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-07-16 01:12:46 +03:00
|
|
|
// Parse "ANGLE Display::initialize error " << error.getID() << ": "
|
|
|
|
// << error.getMessage()
|
|
|
|
nsCString currWord;
|
|
|
|
Tokenizer::Token intToken;
|
|
|
|
if (tokenizer.CheckWord("ANGLE") && tokenizer.CheckWhite() &&
|
|
|
|
tokenizer.CheckWord("Display") && tokenizer.CheckChar(':') &&
|
|
|
|
tokenizer.CheckChar(':') && tokenizer.CheckWord("initialize") &&
|
|
|
|
tokenizer.CheckWhite() && tokenizer.CheckWord("error") &&
|
|
|
|
tokenizer.CheckWhite() &&
|
|
|
|
tokenizer.Check(Tokenizer::TOKEN_INTEGER, intToken)) {
|
|
|
|
*mFailureId = "FAILURE_ID_ANGLE_ID_";
|
|
|
|
mFailureId->AppendPrintf("%" PRIu64, intToken.AsInteger());
|
2018-11-30 13:46:48 +03:00
|
|
|
} else {
|
2016-07-16 01:12:46 +03:00
|
|
|
*mFailureId = "FAILURE_ID_ANGLE_UNKNOWN";
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2016-07-16 01:12:46 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
nsACString* mFailureId;
|
|
|
|
};
|
|
|
|
|
|
|
|
AngleErrorReporting gAngleErrorReporter;
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
static std::shared_ptr<EglDisplay> GetAndInitDisplayForAccelANGLE(
|
2016-07-16 01:12:46 +03:00
|
|
|
GLLibraryEGL& egl, nsACString* const out_failureId) {
|
2020-08-07 10:14:46 +03:00
|
|
|
MOZ_RELEASE_ASSERT(!wr::RenderThread::IsInRenderThread());
|
2017-03-29 17:14:19 +03:00
|
|
|
|
2020-04-05 06:50:33 +03:00
|
|
|
gfx::FeatureState& d3d11ANGLE =
|
|
|
|
gfx::gfxConfig::GetFeature(gfx::Feature::D3D11_HW_ANGLE);
|
2016-05-02 18:56:31 +03:00
|
|
|
|
2019-06-29 00:56:43 +03:00
|
|
|
if (!StaticPrefs::webgl_angle_try_d3d11()) {
|
2016-06-03 21:54:56 +03:00
|
|
|
d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref",
|
2020-07-01 11:29:29 +03:00
|
|
|
"FAILURE_ID_ANGLE_PREF"_ns);
|
2019-06-29 00:56:43 +03:00
|
|
|
}
|
|
|
|
if (StaticPrefs::webgl_angle_force_d3d11()) {
|
2016-05-02 18:56:31 +03:00
|
|
|
d3d11ANGLE.UserForceEnable(
|
|
|
|
"User force-enabled D3D11 ANGLE on disabled hardware");
|
2019-06-29 00:56:43 +03:00
|
|
|
}
|
2016-07-16 01:12:46 +03:00
|
|
|
gAngleErrorReporter.SetFailureId(out_failureId);
|
|
|
|
|
|
|
|
auto guardShutdown = mozilla::MakeScopeExit([&] {
|
|
|
|
gAngleErrorReporter.SetFailureId(nullptr);
|
|
|
|
// NOTE: Ideally we should be calling ANGLEPlatformShutdown after the
|
|
|
|
// ANGLE display is destroyed. However gAngleErrorReporter
|
|
|
|
// will live longer than the ANGLE display so we're fine.
|
|
|
|
});
|
|
|
|
|
2020-04-05 06:50:33 +03:00
|
|
|
if (gfx::gfxConfig::IsForcedOnByUser(gfx::Feature::D3D11_HW_ANGLE)) {
|
2019-08-22 18:15:08 +03:00
|
|
|
return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
|
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
std::shared_ptr<EglDisplay> ret;
|
2016-05-02 18:56:31 +03:00
|
|
|
if (d3d11ANGLE.IsEnabled()) {
|
2019-08-22 18:15:08 +03:00
|
|
|
ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
|
2016-01-22 05:47:29 +03:00
|
|
|
}
|
|
|
|
|
2019-08-22 18:15:08 +03:00
|
|
|
if (!ret) {
|
|
|
|
ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY);
|
2016-01-22 05:47:29 +03:00
|
|
|
}
|
|
|
|
|
2016-08-04 00:28:26 +03:00
|
|
|
if (!ret && out_failureId->IsEmpty()) {
|
2020-07-01 11:29:29 +03:00
|
|
|
*out_failureId = "FEATURE_FAILURE_ACCL_ANGLE_NO_DISP"_ns;
|
2016-07-28 00:14:19 +03:00
|
|
|
}
|
|
|
|
|
2016-01-22 05:47:29 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
// -
|
|
|
|
|
|
|
|
#if defined(XP_UNIX)
|
|
|
|
# define GLES2_LIB "libGLESv2.so"
|
|
|
|
# define GLES2_LIB2 "libGLESv2.so.2"
|
|
|
|
#elif defined(XP_WIN)
|
|
|
|
# define GLES2_LIB "libGLESv2.dll"
|
|
|
|
#else
|
|
|
|
# error "Platform not recognized"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Maybe<SymbolLoader> GLLibraryEGL::GetSymbolLoader() const {
|
|
|
|
auto ret = SymbolLoader(mSymbols.fGetProcAddress);
|
|
|
|
ret.mLib = mGLLibrary;
|
|
|
|
return Some(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
2020-08-07 10:14:46 +03:00
|
|
|
RefPtr<GLLibraryEGL> GLLibraryEGL::Create(nsACString* const out_failureId) {
|
|
|
|
RefPtr<GLLibraryEGL> ret = new GLLibraryEGL;
|
|
|
|
if (!ret->Init(out_failureId)) {
|
|
|
|
return nullptr;
|
2018-06-04 05:09:29 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
return ret;
|
2019-02-23 00:17:28 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
bool GLLibraryEGL::Init(nsACString* const out_failureId) {
|
|
|
|
MOZ_RELEASE_ASSERT(!mSymbols.fTerminate);
|
2012-03-17 02:24:12 +04:00
|
|
|
|
|
|
|
mozilla::ScopedGfxFeatureReporter reporter("EGL");
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (!mEGLLibrary) {
|
2012-07-07 08:44:48 +04:00
|
|
|
// On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul
|
2012-05-15 22:55:50 +04:00
|
|
|
// and we should look for them there. We have to load the libs in this
|
2012-07-07 08:44:48 +04:00
|
|
|
// order, because libEGL.dll depends on libGLESv2.dll which depends on the
|
|
|
|
// DXSDK libraries. This matters especially for WebRT apps which are in a
|
|
|
|
// different directory. See bug 760323 and bug 749459
|
2012-05-15 22:55:50 +04:00
|
|
|
|
2014-05-03 02:31:05 +04:00
|
|
|
// Also note that we intentionally leak the libs we load.
|
|
|
|
|
|
|
|
do {
|
2016-11-15 01:02:49 +03:00
|
|
|
// Windows 8.1+ has d3dcompiler_47.dll in the system directory.
|
2014-05-03 02:31:05 +04:00
|
|
|
// Try it first. Note that _46 will never be in the system
|
2016-11-15 01:02:49 +03:00
|
|
|
// directory. So there is no point trying _46 in the system
|
|
|
|
// directory.
|
2014-05-03 02:31:05 +04:00
|
|
|
|
|
|
|
if (LoadLibrarySystem32(L"d3dcompiler_47.dll")) break;
|
|
|
|
|
|
|
|
# ifdef MOZ_D3DCOMPILER_VISTA_DLL
|
2020-07-01 11:34:12 +03:00
|
|
|
if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING_FROM_CSTRING(
|
|
|
|
MOZ_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL))))
|
2014-05-03 02:31:05 +04:00
|
|
|
break;
|
2012-07-07 08:44:48 +04:00
|
|
|
# endif
|
2014-05-03 02:31:05 +04:00
|
|
|
|
|
|
|
MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
|
|
|
|
} while (false);
|
2012-05-15 22:55:50 +04:00
|
|
|
|
2020-07-01 11:29:29 +03:00
|
|
|
mGLLibrary = LoadLibraryForEGLOnWindows(u"libGLESv2.dll"_ns);
|
2012-05-15 22:55:50 +04:00
|
|
|
|
2020-07-01 11:29:29 +03:00
|
|
|
mEGLLibrary = LoadLibraryForEGLOnWindows(u"libEGL.dll"_ns);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-08-12 20:04:36 +04:00
|
|
|
|
2012-05-15 22:55:50 +04:00
|
|
|
#else // !Windows
|
|
|
|
|
|
|
|
// On non-Windows (Android) we use system copies of libEGL. We look for
|
|
|
|
// the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
|
|
|
|
|
|
|
|
# if defined(ANDROID)
|
2012-03-17 02:24:12 +04:00
|
|
|
if (!mEGLLibrary) mEGLLibrary = LoadApitraceLibrary();
|
2012-05-15 22:55:50 +04:00
|
|
|
# endif
|
2012-03-17 02:24:12 +04:00
|
|
|
|
2012-05-15 22:55:50 +04:00
|
|
|
if (!mEGLLibrary) {
|
|
|
|
mEGLLibrary = PR_LoadLibrary("libEGL.so");
|
|
|
|
}
|
2012-03-17 02:24:12 +04:00
|
|
|
# if defined(XP_UNIX)
|
2012-05-15 22:55:50 +04:00
|
|
|
if (!mEGLLibrary) {
|
|
|
|
mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
|
2012-03-17 02:24:12 +04:00
|
|
|
}
|
2012-05-15 22:55:50 +04:00
|
|
|
# endif
|
2012-03-17 02:24:12 +04:00
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
# ifdef APITRACE_LIB
|
|
|
|
if (!mGLLibrary) {
|
|
|
|
mGLLibrary = PR_LoadLibrary(APITRACE_LIB);
|
2012-03-17 02:24:12 +04:00
|
|
|
}
|
2019-02-23 00:17:28 +03:00
|
|
|
# endif
|
|
|
|
|
|
|
|
if (!mGLLibrary) {
|
|
|
|
mGLLibrary = PR_LoadLibrary(GLES2_LIB);
|
|
|
|
}
|
|
|
|
|
|
|
|
# ifdef GLES2_LIB2
|
|
|
|
if (!mGLLibrary) {
|
|
|
|
mGLLibrary = PR_LoadLibrary(GLES2_LIB2);
|
|
|
|
}
|
|
|
|
# endif
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-05-15 22:55:50 +04:00
|
|
|
#endif // !Windows
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
if (!mEGLLibrary || !mGLLibrary) {
|
|
|
|
NS_WARNING("Couldn't load EGL LIB.");
|
2020-07-01 11:29:29 +03:00
|
|
|
*out_failureId = "FEATURE_FAILURE_EGL_LOAD_3"_ns;
|
2012-03-17 02:24:12 +04:00
|
|
|
return false;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
#define SYMBOL(X) \
|
|
|
|
{ \
|
|
|
|
(PRFuncPtr*)&mSymbols.f##X, { \
|
|
|
|
{ "egl" #X } \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
#define END_OF_SYMBOLS \
|
|
|
|
{ \
|
|
|
|
nullptr, {} \
|
|
|
|
}
|
|
|
|
|
|
|
|
SymLoadStruct earlySymbols[] = {SYMBOL(GetDisplay),
|
|
|
|
SYMBOL(Terminate),
|
|
|
|
SYMBOL(GetCurrentSurface),
|
|
|
|
SYMBOL(GetCurrentContext),
|
|
|
|
SYMBOL(MakeCurrent),
|
|
|
|
SYMBOL(DestroyContext),
|
|
|
|
SYMBOL(CreateContext),
|
|
|
|
SYMBOL(DestroySurface),
|
|
|
|
SYMBOL(CreateWindowSurface),
|
|
|
|
SYMBOL(CreatePbufferSurface),
|
|
|
|
SYMBOL(CreatePbufferFromClientBuffer),
|
|
|
|
SYMBOL(CreatePixmapSurface),
|
|
|
|
SYMBOL(BindAPI),
|
|
|
|
SYMBOL(Initialize),
|
|
|
|
SYMBOL(ChooseConfig),
|
|
|
|
SYMBOL(GetError),
|
|
|
|
SYMBOL(GetConfigs),
|
|
|
|
SYMBOL(GetConfigAttrib),
|
|
|
|
SYMBOL(WaitNative),
|
|
|
|
SYMBOL(GetProcAddress),
|
|
|
|
SYMBOL(SwapBuffers),
|
|
|
|
SYMBOL(CopyBuffers),
|
|
|
|
SYMBOL(QueryString),
|
|
|
|
SYMBOL(QueryContext),
|
|
|
|
SYMBOL(BindTexImage),
|
|
|
|
SYMBOL(ReleaseTexImage),
|
|
|
|
SYMBOL(SwapInterval),
|
|
|
|
SYMBOL(QuerySurface),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
|
|
|
|
{
|
|
|
|
const SymbolLoader libLoader(*mEGLLibrary);
|
|
|
|
if (!libLoader.LoadSymbols(earlySymbols)) {
|
|
|
|
NS_WARNING(
|
|
|
|
"Couldn't find required entry points in EGL library (early init)");
|
2020-07-01 11:29:29 +03:00
|
|
|
*out_failureId = "FEATURE_FAILURE_EGL_SYM"_ns;
|
2019-02-23 00:17:28 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-04 03:49:49 +03:00
|
|
|
{
|
|
|
|
const char internalFuncName[] =
|
|
|
|
"_Z35eglQueryStringImplementationANDROIDPvi";
|
|
|
|
const auto& internalFunc =
|
|
|
|
PR_FindFunctionSymbol(mEGLLibrary, internalFuncName);
|
|
|
|
if (internalFunc) {
|
|
|
|
*(PRFuncPtr*)&mSymbols.fQueryString = internalFunc;
|
|
|
|
}
|
|
|
|
}
|
2020-08-07 00:19:32 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// -
|
|
|
|
|
|
|
|
InitLibExtensions();
|
|
|
|
|
|
|
|
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
|
2020-08-07 02:36:33 +03:00
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
|
|
|
|
if (pfnLoader.LoadSymbols(symbols)) return true;
|
2017-03-04 03:49:49 +03:00
|
|
|
|
2019-02-23 00:17:28 +03:00
|
|
|
ClearSymbols(symbols);
|
|
|
|
return false;
|
|
|
|
};
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-03-04 07:38:57 +03:00
|
|
|
// Check the ANGLE support the system has
|
2020-08-07 10:14:46 +03:00
|
|
|
mIsANGLE = IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-11-13 00:41:45 +03:00
|
|
|
// Client exts are ready. (But not display exts!)
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-03-04 07:38:57 +03:00
|
|
|
if (mIsANGLE) {
|
2020-08-07 10:14:46 +03:00
|
|
|
MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
|
2019-02-23 00:17:28 +03:00
|
|
|
const SymLoadStruct angleSymbols[] = {SYMBOL(GetPlatformDisplayEXT),
|
|
|
|
END_OF_SYMBOLS};
|
2017-03-04 03:49:49 +03:00
|
|
|
if (!fnLoadSymbols(angleSymbols)) {
|
2012-06-13 01:39:18 +04:00
|
|
|
gfxCriticalError() << "Failed to load ANGLE symbols!";
|
2017-03-04 03:49:49 +03:00
|
|
|
return false;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
|
2019-02-23 00:17:28 +03:00
|
|
|
const SymLoadStruct createDeviceSymbols[] = {
|
2017-03-04 03:49:49 +03:00
|
|
|
SYMBOL(CreateDeviceANGLE), SYMBOL(ReleaseDeviceANGLE), END_OF_SYMBOLS};
|
2017-03-04 07:38:57 +03:00
|
|
|
if (!fnLoadSymbols(createDeviceSymbols)) {
|
2018-11-30 13:46:48 +03:00
|
|
|
NS_ERROR(
|
2012-06-13 01:39:18 +04:00
|
|
|
"EGL supports ANGLE_device_creation without exposing its functions!");
|
2020-08-07 10:14:46 +03:00
|
|
|
MarkExtensionUnsupported(EGLLibExtension::ANGLE_device_creation);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// ANDROID_get_native_client_buffer isn't necessarily enumerated in lib exts,
|
|
|
|
// but it is one.
|
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(GetNativeClientBufferANDROID),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
if (fnLoadSymbols(symbols)) {
|
|
|
|
mAvailableExtensions[UnderlyingValue(
|
|
|
|
EGLLibExtension::ANDROID_get_native_client_buffer)] = true;
|
2020-08-07 02:36:33 +03:00
|
|
|
}
|
2020-08-07 01:53:53 +03:00
|
|
|
}
|
2020-08-07 02:36:33 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// -
|
|
|
|
// Load possible display ext symbols.
|
2020-08-07 02:36:33 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(QuerySurfacePointerANGLE),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {
|
2017-03-04 03:49:49 +03:00
|
|
|
SYMBOL(CreateSyncKHR), SYMBOL(DestroySyncKHR),
|
2018-01-09 13:07:50 +03:00
|
|
|
SYMBOL(ClientWaitSyncKHR), SYMBOL(GetSyncAttribKHR), END_OF_SYMBOLS};
|
2020-08-07 10:14:46 +03:00
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(CreateImageKHR),
|
|
|
|
SYMBOL(DestroyImageKHR), END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-24 20:50:48 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(WaitSyncKHR), END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(DupNativeFenceFDANDROID),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(CreateStreamKHR),
|
|
|
|
SYMBOL(DestroyStreamKHR),
|
|
|
|
SYMBOL(QueryStreamKHR), END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(StreamConsumerGLTextureExternalKHR),
|
|
|
|
SYMBOL(StreamConsumerAcquireKHR),
|
|
|
|
SYMBOL(StreamConsumerReleaseKHR),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
2020-08-07 00:19:32 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {SYMBOL(QueryDisplayAttribEXT),
|
|
|
|
SYMBOL(QueryDeviceAttribEXT),
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
2020-08-07 02:36:33 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {
|
2017-05-29 07:15:07 +03:00
|
|
|
SYMBOL(StreamConsumerGLTextureExternalAttribsNV), END_OF_SYMBOLS};
|
2020-08-07 10:14:46 +03:00
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {
|
2018-01-09 13:07:50 +03:00
|
|
|
SYMBOL(CreateStreamProducerD3DTextureANGLE),
|
2018-02-24 02:47:41 +03:00
|
|
|
SYMBOL(StreamPostD3DTextureANGLE), END_OF_SYMBOLS};
|
2020-08-07 10:14:46 +03:00
|
|
|
(void)fnLoadSymbols(symbols);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
2020-01-30 13:46:54 +03:00
|
|
|
const SymLoadStruct symbols[] = {
|
|
|
|
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
|
|
|
|
{{"eglSwapBuffersWithDamageEXT"}}},
|
|
|
|
END_OF_SYMBOLS};
|
2020-08-07 10:14:46 +03:00
|
|
|
(void)fnLoadSymbols(symbols);
|
2020-01-30 13:46:54 +03:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
{
|
2020-01-30 13:46:54 +03:00
|
|
|
const SymLoadStruct symbols[] = {
|
|
|
|
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
|
|
|
|
{{"eglSwapBuffersWithDamageKHR"}}},
|
|
|
|
END_OF_SYMBOLS};
|
2020-08-07 10:14:46 +03:00
|
|
|
(void)fnLoadSymbols(symbols);
|
2020-08-07 01:53:53 +03:00
|
|
|
}
|
Bug 1575765 - Implement KHR_partial_update for webrender. r=sotaro,jgilbert
KHR_partial_update allows us to avoid rerendering the entire
backbuffer every frame, and instead only render what has changed on
the current frame, as well as the difference between the current
backbuffer and the current frontbuffer. It works similarily to
EXT_buffer_age, which we already support, with the additional
requirement that we must call eglSetDamageRegion each frame before
rendering to the backbuffer.
Modify GLContextEGL::GetBufferAge() so that it queries the age if
either EXT_buffer_age or KHR_partial_update are available. This will
now automatically be queried by webrender through the
PartialPresentCompositor trait. Add a new function to that trait,
set_buffer_damage_region(), whose RenderCompositorEGL implementation
calls eglSetDamageRegion(). Call this from composite_simple(), once
the damage rect has been calculated but before rendering to the
backbuffer.
Additionally, change both RenderCompositorEGL and
RenderCompositorOGL's implementations of
ShouldDrawPreviousPartialPresentRegions() to unconditionally return
true, rather than checking for the existence of EXT_buffer_age (or
adding a new check for KHR_partial_update). The lack of these
extensions does not mean that webrender is able to skip rendering
previous frames' damage. Rather the opposite, it means we cannot
render *only* the previous frames' damage, and must instead always
render the entire buffer.
Differential Revision: https://phabricator.services.mozilla.com/D91203
2020-10-02 13:23:56 +03:00
|
|
|
{
|
|
|
|
const SymLoadStruct symbols[] = {
|
|
|
|
{(PRFuncPtr*)&mSymbols.fSetDamageRegion, {{"eglSetDamageRegionKHR"}}},
|
|
|
|
END_OF_SYMBOLS};
|
|
|
|
(void)fnLoadSymbols(symbols);
|
|
|
|
}
|
2020-08-07 01:53:53 +03:00
|
|
|
|
2020-08-07 02:36:33 +03:00
|
|
|
return true;
|
2020-08-07 01:53:53 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// -
|
2020-08-07 01:53:53 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
template <size_t N>
|
|
|
|
static void MarkExtensions(const char* rawExtString, bool shouldDumpExts,
|
|
|
|
const char* extType, const char* const (&names)[N],
|
|
|
|
std::bitset<N>* const out) {
|
|
|
|
MOZ_ASSERT(rawExtString);
|
|
|
|
|
|
|
|
const nsDependentCString extString(rawExtString);
|
|
|
|
|
|
|
|
std::vector<nsCString> extList;
|
|
|
|
SplitByChar(extString, ' ', &extList);
|
|
|
|
|
|
|
|
if (shouldDumpExts) {
|
|
|
|
printf_stderr("%u EGL %s extensions: (*: recognized)\n",
|
|
|
|
(uint32_t)extList.size(), extType);
|
|
|
|
}
|
|
|
|
|
|
|
|
MarkBitfieldByStrings(extList, shouldDumpExts, names, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -
|
|
|
|
|
|
|
|
// static
|
|
|
|
std::shared_ptr<EglDisplay> EglDisplay::Create(GLLibraryEGL& lib,
|
|
|
|
const EGLDisplay display,
|
|
|
|
const bool isWarp) {
|
|
|
|
// Retrieve the EglDisplay if it already exists
|
|
|
|
{
|
|
|
|
const auto itr = lib.mActiveDisplays.find(display);
|
|
|
|
if (itr != lib.mActiveDisplays.end()) {
|
|
|
|
const auto ret = itr->second.lock();
|
|
|
|
if (ret) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lib.fInitialize(display, nullptr, nullptr)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
const auto ret =
|
|
|
|
std::make_shared<EglDisplay>(PrivateUseOnly{}, lib, display, isWarp);
|
|
|
|
lib.mActiveDisplays.insert({display, ret});
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
EglDisplay::EglDisplay(const PrivateUseOnly&, GLLibraryEGL& lib,
|
|
|
|
const EGLDisplay disp, const bool isWarp)
|
|
|
|
: mLib(&lib), mDisplay(disp), mIsWARP(isWarp) {
|
|
|
|
const bool shouldDumpExts = GLContext::ShouldDumpExts();
|
|
|
|
|
|
|
|
auto rawExtString =
|
|
|
|
(const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_EXTENSIONS);
|
|
|
|
if (!rawExtString) {
|
|
|
|
NS_WARNING("Failed to query EGL display extensions!.");
|
|
|
|
rawExtString = "";
|
|
|
|
}
|
|
|
|
MarkExtensions(rawExtString, shouldDumpExts, "display", sEGLExtensionNames,
|
|
|
|
&mAvailableExtensions);
|
|
|
|
|
|
|
|
// -
|
|
|
|
|
|
|
|
if (!HasKHRImageBase()) {
|
|
|
|
MarkExtensionUnsupported(EGLExtension::KHR_image_pixmap);
|
2012-03-17 02:24:12 +04:00
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
|
|
|
|
if (IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
|
|
|
|
const auto vendor =
|
|
|
|
(const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_VENDOR);
|
|
|
|
|
|
|
|
// Bug 1464610: Mali T720 (Amazon Fire 8 HD) claims to support this
|
|
|
|
// extension, but if you actually eglMakeCurrent() with EGL_NO_SURFACE, it
|
|
|
|
// fails to render anything when a real surface is provided later on. We
|
|
|
|
// only have the EGL vendor available here, so just avoid using this
|
|
|
|
// extension on all Mali devices.
|
|
|
|
if (strcmp(vendor, "ARM") == 0) {
|
|
|
|
MarkExtensionUnsupported(EGLExtension::KHR_surfaceless_context);
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2020-08-25 17:37:23 +03:00
|
|
|
|
|
|
|
// ANDROID_native_fence_sync isn't necessarily enumerated in display ext,
|
|
|
|
// but it is one.
|
|
|
|
if (mLib->mSymbols.fDupNativeFenceFDANDROID) {
|
|
|
|
mAvailableExtensions[UnderlyingValue(
|
|
|
|
EGLExtension::ANDROID_native_fence_sync)] = true;
|
|
|
|
}
|
2020-08-07 10:14:46 +03:00
|
|
|
}
|
2020-07-29 05:33:54 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
EglDisplay::~EglDisplay() {
|
|
|
|
fTerminate();
|
|
|
|
mLib->mActiveDisplays.erase(mDisplay);
|
2020-07-29 05:33:54 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
// -
|
|
|
|
|
|
|
|
std::shared_ptr<EglDisplay> GLLibraryEGL::DefaultDisplay(
|
|
|
|
nsACString* const out_failureId) {
|
|
|
|
auto ret = mDefaultDisplay.lock();
|
|
|
|
if (ret) return ret;
|
|
|
|
|
|
|
|
ret = CreateDisplay(false, out_failureId);
|
|
|
|
mDefaultDisplay = ret;
|
|
|
|
return ret;
|
2012-03-17 02:24:12 +04:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
|
|
|
|
const bool forceAccel, nsACString* const out_failureId) {
|
|
|
|
const nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
2012-03-17 02:24:12 +04:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
std::shared_ptr<EglDisplay> ret;
|
2012-06-13 01:39:43 +04:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
if (IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d)) {
|
2013-02-14 03:26:24 +04:00
|
|
|
nsCString accelAngleFailureId;
|
2018-04-04 03:38:42 +03:00
|
|
|
bool accelAngleSupport =
|
2013-02-14 03:26:24 +04:00
|
|
|
IsAccelAngleSupported(gfxInfo, &accelAngleFailureId);
|
2017-03-04 03:49:49 +03:00
|
|
|
bool shouldTryAccel = forceAccel || accelAngleSupport;
|
2013-02-14 03:26:24 +04:00
|
|
|
bool shouldTryWARP = !forceAccel; // Only if ANGLE not supported or fails
|
|
|
|
|
2014-06-08 17:18:53 +04:00
|
|
|
// If WARP preferred, will override ANGLE support
|
2019-06-29 00:56:43 +03:00
|
|
|
if (StaticPrefs::webgl_angle_force_warp()) {
|
2018-04-04 03:38:42 +03:00
|
|
|
shouldTryWARP = true;
|
|
|
|
shouldTryAccel = false;
|
2014-06-08 17:18:53 +04:00
|
|
|
if (accelAngleFailureId.IsEmpty()) {
|
2020-07-01 11:29:29 +03:00
|
|
|
accelAngleFailureId = "FEATURE_FAILURE_FORCE_WARP"_ns;
|
2014-06-08 17:18:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-29 07:15:07 +03:00
|
|
|
// Hardware accelerated ANGLE path (supported or force accel)
|
|
|
|
if (shouldTryAccel) {
|
2020-08-07 10:14:46 +03:00
|
|
|
ret = GetAndInitDisplayForAccelANGLE(*this, out_failureId);
|
2017-05-29 07:15:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Report the acceleration status to telemetry
|
2020-08-07 10:14:46 +03:00
|
|
|
if (!ret) {
|
2017-05-29 07:15:07 +03:00
|
|
|
if (accelAngleFailureId.IsEmpty()) {
|
2020-07-01 11:29:29 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
|
|
|
|
"FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN"_ns);
|
2017-05-29 07:15:07 +03:00
|
|
|
} else {
|
|
|
|
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
|
|
|
|
accelAngleFailureId);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-05-29 07:15:07 +03:00
|
|
|
} else {
|
|
|
|
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
|
2020-07-01 11:29:29 +03:00
|
|
|
"SUCCESS"_ns);
|
2017-05-29 07:15:07 +03:00
|
|
|
}
|
|
|
|
|
2018-06-29 00:01:03 +03:00
|
|
|
// Fallback to a WARP display if ANGLE fails, or if WARP is forced
|
2020-08-07 10:14:46 +03:00
|
|
|
if (!ret && shouldTryWARP) {
|
|
|
|
ret = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
|
|
|
|
if (!ret) {
|
2018-06-29 00:01:03 +03:00
|
|
|
if (out_failureId->IsEmpty()) {
|
2020-07-01 11:29:29 +03:00
|
|
|
*out_failureId = "FEATURE_FAILURE_WARP_FALLBACK"_ns;
|
2018-06-29 00:01:03 +03:00
|
|
|
}
|
2018-04-04 03:38:42 +03:00
|
|
|
NS_ERROR("Fallback WARP context failed to initialize.");
|
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2018-06-29 00:01:03 +03:00
|
|
|
}
|
2018-06-04 05:09:52 +03:00
|
|
|
} else {
|
2018-04-04 03:38:42 +03:00
|
|
|
void* nativeDisplay = EGL_DEFAULT_DISPLAY;
|
2018-05-09 16:26:15 +03:00
|
|
|
#ifdef MOZ_WAYLAND
|
|
|
|
// Some drivers doesn't support EGL_DEFAULT_DISPLAY
|
|
|
|
GdkDisplay* gdkDisplay = gdk_display_get_default();
|
2020-03-05 13:20:48 +03:00
|
|
|
if (gdkDisplay && !GDK_IS_X11_DISPLAY(gdkDisplay)) {
|
2020-04-05 06:50:33 +03:00
|
|
|
nativeDisplay = widget::WaylandDisplayGetWLDisplay(gdkDisplay);
|
2018-05-09 16:26:15 +03:00
|
|
|
if (!nativeDisplay) {
|
|
|
|
NS_WARNING("Failed to get wl_display.");
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-04-04 03:38:42 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
#endif
|
2020-08-07 10:14:46 +03:00
|
|
|
ret = GetAndInitDisplay(*this, nativeDisplay);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2018-04-04 03:38:42 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
if (!ret) {
|
2018-04-04 03:38:42 +03:00
|
|
|
if (out_failureId->IsEmpty()) {
|
2020-07-01 11:29:29 +03:00
|
|
|
*out_failureId = "FEATURE_FAILURE_NO_DISPLAY"_ns;
|
2018-04-04 03:38:42 +03:00
|
|
|
}
|
|
|
|
NS_WARNING("Failed to initialize a display.");
|
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2018-04-04 03:38:42 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
return ret;
|
2015-11-13 00:41:45 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
void GLLibraryEGL::InitLibExtensions() {
|
2015-11-13 00:41:45 +03:00
|
|
|
const bool shouldDumpExts = GLContext::ShouldDumpExts();
|
2012-06-13 01:39:18 +04:00
|
|
|
|
2015-11-13 00:41:45 +03:00
|
|
|
const char* rawExtString = nullptr;
|
|
|
|
|
|
|
|
#ifndef ANDROID
|
|
|
|
// Bug 1209612: Crashes on a number of android drivers.
|
|
|
|
// Ideally we would only blocklist this there, but for now we don't need the
|
|
|
|
// client extension list on ANDROID (we mostly need it on ANGLE), and we'd
|
|
|
|
// rather not crash.
|
|
|
|
rawExtString = (const char*)fQueryString(nullptr, LOCAL_EGL_EXTENSIONS);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!rawExtString) {
|
|
|
|
if (shouldDumpExts) {
|
2020-08-07 10:14:46 +03:00
|
|
|
printf_stderr("No EGL lib extensions.\n");
|
2015-01-29 11:44:19 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
return;
|
|
|
|
}
|
2015-01-29 11:44:19 +03:00
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
MarkExtensions(rawExtString, shouldDumpExts, "lib", sEGLLibraryExtensionNames,
|
2015-11-13 00:41:45 +03:00
|
|
|
&mAvailableExtensions);
|
2012-06-13 01:39:18 +04:00
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
void EglDisplay::DumpEGLConfig(EGLConfig cfg) const {
|
|
|
|
#define ATTR(_x) \
|
|
|
|
do { \
|
|
|
|
int attrval = 0; \
|
|
|
|
mLib->fGetConfigAttrib(mDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
|
|
|
|
const auto err = mLib->fGetError(); \
|
|
|
|
if (err != 0x3000) { \
|
|
|
|
printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
|
|
|
|
} else { \
|
|
|
|
printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
|
|
|
|
} \
|
2012-03-17 02:24:12 +04:00
|
|
|
} while (0)
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-17 02:24:12 +04:00
|
|
|
printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-17 02:24:12 +04:00
|
|
|
ATTR(BUFFER_SIZE);
|
|
|
|
ATTR(ALPHA_SIZE);
|
|
|
|
ATTR(BLUE_SIZE);
|
|
|
|
ATTR(GREEN_SIZE);
|
|
|
|
ATTR(RED_SIZE);
|
|
|
|
ATTR(DEPTH_SIZE);
|
|
|
|
ATTR(STENCIL_SIZE);
|
|
|
|
ATTR(CONFIG_CAVEAT);
|
|
|
|
ATTR(CONFIG_ID);
|
|
|
|
ATTR(LEVEL);
|
|
|
|
ATTR(MAX_PBUFFER_HEIGHT);
|
|
|
|
ATTR(MAX_PBUFFER_PIXELS);
|
|
|
|
ATTR(MAX_PBUFFER_WIDTH);
|
|
|
|
ATTR(NATIVE_RENDERABLE);
|
|
|
|
ATTR(NATIVE_VISUAL_ID);
|
|
|
|
ATTR(NATIVE_VISUAL_TYPE);
|
|
|
|
ATTR(PRESERVED_RESOURCES);
|
|
|
|
ATTR(SAMPLES);
|
|
|
|
ATTR(SAMPLE_BUFFERS);
|
|
|
|
ATTR(SURFACE_TYPE);
|
|
|
|
ATTR(TRANSPARENT_TYPE);
|
|
|
|
ATTR(TRANSPARENT_RED_VALUE);
|
|
|
|
ATTR(TRANSPARENT_GREEN_VALUE);
|
|
|
|
ATTR(TRANSPARENT_BLUE_VALUE);
|
|
|
|
ATTR(BIND_TO_TEXTURE_RGB);
|
|
|
|
ATTR(BIND_TO_TEXTURE_RGBA);
|
|
|
|
ATTR(MIN_SWAP_INTERVAL);
|
|
|
|
ATTR(MAX_SWAP_INTERVAL);
|
|
|
|
ATTR(LUMINANCE_SIZE);
|
|
|
|
ATTR(ALPHA_MASK_SIZE);
|
|
|
|
ATTR(COLOR_BUFFER_TYPE);
|
|
|
|
ATTR(RENDERABLE_TYPE);
|
|
|
|
ATTR(CONFORMANT);
|
|
|
|
|
|
|
|
#undef ATTR
|
|
|
|
}
|
|
|
|
|
2020-08-07 10:14:46 +03:00
|
|
|
void EglDisplay::DumpEGLConfigs() const {
|
2012-03-17 02:24:12 +04:00
|
|
|
int nc = 0;
|
2020-08-07 10:14:46 +03:00
|
|
|
mLib->fGetConfigs(mDisplay, nullptr, 0, &nc);
|
|
|
|
std::vector<EGLConfig> ec(nc);
|
|
|
|
mLib->fGetConfigs(mDisplay, ec.data(), ec.size(), &nc);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-17 02:24:12 +04:00
|
|
|
for (int i = 0; i < nc; ++i) {
|
2016-06-07 02:29:08 +03:00
|
|
|
printf_stderr("========= EGL Config %d ========\n", i);
|
2012-03-17 02:24:12 +04:00
|
|
|
DumpEGLConfig(ec[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-07 02:29:08 +03:00
|
|
|
static bool ShouldTrace() {
|
|
|
|
static bool ret = gfxEnv::GlDebugVerbose();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-03-04 06:24:51 +03:00
|
|
|
void BeforeEGLCall(const char* glFunction) {
|
2016-06-07 02:29:08 +03:00
|
|
|
if (ShouldTrace()) {
|
|
|
|
printf_stderr("[egl] > %s\n", glFunction);
|
2013-09-04 16:14:52 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-04 06:24:51 +03:00
|
|
|
void AfterEGLCall(const char* glFunction) {
|
2016-06-07 02:29:08 +03:00
|
|
|
if (ShouldTrace()) {
|
2013-09-04 16:14:52 +04:00
|
|
|
printf_stderr("[egl] < %s\n", glFunction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-17 02:24:12 +04:00
|
|
|
} /* namespace gl */
|
|
|
|
} /* namespace mozilla */
|