1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AndroidBuild.h"
9 #include "GLContextProvider.h"
10 #include "nsUnicharUtils.h"
12 #include "nsExceptionHandler.h"
13 #include "nsHashKeys.h"
14 #include "nsVersionComparator.h"
15 #include "nsServiceManagerUtils.h"
17 #include "mozilla/Preferences.h"
18 #include "mozilla/java/GeckoAppShellWrappers.h"
19 #include "mozilla/java/HardwareCodecCapabilityUtilsWrappers.h"
24 class GfxInfo::GLStrings
{
28 nsTArray
<nsCString
> mExtensions
;
32 GLStrings() : mReady(false) {}
34 const nsCString
& Vendor() {
39 // This spoofed value wins, even if the environment variable
40 // MOZ_GFX_SPOOF_GL_VENDOR was set.
41 void SpoofVendor(const nsCString
& s
) { mVendor
= s
; }
43 const nsCString
& Renderer() {
48 // This spoofed value wins, even if the environment variable
49 // MOZ_GFX_SPOOF_GL_RENDERER was set.
50 void SpoofRenderer(const nsCString
& s
) { mRenderer
= s
; }
52 const nsCString
& Version() {
57 // This spoofed value wins, even if the environment variable
58 // MOZ_GFX_SPOOF_GL_VERSION was set.
59 void SpoofVersion(const nsCString
& s
) { mVersion
= s
; }
61 const nsTArray
<nsCString
>& Extensions() {
66 void EnsureInitialized() {
71 RefPtr
<gl::GLContext
> gl
;
72 nsCString discardFailureId
;
73 gl
= gl::GLContextProvider::CreateHeadless(
74 {gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE
}, &discardFailureId
);
77 // Setting mReady to true here means that we won't retry. Everything will
78 // remain blocklisted forever. Ideally, we would like to update that once
79 // any GLContext is successfully created, like the compositor's GLContext.
86 if (mVendor
.IsEmpty()) {
87 const char* spoofedVendor
= PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
89 mVendor
.Assign(spoofedVendor
);
91 mVendor
.Assign((const char*)gl
->fGetString(LOCAL_GL_VENDOR
));
95 if (mRenderer
.IsEmpty()) {
96 const char* spoofedRenderer
= PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
97 if (spoofedRenderer
) {
98 mRenderer
.Assign(spoofedRenderer
);
100 mRenderer
.Assign((const char*)gl
->fGetString(LOCAL_GL_RENDERER
));
104 if (mVersion
.IsEmpty()) {
105 const char* spoofedVersion
= PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
106 if (spoofedVersion
) {
107 mVersion
.Assign(spoofedVersion
);
109 mVersion
.Assign((const char*)gl
->fGetString(LOCAL_GL_VERSION
));
113 if (mExtensions
.IsEmpty()) {
114 nsCString rawExtensions
;
115 rawExtensions
.Assign((const char*)gl
->fGetString(LOCAL_GL_EXTENSIONS
));
116 rawExtensions
.Trim(" ");
118 for (auto extension
: rawExtensions
.Split(' ')) {
119 mExtensions
.AppendElement(extension
);
128 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo
, GfxInfoBase
, nsIGfxInfoDebug
)
132 : mInitialized(false),
133 mGLStrings(new GLStrings
),
134 mOSVersionInteger(0),
137 GfxInfo::~GfxInfo() {}
139 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after
140 * gfxPlatform initialization has occurred because they depend on it for
141 * information. (See bug 591561) */
142 nsresult
GfxInfo::GetD2DEnabled(bool* aEnabled
) { return NS_ERROR_FAILURE
; }
144 nsresult
GfxInfo::GetDWriteEnabled(bool* aEnabled
) { return NS_ERROR_FAILURE
; }
146 nsresult
GfxInfo::GetHasBattery(bool* aHasBattery
) {
147 return NS_ERROR_NOT_IMPLEMENTED
;
151 GfxInfo::GetDWriteVersion(nsAString
& aDwriteVersion
) {
152 return NS_ERROR_FAILURE
;
156 GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality
) {
157 return NS_ERROR_FAILURE
;
161 GfxInfo::GetCleartypeParameters(nsAString
& aCleartypeParams
) {
162 return NS_ERROR_FAILURE
;
166 GfxInfo::GetWindowProtocol(nsAString
& aWindowProtocol
) {
167 return NS_ERROR_NOT_IMPLEMENTED
;
171 GfxInfo::GetTestType(nsAString
& aTestType
) { return NS_ERROR_NOT_IMPLEMENTED
; }
173 void GfxInfo::EnsureInitialized() {
174 if (mInitialized
) return;
176 if (!jni::IsAvailable()) {
177 gfxWarning() << "JNI missing during initialization";
181 jni::String::LocalRef model
= java::sdk::Build::MODEL();
182 mModel
= model
->ToString();
183 mAdapterDescription
.AppendPrintf("Model: %s",
184 NS_LossyConvertUTF16toASCII(mModel
).get());
186 jni::String::LocalRef product
= java::sdk::Build::PRODUCT();
187 mProduct
= product
->ToString();
188 mAdapterDescription
.AppendPrintf(", Product: %s",
189 NS_LossyConvertUTF16toASCII(mProduct
).get());
191 jni::String::LocalRef manufacturer
=
192 mozilla::java::sdk::Build::MANUFACTURER();
193 mManufacturer
= manufacturer
->ToString();
194 mAdapterDescription
.AppendPrintf(
195 ", Manufacturer: %s", NS_LossyConvertUTF16toASCII(mManufacturer
).get());
197 mSDKVersion
= java::sdk::Build::VERSION::SDK_INT();
198 // the HARDWARE field isn't available on Android SDK < 8, but we require 9+
200 MOZ_ASSERT(mSDKVersion
>= 8);
201 jni::String::LocalRef hardware
= java::sdk::Build::HARDWARE();
202 mHardware
= hardware
->ToString();
203 mAdapterDescription
.AppendPrintf(
204 ", Hardware: %s", NS_LossyConvertUTF16toASCII(mHardware
).get());
206 jni::String::LocalRef release
= java::sdk::Build::VERSION::RELEASE();
207 mOSVersion
= release
->ToCString();
209 mOSVersionInteger
= 0;
210 char a
[5], b
[5], c
[5], d
[5];
211 SplitDriverVersion(mOSVersion
.get(), a
, b
, c
, d
);
212 uint8_t na
= atoi(a
);
213 uint8_t nb
= atoi(b
);
214 uint8_t nc
= atoi(c
);
215 uint8_t nd
= atoi(d
);
217 mOSVersionInteger
= (uint32_t(na
) << 24) | (uint32_t(nb
) << 16) |
218 (uint32_t(nc
) << 8) | uint32_t(nd
);
220 mAdapterDescription
.AppendPrintf(
221 ", OpenGL: %s -- %s -- %s", mGLStrings
->Vendor().get(),
222 mGLStrings
->Renderer().get(), mGLStrings
->Version().get());
224 AddCrashReportAnnotations();
229 GfxInfo::GetAdapterDescription(nsAString
& aAdapterDescription
) {
231 aAdapterDescription
= NS_ConvertASCIItoUTF16(mAdapterDescription
);
236 GfxInfo::GetAdapterDescription2(nsAString
& aAdapterDescription
) {
238 return NS_ERROR_FAILURE
;
242 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM
) {
249 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM
) {
251 return NS_ERROR_FAILURE
;
255 GfxInfo::GetAdapterDriver(nsAString
& aAdapterDriver
) {
257 aAdapterDriver
.Truncate();
262 GfxInfo::GetAdapterDriver2(nsAString
& aAdapterDriver
) {
264 return NS_ERROR_FAILURE
;
268 GfxInfo::GetAdapterDriverVendor(nsAString
& aAdapterDriverVendor
) {
270 aAdapterDriverVendor
.Truncate();
275 GfxInfo::GetAdapterDriverVendor2(nsAString
& aAdapterDriverVendor
) {
277 return NS_ERROR_FAILURE
;
281 GfxInfo::GetAdapterDriverVersion(nsAString
& aAdapterDriverVersion
) {
283 aAdapterDriverVersion
= NS_ConvertASCIItoUTF16(mGLStrings
->Version());
288 GfxInfo::GetAdapterDriverVersion2(nsAString
& aAdapterDriverVersion
) {
290 return NS_ERROR_FAILURE
;
294 GfxInfo::GetAdapterDriverDate(nsAString
& aAdapterDriverDate
) {
296 aAdapterDriverDate
.Truncate();
301 GfxInfo::GetAdapterDriverDate2(nsAString
& aAdapterDriverDate
) {
303 return NS_ERROR_FAILURE
;
307 GfxInfo::GetAdapterVendorID(nsAString
& aAdapterVendorID
) {
309 aAdapterVendorID
= NS_ConvertASCIItoUTF16(mGLStrings
->Vendor());
314 GfxInfo::GetAdapterVendorID2(nsAString
& aAdapterVendorID
) {
316 return NS_ERROR_FAILURE
;
320 GfxInfo::GetAdapterDeviceID(nsAString
& aAdapterDeviceID
) {
322 aAdapterDeviceID
= NS_ConvertASCIItoUTF16(mGLStrings
->Renderer());
327 GfxInfo::GetAdapterDeviceID2(nsAString
& aAdapterDeviceID
) {
329 return NS_ERROR_FAILURE
;
333 GfxInfo::GetAdapterSubsysID(nsAString
& aAdapterSubsysID
) {
335 return NS_ERROR_FAILURE
;
339 GfxInfo::GetAdapterSubsysID2(nsAString
& aAdapterSubsysID
) {
341 return NS_ERROR_FAILURE
;
345 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active
) {
347 return NS_ERROR_FAILURE
;
351 GfxInfo::GetDrmRenderDevice(nsACString
& aDrmRenderDevice
) {
352 return NS_ERROR_NOT_IMPLEMENTED
;
355 void GfxInfo::AddCrashReportAnnotations() {
356 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID
,
357 mGLStrings
->Vendor());
358 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID
,
359 mGLStrings
->Renderer());
360 CrashReporter::AnnotateCrashReport(
361 CrashReporter::Annotation::AdapterDriverVersion
, mGLStrings
->Version());
364 const nsTArray
<GfxDriverInfo
>& GfxInfo::GetGfxDriverInfo() {
365 if (sDriverInfo
->IsEmpty()) {
366 APPEND_TO_DRIVER_BLOCKLIST2(
367 OperatingSystem::Android
, DeviceFamily::All
,
368 nsIGfxInfo::FEATURE_OPENGL_LAYERS
, nsIGfxInfo::FEATURE_STATUS_OK
,
369 DRIVER_COMPARISON_IGNORED
, GfxDriverInfo::allDriverVersions
,
370 "FEATURE_OK_FORCE_OPENGL");
376 nsresult
GfxInfo::GetFeatureStatusImpl(
377 int32_t aFeature
, int32_t* aStatus
, nsAString
& aSuggestedDriverVersion
,
378 const nsTArray
<GfxDriverInfo
>& aDriverInfo
, nsACString
& aFailureId
,
379 OperatingSystem
* aOS
/* = nullptr */) {
380 NS_ENSURE_ARG_POINTER(aStatus
);
381 aSuggestedDriverVersion
.SetIsVoid(true);
382 *aStatus
= nsIGfxInfo::FEATURE_STATUS_UNKNOWN
;
383 OperatingSystem os
= OperatingSystem::Android
;
386 if (sShutdownOccurred
) {
390 // OpenGL layers are never blocklisted on Android.
391 // This early return is so we avoid potentially slow
392 // GLStrings initialization on startup when we initialize GL layers.
393 if (aFeature
== nsIGfxInfo::FEATURE_OPENGL_LAYERS
) {
394 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
400 if (mGLStrings
->Vendor().IsEmpty() || mGLStrings
->Renderer().IsEmpty()) {
401 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
405 // Don't evaluate special cases when evaluating the downloaded blocklist.
406 if (aDriverInfo
.IsEmpty()) {
407 if (aFeature
== nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION
) {
408 if (mSDKVersion
< 11) {
409 // It's slower than software due to not having a compositing fast path
410 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION
;
411 aFailureId
= "FEATURE_FAILURE_CANVAS_2D_SDK";
412 } else if (mGLStrings
->Renderer().Find("Vivante GC1000") != -1) {
413 // Blocklist Vivante GC1000. See bug 1248183.
414 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
415 aFailureId
= "FEATURE_FAILED_CANVAS_2D_HW";
417 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
422 if (aFeature
== FEATURE_WEBGL_OPENGL
) {
423 if (mGLStrings
->Renderer().Find("Adreno 200") != -1 ||
424 mGLStrings
->Renderer().Find("Adreno 205") != -1) {
425 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
426 aFailureId
= "FEATURE_FAILURE_ADRENO_20x";
430 if (mSDKVersion
<= 17) {
431 if (mGLStrings
->Renderer().Find("Adreno (TM) 3") != -1) {
432 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
433 aFailureId
= "FEATURE_FAILURE_ADRENO_3xx";
438 if (mHardware
.EqualsLiteral("ville")) {
439 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
440 aFailureId
= "FEATURE_FAILURE_VILLE";
445 if (aFeature
== FEATURE_STAGEFRIGHT
) {
446 NS_LossyConvertUTF16toASCII
cManufacturer(mManufacturer
);
447 NS_LossyConvertUTF16toASCII
cModel(mModel
);
448 NS_LossyConvertUTF16toASCII
cHardware(mHardware
);
450 if (cHardware
.EqualsLiteral("antares") ||
451 cHardware
.EqualsLiteral("harmony") ||
452 cHardware
.EqualsLiteral("picasso") ||
453 cHardware
.EqualsLiteral("picasso_e") ||
454 cHardware
.EqualsLiteral("ventana") ||
455 cHardware
.EqualsLiteral("rk30board")) {
456 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
457 aFailureId
= "FEATURE_FAILURE_STAGE_HW";
461 if (CompareVersions(mOSVersion
.get(), "4.1.0") < 0) {
463 // All Samsung ICS devices, except for:
464 // Samsung SGH-I717 (Bug 845729)
465 // Samsung SGH-I727 (Bug 845729)
466 // Samsung SGH-I757 (Bug 845729)
467 // All Galaxy nexus ICS devices
468 // Sony Xperia Ion (LT28) ICS devices
470 cModel
.Equals("LT28h", nsCaseInsensitiveCStringComparator
) ||
471 cManufacturer
.Equals("samsung",
472 nsCaseInsensitiveCStringComparator
) ||
475 nsCaseInsensitiveCStringComparator
); // some Galaxy Nexus
477 // manufacturer=amazon
479 if (cModel
.LowerCaseFindASCII("sgh-i717") != -1 ||
480 cModel
.LowerCaseFindASCII("sgh-i727") != -1 ||
481 cModel
.LowerCaseFindASCII("sgh-i757") != -1) {
482 isWhitelisted
= false;
485 if (!isWhitelisted
) {
486 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
487 aFailureId
= "FEATURE_FAILURE_4_1_HW";
490 } else if (CompareVersions(mOSVersion
.get(), "4.2.0") < 0) {
492 // All JB phones except for those in blocklist below
494 // Samsung devices from bug 812881 and 853522.
495 // Motorola XT890 from bug 882342.
496 bool isBlocklisted
= cModel
.LowerCaseFindASCII("gt-p3100") != -1 ||
497 cModel
.LowerCaseFindASCII("gt-p3110") != -1 ||
498 cModel
.LowerCaseFindASCII("gt-p3113") != -1 ||
499 cModel
.LowerCaseFindASCII("gt-p5100") != -1 ||
500 cModel
.LowerCaseFindASCII("gt-p5110") != -1 ||
501 cModel
.LowerCaseFindASCII("gt-p5113") != -1 ||
502 cModel
.LowerCaseFindASCII("xt890") != -1;
505 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
506 aFailureId
= "FEATURE_FAILURE_4_2_HW";
509 } else if (CompareVersions(mOSVersion
.get(), "4.3.0") < 0) {
510 // Blocklist all Sony devices
511 if (cManufacturer
.LowerCaseFindASCII("sony") != -1) {
512 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
513 aFailureId
= "FEATURE_FAILURE_4_3_SONY";
519 if (aFeature
== FEATURE_WEBRTC_HW_ACCELERATION_ENCODE
) {
520 if (jni::IsAvailable()) {
521 *aStatus
= WebRtcHwVp8EncodeSupported();
522 aFailureId
= "FEATURE_FAILURE_WEBRTC_ENCODE";
526 if (aFeature
== FEATURE_WEBRTC_HW_ACCELERATION_DECODE
) {
527 if (jni::IsAvailable()) {
528 *aStatus
= WebRtcHwVp8DecodeSupported();
529 aFailureId
= "FEATURE_FAILURE_WEBRTC_DECODE";
533 if (aFeature
== FEATURE_WEBRTC_HW_ACCELERATION_H264
) {
534 if (jni::IsAvailable()) {
535 *aStatus
= WebRtcHwH264Supported();
536 aFailureId
= "FEATURE_FAILURE_WEBRTC_H264";
540 if (aFeature
== FEATURE_VP8_HW_DECODE
||
541 aFeature
== FEATURE_VP9_HW_DECODE
) {
542 NS_LossyConvertUTF16toASCII
model(mModel
);
544 // GIFV crash, see bug 1232911.
545 model
.Equals("GT-N8013", nsCaseInsensitiveCStringComparator
);
548 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
549 aFailureId
= "FEATURE_FAILURE_VPx";
551 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
556 if (aFeature
== FEATURE_WEBRENDER
) {
557 const bool isMali4xx
=
558 mGLStrings
->Renderer().LowerCaseFindASCII("mali-4") >= 0;
560 const bool isPowerVrG6110
=
561 mGLStrings
->Renderer().LowerCaseFindASCII("powervr rogue g6110") >= 0;
563 const bool isVivanteGC7000UL
=
564 mGLStrings
->Renderer().LowerCaseFindASCII("vivante gc7000ul") >= 0;
566 const bool isPowerVrFenceSyncCrash
=
567 (mGLStrings
->Renderer().LowerCaseFindASCII("powervr rogue g6200") >=
569 mGLStrings
->Renderer().LowerCaseFindASCII("powervr rogue g6430") >=
571 mGLStrings
->Renderer().LowerCaseFindASCII("powervr rogue gx6250") >=
573 (mGLStrings
->Version().Find("3283119") >= 0 ||
574 mGLStrings
->Version().Find("3443629") >= 0 ||
575 mGLStrings
->Version().Find("3573678") >= 0 ||
576 mGLStrings
->Version().Find("3830101") >= 0);
579 // Mali 4xx does not support GLES 3.
580 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
581 aFailureId
= "FEATURE_FAILURE_NO_GLES_3";
582 } else if (isPowerVrG6110
) {
583 // Blocked on PowerVR Rogue G6110 due to bug 1742986 and bug 1717863.
584 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
585 aFailureId
= "FEATURE_FAILURE_POWERVR_G6110";
586 } else if (isVivanteGC7000UL
) {
587 // Blocked on Vivante GC7000UL due to bug 1719327.
588 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
589 aFailureId
= "FEATURE_FAILURE_VIVANTE_GC7000UL";
590 } else if (isPowerVrFenceSyncCrash
) {
591 // Blocked on various PowerVR GPUs due to bug 1773128.
592 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
593 aFailureId
= "FEATURE_FAILURE_POWERVR_FENCE_SYNC_CRASH";
595 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
600 if (aFeature
== FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS
) {
601 // Emulator with SwiftShader is buggy when attempting to clear picture
602 // cache textures with a scissor rect set.
603 const bool isEmulatorSwiftShader
=
604 mGLStrings
->Renderer().Find(
605 "Android Emulator OpenGL ES Translator (Google SwiftShader)") >=
607 if (isEmulatorSwiftShader
) {
608 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
609 aFailureId
= "FEATURE_FAILURE_BUG_1603515";
611 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
616 if (aFeature
== FEATURE_WEBRENDER_SHADER_CACHE
) {
617 // Program binaries are known to be buggy on Adreno 3xx. While we haven't
618 // encountered any correctness or stability issues with them, loading them
619 // fails more often than not, so is a waste of time. Better to just not
620 // even attempt to cache them. See bug 1615574.
621 const bool isAdreno3xx
=
622 mGLStrings
->Renderer().LowerCaseFindASCII("adreno (tm) 3") >= 0;
624 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
625 aFailureId
= "FEATURE_FAILURE_ADRENO_3XX";
627 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
631 if (aFeature
== FEATURE_WEBRENDER_OPTIMIZED_SHADERS
) {
632 // Optimized shaders result in completely broken rendering on some Mali-T
633 // devices. We have seen this on T6xx, T7xx, and T8xx on android versions
634 // up to 5.1, and on T6xx on versions up to android 7.1. As a precaution
635 // disable for all Mali-T regardless of version. See bug 1689064 and bug
636 // 1707283 for details.
638 mGLStrings
->Renderer().LowerCaseFindASCII("mali-t") >= 0;
640 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
641 aFailureId
= "FEATURE_FAILURE_BUG_1689064";
643 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
648 if (aFeature
== FEATURE_WEBRENDER_PARTIAL_PRESENT
) {
649 // Block partial present on some devices due to rendering issues.
650 // On Mali-Txxx due to bug 1680087 and bug 1707815.
651 // On Adreno 3xx GPUs due to bug 1695771.
653 mGLStrings
->Renderer().LowerCaseFindASCII("mali-t") >= 0;
654 const bool isAdreno3xx
=
655 mGLStrings
->Renderer().LowerCaseFindASCII("adreno (tm) 3") >= 0;
656 if (isMaliT
|| isAdreno3xx
) {
657 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
658 aFailureId
= "FEATURE_FAILURE_BUG_1680087_1695771_1707815";
660 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
666 if (aFeature
== FEATURE_GL_SWIZZLE
) {
667 // Swizzling appears to be buggy on PowerVR Rogue devices with webrender.
669 const bool isPowerVRRogue
=
670 mGLStrings
->Renderer().LowerCaseFindASCII("powervr rogue") >= 0;
671 if (isPowerVRRogue
) {
672 *aStatus
= nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
673 aFailureId
= "FEATURE_FAILURE_POWERVR_ROGUE";
675 *aStatus
= nsIGfxInfo::FEATURE_STATUS_OK
;
680 return GfxInfoBase::GetFeatureStatusImpl(
681 aFeature
, aStatus
, aSuggestedDriverVersion
, aDriverInfo
, aFailureId
, &os
);
684 static nsCString
FeatureCacheOsVerPrefName(int32_t aFeature
) {
685 nsCString osPrefName
;
686 osPrefName
.AppendASCII("gfxinfo.cache.");
687 osPrefName
.AppendInt(aFeature
);
688 osPrefName
.AppendASCII(".osver");
692 static nsCString
FeatureCacheAppVerPrefName(int32_t aFeature
) {
693 nsCString osPrefName
;
694 osPrefName
.AppendASCII("gfxinfo.cache.");
695 osPrefName
.AppendInt(aFeature
);
696 osPrefName
.AppendASCII(".appver");
700 static nsCString
FeatureCacheValuePrefName(int32_t aFeature
) {
701 nsCString osPrefName
;
702 osPrefName
.AppendASCII("gfxinfo.cache.");
703 osPrefName
.AppendInt(aFeature
);
704 osPrefName
.AppendASCII(".value");
708 static bool GetCachedFeatureVal(int32_t aFeature
, uint32_t aExpectedOsVer
,
709 const nsCString
& aCurrentAppVer
,
710 int32_t& aOutStatus
) {
713 Preferences::GetUint(FeatureCacheOsVerPrefName(aFeature
).get(), &osVer
);
714 if (NS_FAILED(rv
) || osVer
!= aExpectedOsVer
) {
717 // Bug 1804287 requires we invalidate cached values for new builds to allow
718 // for code changes to modify the features support.
719 nsAutoCString cachedAppVersion
;
720 rv
= Preferences::GetCString(FeatureCacheAppVerPrefName(aFeature
).get(),
722 if (NS_FAILED(rv
) || !aCurrentAppVer
.Equals(cachedAppVersion
)) {
726 rv
= Preferences::GetInt(FeatureCacheValuePrefName(aFeature
).get(), &status
);
734 static void SetCachedFeatureVal(int32_t aFeature
, uint32_t aOsVer
,
735 const nsCString
& aCurrentAppVer
,
737 // Ignore failures; not much we can do anyway.
738 Preferences::SetUint(FeatureCacheOsVerPrefName(aFeature
).get(), aOsVer
);
739 Preferences::SetCString(FeatureCacheAppVerPrefName(aFeature
).get(),
741 Preferences::SetInt(FeatureCacheValuePrefName(aFeature
).get(), aStatus
);
744 int32_t GfxInfo::WebRtcHwVp8EncodeSupported() {
745 MOZ_ASSERT(jni::IsAvailable());
747 // The Android side of this calculation is very slow, so we cache the result
748 // in preferences, invalidating if the OS version changes.
751 const auto& currentAppVersion
= GfxInfoBase::GetApplicationVersion();
752 if (GetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_ENCODE
,
753 mOSVersionInteger
, currentAppVersion
, status
)) {
757 status
= java::GeckoAppShell::HasHWVP8Encoder()
758 ? nsIGfxInfo::FEATURE_STATUS_OK
759 : nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
761 SetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_ENCODE
, mOSVersionInteger
,
762 currentAppVersion
, status
);
767 int32_t GfxInfo::WebRtcHwVp8DecodeSupported() {
768 MOZ_ASSERT(jni::IsAvailable());
770 // The Android side of this caclulation is very slow, so we cache the result
771 // in preferences, invalidating if the OS version changes.
774 const auto& appVersion
= GfxInfoBase::GetApplicationVersion();
775 if (GetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_DECODE
,
776 mOSVersionInteger
, appVersion
, status
)) {
780 status
= java::GeckoAppShell::HasHWVP8Decoder()
781 ? nsIGfxInfo::FEATURE_STATUS_OK
782 : nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
784 SetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_DECODE
, mOSVersionInteger
,
790 int32_t GfxInfo::WebRtcHwH264Supported() {
791 MOZ_ASSERT(jni::IsAvailable());
793 // The Android side of this calculation is very slow, so we cache the result
794 // in preferences, invalidating if the OS version changes.
797 const auto& currentAppVersion
= GfxInfoBase::GetApplicationVersion();
798 if (GetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_H264
,
799 mOSVersionInteger
, currentAppVersion
, status
)) {
803 status
= java::HardwareCodecCapabilityUtils::HasHWH264()
804 ? nsIGfxInfo::FEATURE_STATUS_OK
805 : nsIGfxInfo::FEATURE_BLOCKED_DEVICE
;
807 SetCachedFeatureVal(FEATURE_WEBRTC_HW_ACCELERATION_H264
, mOSVersionInteger
,
808 currentAppVersion
, status
);
815 // Implement nsIGfxInfoDebug
817 NS_IMETHODIMP
GfxInfo::SpoofVendorID(const nsAString
& aVendorID
) {
818 mGLStrings
->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID
));
822 NS_IMETHODIMP
GfxInfo::SpoofDeviceID(const nsAString
& aDeviceID
) {
823 mGLStrings
->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID
));
827 NS_IMETHODIMP
GfxInfo::SpoofDriverVersion(const nsAString
& aDriverVersion
) {
828 mGLStrings
->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion
));
832 NS_IMETHODIMP
GfxInfo::SpoofOSVersion(uint32_t aVersion
) {
834 mOSVersion
= aVersion
;
838 NS_IMETHODIMP
GfxInfo::FireTestProcess() { return NS_OK
; }
842 nsString
GfxInfo::Model() {
847 nsString
GfxInfo::Hardware() {
852 nsString
GfxInfo::Product() {
857 nsString
GfxInfo::Manufacturer() {
859 return mManufacturer
;
862 uint32_t GfxInfo::OperatingSystemVersion() {
864 return mOSVersionInteger
;
867 } // namespace widget
868 } // namespace mozilla