зеркало из 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
|
||||
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;
|
||||
if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature,
|
||||
*out_failureId, &status)))
|
||||
*out_blacklistId, &status)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return status != nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
}
|
||||
|
@ -562,16 +565,16 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
|
|||
|
||||
// Done with baseCaps construction.
|
||||
|
||||
bool forceAllowAA = gfxPrefs::WebGLForceMSAA();
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
nsCString discardFailureId;
|
||||
if (!forceAllowAA &&
|
||||
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA, &discardFailureId))
|
||||
{
|
||||
if (!gfxPrefs::WebGLForceMSAA()) {
|
||||
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
|
||||
nsCString blocklistId;
|
||||
if (IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA, &blocklistId)) {
|
||||
webgl->GenerateWarning("Disallowing antialiased backbuffers due"
|
||||
" to blacklisting.");
|
||||
baseCaps.antialias = false;
|
||||
}
|
||||
}
|
||||
|
||||
return baseCaps;
|
||||
}
|
||||
|
@ -580,8 +583,7 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
|
|||
|
||||
static already_AddRefed<gl::GLContext>
|
||||
CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||
WebGLContext* webgl, nsACString* const out_failReason,
|
||||
nsACString* const out_failureId)
|
||||
WebGLContext* webgl, std::vector<FailureReason>* const out_failReasons)
|
||||
{
|
||||
const gfx::IntSize dummySize(16, 16);
|
||||
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
||||
|
@ -591,13 +593,8 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
|||
}
|
||||
|
||||
if (!gl) {
|
||||
if (out_failReason->Length()) {
|
||||
out_failReason->AppendLiteral("\n");
|
||||
}
|
||||
out_failReason->AppendLiteral("Error during EGL OpenGL init.");
|
||||
if (out_failureId->IsEmpty()) {
|
||||
*out_failureId = "FEATURE_FAILURE_WEBGL_EGL_INIT";
|
||||
}
|
||||
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_EGL_INIT",
|
||||
"Error during EGL OpenGL init." });
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -606,8 +603,7 @@ CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
|||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||
WebGLContext* webgl, nsACString* const out_failReason,
|
||||
nsACString* const out_failureId)
|
||||
WebGLContext* webgl, std::vector<FailureReason>* const out_failReasons)
|
||||
{
|
||||
const gfx::IntSize dummySize(16, 16);
|
||||
RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
|
||||
|
@ -617,13 +613,8 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
|||
}
|
||||
|
||||
if (!gl) {
|
||||
if (out_failReason->Length()) {
|
||||
out_failReason->AppendLiteral("\n");
|
||||
}
|
||||
out_failReason->AppendLiteral("Error during ANGLE OpenGL init.");
|
||||
if (out_failureId->IsEmpty()) {
|
||||
*out_failureId = "FEATURE_FAILURE_WEBGL_ANGLE_INIT";
|
||||
}
|
||||
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_ANGLE_INIT",
|
||||
"Error during ANGLE OpenGL init." });
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -632,22 +623,9 @@ CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
|||
|
||||
static already_AddRefed<gl::GLContext>
|
||||
CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
||||
WebGLContext* webgl, nsACString* const out_failReason,
|
||||
nsACString* const out_failureId)
|
||||
WebGLContext* webgl,
|
||||
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);
|
||||
RefPtr<GLContext> gl = gl::GLContextProvider::CreateOffscreen(dummySize, caps,
|
||||
flags, out_failureId);
|
||||
|
@ -657,13 +635,8 @@ CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
|
|||
}
|
||||
|
||||
if (!gl) {
|
||||
if (out_failReason->Length()) {
|
||||
out_failReason->AppendASCII("\n");
|
||||
}
|
||||
out_failReason->AppendASCII("Error during native OpenGL init.");
|
||||
if (out_failureId->IsEmpty()) {
|
||||
*out_failureId = "FEATURE_FAILURE_WEBGL_DEFAULT_INIT";
|
||||
}
|
||||
out_failReasons->push_back({ "FEATURE_FAILURE_WEBGL_DEFAULT_INIT",
|
||||
"Error during native OpenGL init." });
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -676,8 +649,7 @@ bool
|
|||
WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
||||
const gl::SurfaceCaps& baseCaps,
|
||||
gl::CreateContextFlags flags,
|
||||
nsACString* const out_failReason,
|
||||
nsACString* const out_failureId)
|
||||
std::vector<FailureReason>* const out_failReasons)
|
||||
{
|
||||
std::queue<gl::SurfaceCaps> fallbackCaps;
|
||||
PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
|
||||
|
@ -685,9 +657,8 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
|||
MOZ_RELEASE_ASSERT(!gl, "GFX: Already have a context.");
|
||||
gl = nullptr;
|
||||
while (!fallbackCaps.empty()) {
|
||||
gl::SurfaceCaps& caps = fallbackCaps.front();
|
||||
|
||||
gl = fnCreateGL(caps, flags, this, out_failReason, out_failureId);
|
||||
const gl::SurfaceCaps& caps = fallbackCaps.front();
|
||||
gl = fnCreateGL(caps, flags, this, out_failReasons);
|
||||
if (gl)
|
||||
break;
|
||||
|
||||
|
@ -696,9 +667,11 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
|||
if (!gl)
|
||||
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.
|
||||
gl = nullptr;
|
||||
out_failReasons->push_back(reason);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -706,16 +679,30 @@ WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
|
|||
}
|
||||
|
||||
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;
|
||||
#ifdef XP_WIN
|
||||
const bool disableANGLE = (gfxPrefs::WebGLDisableANGLE() ||
|
||||
PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"));
|
||||
useANGLE = !disableANGLE;
|
||||
#endif
|
||||
FailureReason reason;
|
||||
if (IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL,
|
||||
&reason.key))
|
||||
{
|
||||
blacklistOpenGL = true;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -725,13 +712,34 @@ WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReaso
|
|||
|
||||
const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
|
||||
|
||||
//////
|
||||
|
||||
if (!blacklistOpenGL) {
|
||||
const bool useEGL = PR_GetEnv("MOZ_WEBGL_FORCE_EGL");
|
||||
|
||||
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)
|
||||
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:
|
||||
|
@ -929,12 +937,15 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
|
|||
ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
|
||||
|
||||
MOZ_ASSERT(!gl);
|
||||
nsCString failReason;
|
||||
nsCString failureId;
|
||||
if (!CreateAndInitGL(forceEnabled, &failReason, &failureId)) {
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, failureId);
|
||||
const nsPrintfCString text("WebGL creation failed: %s",
|
||||
failReason.BeginReading());
|
||||
std::vector<FailureReason> failReasons;
|
||||
if (!CreateAndInitGL(forceEnabled, &failReasons)) {
|
||||
nsCString text("WebGL creation failed: ");
|
||||
for (const auto& cur : failReasons) {
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, cur.key);
|
||||
|
||||
text.AppendASCII("\n* ");
|
||||
text.Append(cur.info);
|
||||
}
|
||||
ThrowEvent_WebGLContextCreationError(text);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -1201,19 +1201,24 @@ public:
|
|||
protected:
|
||||
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);
|
||||
|
||||
typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
|
||||
gl::CreateContextFlags flags,
|
||||
WebGLContext* webgl,
|
||||
nsACString* const out_failReason,
|
||||
nsACString* const out_failureId);
|
||||
std::vector<FailureReason>* const out_failReasons);
|
||||
|
||||
bool CreateAndInitGLWith(FnCreateGL_T fnCreateGL, const gl::SurfaceCaps& baseCaps,
|
||||
gl::CreateContextFlags flags,
|
||||
nsACString* const out_failReason,
|
||||
nsACString* const out_failureId);
|
||||
std::vector<FailureReason>* const out_failReasons);
|
||||
|
||||
void ThrowEvent_WebGLContextCreationError(const nsACString& text);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
Загрузка…
Ссылка в новой задаче