зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1268638 - Update WebGL creation to allow non-blacklisted native-gl. - r=jrmuizel
Also support accumulating a list of WebGL failure reasons. MozReview-Commit-ID: I9p0BBrBJ5V
This commit is contained in:
Родитель
5a27646a69
Коммит
e417babf90
|
@ -434,12 +434,15 @@ WebGLContext::GetHeight() const
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature, nsACString* const out_failureId)
|
IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature,
|
||||||
|
nsCString* const out_blacklistId)
|
||||||
{
|
{
|
||||||
int32_t status;
|
int32_t status;
|
||||||
if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature,
|
if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature,
|
||||||
*out_failureId, &status)))
|
*out_blacklistId, &status)))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return status != nsIGfxInfo::FEATURE_STATUS_OK;
|
return status != nsIGfxInfo::FEATURE_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
@ -562,16 +565,16 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
|
||||||
|
|
||||||
// Done with baseCaps construction.
|
// Done with baseCaps construction.
|
||||||
|
|
||||||
bool forceAllowAA = gfxPrefs::WebGLForceMSAA();
|
if (!gfxPrefs::WebGLForceMSAA()) {
|
||||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||||
nsCString discardFailureId;
|
|
||||||
if (!forceAllowAA &&
|
nsCString blocklistId;
|
||||||
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA, &discardFailureId))
|
if (IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA, &blocklistId)) {
|
||||||
{
|
|
||||||
webgl->GenerateWarning("Disallowing antialiased backbuffers due"
|
webgl->GenerateWarning("Disallowing antialiased backbuffers due"
|
||||||
" to blacklisting.");
|
" to blacklisting.");
|
||||||
baseCaps.antialias = false;
|
baseCaps.antialias = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return baseCaps;
|
return baseCaps;
|
||||||
}
|
}
|
||||||
|
@ -580,8 +583,7 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
|
||||||
|
|
||||||
static already_AddRefed<gl::GLContext>
|
static already_AddRefed<gl::GLContext>
|
||||||
CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
WebGLContext* webgl, nsACString* const out_failReason,
|
WebGLContext* webgl, std::vector<FailureReason>* const out_failReasons)
|
||||||
nsACString* const out_failureId)
|
|
||||||
{
|
{
|
||||||
const gfx::IntSize dummySize(16, 16);
|
const gfx::IntSize dummySize(16, 16);
|
||||||
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
||||||
|
@ -591,13 +593,8 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
if (out_failReason->Length()) {
|
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_EGL_INIT",
|
||||||
out_failReason->AppendLiteral("\n");
|
"Error during EGL OpenGL init." });
|
||||||
}
|
|
||||||
out_failReason->AppendLiteral("Error during EGL OpenGL init.");
|
|
||||||
if (out_failureId->IsEmpty()) {
|
|
||||||
*out_failureId = "FEATURE_FAILURE_WEBGL_EGL_INIT";
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,8 +603,7 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
|
|
||||||
static already_AddRefed<GLContext>
|
static already_AddRefed<GLContext>
|
||||||
CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
WebGLContext* webgl, nsACString* const out_failReason,
|
WebGLContext* webgl, std::vector<FailureReason>* const out_failReasons)
|
||||||
nsACString* const out_failureId)
|
|
||||||
{
|
{
|
||||||
const gfx::IntSize dummySize(16, 16);
|
const gfx::IntSize dummySize(16, 16);
|
||||||
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
||||||
|
@ -617,13 +613,8 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
if (out_failReason->Length()) {
|
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_ANGLE_INIT",
|
||||||
out_failReason->AppendLiteral("\n");
|
"Error during ANGLE OpenGL init." });
|
||||||
}
|
|
||||||
out_failReason->AppendLiteral("Error during ANGLE OpenGL init.");
|
|
||||||
if (out_failureId->IsEmpty()) {
|
|
||||||
*out_failureId = "FEATURE_FAILURE_WEBGL_ANGLE_INIT";
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,22 +623,9 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
|
|
||||||
static already_AddRefed<gl::GLContext>
|
static already_AddRefed<gl::GLContext>
|
||||||
CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
WebGLContext* webgl, nsACString* const out_failReason,
|
WebGLContext* webgl,
|
||||||
nsACString* const out_failureId)
|
std::vector<FailureReason>* const out_failReasons)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
|
||||||
|
|
||||||
if (!(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE) &&
|
|
||||||
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL, out_failureId))
|
|
||||||
{
|
|
||||||
if (out_failReason->Length()) {
|
|
||||||
out_failReason->AppendASCII("\n");
|
|
||||||
}
|
|
||||||
out_failReason->AppendASCII("Refused to create native OpenGL context because of"
|
|
||||||
" blacklisting.");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfx::IntSize dummySize(16, 16);
|
const gfx::IntSize dummySize(16, 16);
|
||||||
RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps,
|
RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps,
|
||||||
flags, out_failureId);
|
flags, out_failureId);
|
||||||
|
@ -657,13 +635,8 @@ CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
if (out_failReason->Length()) {
|
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_DEFAULT_INIT",
|
||||||
out_failReason->AppendASCII("\n");
|
"Error during native OpenGL init." });
|
||||||
}
|
|
||||||
out_failReason->AppendASCII("Error during native OpenGL init.");
|
|
||||||
if (out_failureId->IsEmpty()) {
|
|
||||||
*out_failureId = "FEATURE_FAILURE_WEBGL_DEFAULT_INIT";
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,8 +649,7 @@ bool
|
||||||
WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
||||||
const gl::SurfaceCaps& baseCaps,
|
const gl::SurfaceCaps& baseCaps,
|
||||||
gl::CreateContextFlags flags,
|
gl::CreateContextFlags flags,
|
||||||
nsACString* const out_failReason,
|
std::vector<FailureReason>* const out_failReasons)
|
||||||
nsACString* const out_failureId)
|
|
||||||
{
|
{
|
||||||
std::queue<gl::SurfaceCaps> fallbackCaps;
|
std::queue<gl::SurfaceCaps> fallbackCaps;
|
||||||
PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
|
PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
|
||||||
|
@ -685,9 +657,8 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
||||||
MOZ_RELEASE_ASSERT(!gl, "GFX: Already have a context.");
|
MOZ_RELEASE_ASSERT(!gl, "GFX: Already have a context.");
|
||||||
gl = nullptr;
|
gl = nullptr;
|
||||||
while (!fallbackCaps.empty()) {
|
while (!fallbackCaps.empty()) {
|
||||||
gl::SurfaceCaps& caps = fallbackCaps.front();
|
const gl::SurfaceCaps& caps = fallbackCaps.front();
|
||||||
|
gl = fnCreateGL(caps, flags, this, out_failReasons);
|
||||||
gl = fnCreateGL(caps, flags, this, out_failReason, out_failureId);
|
|
||||||
if (gl)
|
if (gl)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -696,9 +667,11 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
||||||
if (!gl)
|
if (!gl)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!InitAndValidateGL(out_failReason, out_failureId)) {
|
FailureReason reason;
|
||||||
|
if (!InitAndValidateGL(&reason.info, &reason.key)) {
|
||||||
// The fail reason here should be specific enough for now.
|
// The fail reason here should be specific enough for now.
|
||||||
gl = nullptr;
|
gl = nullptr;
|
||||||
|
out_failReasons->push_back(reason);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,16 +679,30 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason, nsACString* const out_failureId)
|
WebGLContext::CreateAndInitGL(bool forceEnabled,
|
||||||
|
std::vector<FailureReason>* const out_failReasons)
|
||||||
{
|
{
|
||||||
const bool useEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
|
bool blacklistOpenGL = false;
|
||||||
|
if (!forceEnabled) {
|
||||||
|
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||||
|
|
||||||
bool useANGLE = false;
|
FailureReason reason;
|
||||||
#ifdef XP_WIN
|
if (IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL,
|
||||||
const bool disableANGLE = (gfxPrefs::WebGLDisableANGLE() ||
|
&reason.key))
|
||||||
PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"));
|
{
|
||||||
useANGLE = !disableANGLE;
|
blacklistOpenGL = true;
|
||||||
#endif
|
|
||||||
|
reason.info = "Refused to create native OpenGL context because of blacklist"
|
||||||
|
" entry: ";
|
||||||
|
reason.info.Append(blacklistId);
|
||||||
|
|
||||||
|
out_failReasons->push_back(reason);
|
||||||
|
|
||||||
|
GenerateWarning(text.BeginReading());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////
|
||||||
|
|
||||||
gl::CreateContextFlags flags = gl::CreateContextFlags::NO_VALIDATION;
|
gl::CreateContextFlags flags = gl::CreateContextFlags::NO_VALIDATION;
|
||||||
|
|
||||||
|
@ -725,13 +712,34 @@ WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReaso
|
||||||
|
|
||||||
const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
|
const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
|
||||||
|
|
||||||
|
//////
|
||||||
|
|
||||||
|
if (!blacklistOpenGL) {
|
||||||
|
const bool useEGL = PR_GetEnv("MOZ_WEBGL_FORCE_EGL");
|
||||||
|
|
||||||
if (useEGL)
|
if (useEGL)
|
||||||
return CreateAndInitGLWith(CreateGLWithEGL, baseCaps, flags, out_failReason, out_failureId);
|
return CreateAndInitGLWith(CreateGLWithEGL, baseCaps, flags, out_failReasons);
|
||||||
|
|
||||||
|
if (CreateAndInitGLWith(CreateGLWithNative, baseCaps, flags, out_failReasons))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////
|
||||||
|
|
||||||
|
bool useANGLE = false;
|
||||||
|
#ifdef XP_WIN
|
||||||
|
const bool disableANGLE = (gfxPrefs::WebGLDisableANGLE() ||
|
||||||
|
PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"));
|
||||||
|
useANGLE = !disableANGLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (useANGLE)
|
if (useANGLE)
|
||||||
return CreateAndInitGLWith(CreateGLWithANGLE, baseCaps, flags, out_failReason, out_failureId);
|
return CreateAndInitGLWith(CreateGLWithANGLE, baseCaps, flags, out_failReasons);
|
||||||
|
|
||||||
return CreateAndInitGLWith(CreateGLWithDefault, baseCaps, flags, out_failReason, out_failureId);
|
//////
|
||||||
|
|
||||||
|
out_failReasons->push_back(nsLiteralCString("Exhausted GL driver options."));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback for resizes:
|
// Fallback for resizes:
|
||||||
|
@ -929,12 +937,15 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
|
||||||
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
||||||
|
|
||||||
MOZ_ASSERT(!gl);
|
MOZ_ASSERT(!gl);
|
||||||
nsCString failReason;
|
std::vector<FailureReason> failReasons;
|
||||||
nsCString failureId;
|
if (!CreateAndInitGL(forceEnabled, &failReasons)) {
|
||||||
if (!CreateAndInitGL(forceEnabled, &failReason, &failureId)) {
|
nsCString text("WebGL creation failed: ");
|
||||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, failureId);
|
for (const auto& cur : failReasons) {
|
||||||
const nsPrintfCString text("WebGL creation failed: %s",
|
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, cur.key);
|
||||||
failReason.BeginReading());
|
|
||||||
|
text.AppendASCII("\n* ");
|
||||||
|
text.Append(cur.info);
|
||||||
|
}
|
||||||
ThrowEvent_WebGLContextCreationError(text);
|
ThrowEvent_WebGLContextCreationError(text);
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1201,19 +1201,24 @@ public:
|
||||||
protected:
|
protected:
|
||||||
bool InitWebGL2(nsACString* const out_failReason, nsACString* const out_failureId);
|
bool InitWebGL2(nsACString* const out_failReason, nsACString* const out_failureId);
|
||||||
|
|
||||||
bool CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason, nsACString* const out_failureId);
|
struct FailureReason {
|
||||||
|
nsCString key; // For reporting.
|
||||||
|
nsCString info;
|
||||||
|
};
|
||||||
|
bool CreateAndInitGL(bool forceEnabled,
|
||||||
|
std::vector<FailureReason>* const out_failReasons);
|
||||||
|
|
||||||
bool ResizeBackbuffer(uint32_t width, uint32_t height);
|
bool ResizeBackbuffer(uint32_t width, uint32_t height);
|
||||||
|
|
||||||
typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
|
typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
|
||||||
gl::CreateContextFlags flags,
|
gl::CreateContextFlags flags,
|
||||||
WebGLContext* webgl,
|
WebGLContext* webgl,
|
||||||
nsACString* const out_failReason,
|
std::vector<FailureReason>* const out_failReasons);
|
||||||
nsACString* const out_failureId);
|
|
||||||
|
|
||||||
bool CreateAndInitGLWith(FnCreateGL_T fnCreateGL, const gl::SurfaceCaps& baseCaps,
|
bool CreateAndInitGLWith(FnCreateGL_T fnCreateGL, const gl::SurfaceCaps& baseCaps,
|
||||||
gl::CreateContextFlags flags,
|
gl::CreateContextFlags flags,
|
||||||
nsACString* const out_failReason,
|
std::vector<FailureReason>* const out_failReasons);
|
||||||
nsACString* const out_failureId);
|
|
||||||
void ThrowEvent_WebGLContextCreationError(const nsACString& text);
|
void ThrowEvent_WebGLContextCreationError(const nsACString& text);
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
Загрузка…
Ссылка в новой задаче