Bug 1156135. Add runtime testing of graphics features. r=mattwoodrow,mossop
This commit is contained in:
@@ -911,3 +911,9 @@ bin/libfreebl_32int64_3.so
|
|||||||
@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
|
@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
|
||||||
@RESPATH@/gmp-clearkey/0.1/clearkey.info
|
@RESPATH@/gmp-clearkey/0.1/clearkey.info
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
; gfx
|
||||||
|
#ifdef XP_WIN
|
||||||
|
@RESPATH@/components/GfxSanityTest.manifest
|
||||||
|
@RESPATH@/components/SanityTest.js
|
||||||
|
#endif
|
||||||
|
|||||||
3
toolkit/components/gfx/GfxSanityTest.manifest
Normal file
3
toolkit/components/gfx/GfxSanityTest.manifest
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
component {f3a8ca4d-4c83-456b-aee2-6a2cbf11e9bd} SanityTest.js process=main
|
||||||
|
contract @mozilla.org/sanity-test;1 {f3a8ca4d-4c83-456b-aee2-6a2cbf11e9bd} process=main
|
||||||
|
category profile-after-change SanityTest @mozilla.org/sanity-test;1 process=main
|
||||||
150
toolkit/components/gfx/SanityTest.js
Normal file
150
toolkit/components/gfx/SanityTest.js
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { utils: Cu, interfaces: Ci, classes: Cc, results: Cr } = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import('resource://gre/modules/Preferences.jsm');
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
const PAGE_WIDTH=72;
|
||||||
|
const PAGE_HEIGHT=136;
|
||||||
|
const DRIVER_PREF="sanity-test.driver-version";
|
||||||
|
const DEVICE_PREF="sanity-test.device-id";
|
||||||
|
const VERSION_PREF="sanity-test.version";
|
||||||
|
const DISABLE_VIDEO_PREF="media.hardware-video-decoding.failed";
|
||||||
|
const RUNNING_PREF="sanity-test.running";
|
||||||
|
|
||||||
|
// GRAPHICS_SANITY_TEST histogram enumeration values
|
||||||
|
const TEST_PASSED=0;
|
||||||
|
const TEST_FAILED_RENDER=1;
|
||||||
|
const TEST_FAILED_VIDEO=2;
|
||||||
|
const TEST_CRASHED=3;
|
||||||
|
|
||||||
|
function testPixel(ctx, x, y, r, g, b, a, fuzz) {
|
||||||
|
var data = ctx.getImageData(x, y, 1, 1);
|
||||||
|
|
||||||
|
if (Math.abs(data.data[0] - r) <= fuzz &&
|
||||||
|
Math.abs(data.data[1] - g) <= fuzz &&
|
||||||
|
Math.abs(data.data[2] - b) <= fuzz &&
|
||||||
|
Math.abs(data.data[3] - a) <= fuzz) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reportResult(val) {
|
||||||
|
try {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("GRAPHICS_SANITY_TEST");
|
||||||
|
histogram.add(val);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
Preferences.set(RUNNING_PREF, false);
|
||||||
|
Services.prefs.savePrefFile(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function takeWindowSnapshot(win) {
|
||||||
|
// Take a snapshot of the window contents, and then close the window
|
||||||
|
var canvas = win.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||||
|
canvas.setAttribute("width", PAGE_WIDTH);
|
||||||
|
canvas.setAttribute("height", PAGE_HEIGHT);
|
||||||
|
|
||||||
|
// TODO: drawWindow reads back from the gpu's backbuffer, which won't catch issues with presenting
|
||||||
|
// the front buffer via the window manager. Ideally we'd use an OS level API for reading back
|
||||||
|
// from the desktop itself to get a more accurate test.
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
var flags = ctx.DRAWWINDOW_DRAW_CARET | ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS;
|
||||||
|
ctx.drawWindow(win.ownerGlobal, 0, 0, PAGE_WIDTH, PAGE_HEIGHT, "rgb(255,255,255)", flags);
|
||||||
|
|
||||||
|
win.ownerGlobal.close();
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that all the 4 coloured squares of the video
|
||||||
|
// render as expected (with a tolerance of 64 to allow for
|
||||||
|
// yuv->rgb differences between platforms).
|
||||||
|
//
|
||||||
|
// The video is 64x64, and is split into quadrants of
|
||||||
|
// different colours. The top left of the video is 8,72
|
||||||
|
// and we test a pixel 10,10 into each quadrant to avoid
|
||||||
|
// blending differences at the edges.
|
||||||
|
//
|
||||||
|
// We allow massive amounts of fuzz for the colours since
|
||||||
|
// it can depend hugely on the yuv -> rgb conversion, and
|
||||||
|
// we don't want to fail unnecessarily.
|
||||||
|
function verifyVideoRendering(ctx) {
|
||||||
|
return testPixel(ctx, 18, 82, 255, 255, 255, 255, 64) &&
|
||||||
|
testPixel(ctx, 50, 82, 0, 255, 0, 255, 64) &&
|
||||||
|
testPixel(ctx, 18, 114, 0, 0, 255, 255, 64) &&
|
||||||
|
testPixel(ctx, 50, 114, 255, 0, 0, 255, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGfxFeatures(event) {
|
||||||
|
var win = event.target;
|
||||||
|
var canvas = takeWindowSnapshot(win);
|
||||||
|
|
||||||
|
if (!verifyVideoRendering(canvas)) {
|
||||||
|
reportResult(TEST_FAILED_VIDEO);
|
||||||
|
Preferences.set(DISABLE_VIDEO_PREF, true);
|
||||||
|
} else {
|
||||||
|
reportResult(TEST_PASSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SanityTest() {}
|
||||||
|
SanityTest.prototype = {
|
||||||
|
classID: Components.ID("{f3a8ca4d-4c83-456b-aee2-6a2cbf11e9bd}"),
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||||
|
Ci.nsISupportsWeakReference]),
|
||||||
|
|
||||||
|
shouldRunTest: function() {
|
||||||
|
// Only test gfx features if firefox has updated, or if the user has a new
|
||||||
|
// gpu or drivers.
|
||||||
|
var appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
|
||||||
|
var xulVersion = appInfo.version;
|
||||||
|
var gfxinfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
|
||||||
|
|
||||||
|
if (Preferences.get(RUNNING_PREF, false)) {
|
||||||
|
Preferences.set(DISABLE_VIDEO_PREF, true);
|
||||||
|
reportResult(TEST_CRASHED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Handle dual GPU setups
|
||||||
|
if (Preferences.get(DRIVER_PREF, "") == gfxinfo.adapterDriverVersion &&
|
||||||
|
Preferences.get(DEVICE_PREF, "") == gfxinfo.adapterDeviceID &&
|
||||||
|
Preferences.get(VERSION_PREF, "") == xulVersion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable hardware decoding so we can test again
|
||||||
|
// and record the driver version to detect if the driver changes.
|
||||||
|
Preferences.set(DISABLE_VIDEO_PREF, false);
|
||||||
|
Preferences.set(DRIVER_PREF, gfxinfo.adapterDriverVersion);
|
||||||
|
Preferences.set(DEVICE_PREF, gfxinfo.adapterDeviceID);
|
||||||
|
Preferences.set(VERSION_PREF, xulVersion);
|
||||||
|
|
||||||
|
// Update the prefs so that this test doesn't run again until the next update.
|
||||||
|
Preferences.set(RUNNING_PREF, true);
|
||||||
|
Services.prefs.savePrefFile(null);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
observe: function(subject, topic, data) {
|
||||||
|
if (topic != "profile-after-change") return;
|
||||||
|
if (!this.shouldRunTest()) return;
|
||||||
|
|
||||||
|
// Open a tiny window to render our test page, and notify us when it's loaded
|
||||||
|
var sanityTest = Services.ww.openWindow(null,
|
||||||
|
"chrome://gfxsanity/content/sanitytest.html",
|
||||||
|
"Test Page",
|
||||||
|
"width=" + PAGE_WIDTH + ",height=" + PAGE_HEIGHT + ",chrome,titlebar=0,scrollbars=0",
|
||||||
|
null);
|
||||||
|
sanityTest.onload = testGfxFeatures;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SanityTest]);
|
||||||
6
toolkit/components/gfx/content/sanitytest.html
Normal file
6
toolkit/components/gfx/content/sanitytest.html
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div style="width:64px; height:64px; background-color:red;"></div>
|
||||||
|
<video src="videotest.mp4"></video>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
toolkit/components/gfx/content/videotest.mp4
Normal file
BIN
toolkit/components/gfx/content/videotest.mp4
Normal file
Binary file not shown.
8
toolkit/components/gfx/jar.mn
Normal file
8
toolkit/components/gfx/jar.mn
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# 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/.
|
||||||
|
|
||||||
|
toolkit.jar:
|
||||||
|
% content gfxsanity %content/gfxsanity/
|
||||||
|
content/gfxsanity/sanitytest.html (content/sanitytest.html)
|
||||||
|
content/gfxsanity/videotest.mp4 (content/videotest.mp4)
|
||||||
15
toolkit/components/gfx/moz.build
Normal file
15
toolkit/components/gfx/moz.build
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
|
||||||
|
|
||||||
|
if toolkit == 'windows':
|
||||||
|
EXTRA_COMPONENTS += [
|
||||||
|
'GfxSanityTest.manifest',
|
||||||
|
'SanityTest.js',
|
||||||
|
]
|
||||||
|
|
||||||
|
JAR_MANIFESTS += ['jar.mn']
|
||||||
@@ -28,6 +28,7 @@ DIRS += [
|
|||||||
'finalizationwitness',
|
'finalizationwitness',
|
||||||
'formautofill',
|
'formautofill',
|
||||||
'find',
|
'find',
|
||||||
|
'gfx',
|
||||||
'jsdownloads',
|
'jsdownloads',
|
||||||
'mediasniffer',
|
'mediasniffer',
|
||||||
'microformats',
|
'microformats',
|
||||||
|
|||||||
@@ -655,6 +655,7 @@ nsresult
|
|||||||
GfxInfoBase::Init()
|
GfxInfoBase::Init()
|
||||||
{
|
{
|
||||||
InitGfxDriverInfoShutdownObserver();
|
InitGfxDriverInfoShutdownObserver();
|
||||||
|
gfxPrefs::GetSingleton();
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||||
if (os) {
|
if (os) {
|
||||||
|
|||||||
Reference in New Issue
Block a user