mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c. a=merge
This commit is contained in:
commit
39400dced0
10
addon-sdk/source/app-extension/bootstrap.js
vendored
10
addon-sdk/source/app-extension/bootstrap.js
vendored
@ -50,7 +50,15 @@ function setResourceSubstitution(domain, uri) {
|
||||
function readURI(uri) {
|
||||
let ioservice = Cc['@mozilla.org/network/io-service;1'].
|
||||
getService(Ci.nsIIOService);
|
||||
let channel = ioservice.newChannel(uri, 'UTF-8', null);
|
||||
|
||||
let channel = ioservice.newChannel2(uri,
|
||||
'UTF-8',
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
systemPrincipal,
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = channel.open();
|
||||
|
||||
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
|
||||
|
@ -15,6 +15,7 @@ const IOService = Cc["@mozilla.org/network/io-service;1"].
|
||||
|
||||
const { deprecateFunction } = require('../util/deprecate');
|
||||
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const FaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
|
||||
@ -51,7 +52,14 @@ exports.getFaviconURIForLocation = getFaviconURIForLocation;
|
||||
* @returns {String}
|
||||
*/
|
||||
function getChromeURIContent(chromeURI) {
|
||||
let channel = IOService.newChannel(chromeURI, null, null);
|
||||
let channel = IOService.newChannel2(chromeURI,
|
||||
null,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let input = channel.open();
|
||||
let stream = Cc["@mozilla.org/binaryinputstream;1"].
|
||||
createInstance(Ci.nsIBinaryInputStream);
|
||||
|
@ -8,11 +8,13 @@ module.metadata = {
|
||||
"stability": "experimental"
|
||||
};
|
||||
|
||||
const { Cu, components } = require("chrome");
|
||||
const { Ci, Cu, components } = require("chrome");
|
||||
|
||||
const { defer } = require("../core/promise");
|
||||
const { merge } = require("../util/object");
|
||||
|
||||
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
/**
|
||||
* Reads a URI and returns a promise.
|
||||
@ -33,12 +35,19 @@ function readURI(uri, options) {
|
||||
options = options || {};
|
||||
let charset = options.charset || 'UTF-8';
|
||||
|
||||
let channel = NetUtil.newChannel(uri, charset, null);
|
||||
let channel = NetUtil.newChannel2(uri,
|
||||
charset,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
|
||||
let { promise, resolve, reject } = defer();
|
||||
|
||||
try {
|
||||
NetUtil.asyncFetch(channel, function (stream, result) {
|
||||
NetUtil.asyncFetch2(channel, function (stream, result) {
|
||||
if (components.isSuccessCode(result)) {
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, { charset : charset });
|
||||
@ -74,7 +83,14 @@ exports.readURI = readURI;
|
||||
function readURISync(uri, charset) {
|
||||
charset = typeof charset === "string" ? charset : "UTF-8";
|
||||
|
||||
let channel = NetUtil.newChannel(uri, charset, null);
|
||||
let channel = NetUtil.newChannel2(uri,
|
||||
charset,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = channel.open();
|
||||
|
||||
let count = stream.available();
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
|
||||
const system = require("sdk/system");
|
||||
const file = require("sdk/io/file");
|
||||
@ -12,6 +12,8 @@ const unload = require("sdk/system/unload");
|
||||
// Retrieve the path to the OS temporary directory:
|
||||
const tmpDir = require("sdk/system").pathFor("TmpD");
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// List of all tmp file created
|
||||
let files = [];
|
||||
|
||||
@ -33,7 +35,14 @@ unload.when(function () {
|
||||
// `uri` and returns content string. Read in binary mode.
|
||||
function readBinaryURI(uri) {
|
||||
let ioservice = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||
let channel = ioservice.newChannel(uri, "UTF-8", null);
|
||||
let channel = ioservice.newChannel2(uri,
|
||||
"UTF-8",
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = Cc["@mozilla.org/binaryinputstream;1"].
|
||||
createInstance(Ci.nsIBinaryInputStream);
|
||||
stream.setInputStream(channel.open());
|
||||
|
@ -7,7 +7,7 @@ module.metadata = {
|
||||
"stability": "experimental"
|
||||
};
|
||||
|
||||
const { Cc, Ci, Cr } = require("chrome");
|
||||
const { Cc, Ci, Cr, Cu } = require("chrome");
|
||||
|
||||
const { Class } = require("./core/heritage");
|
||||
const base64 = require("./base64");
|
||||
@ -23,6 +23,8 @@ var resProt = ios.getProtocolHandler("resource")
|
||||
var URLParser = Cc["@mozilla.org/network/url-parser;1?auth=no"]
|
||||
.getService(Ci.nsIURLParser);
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function newURI(uriStr, base) {
|
||||
try {
|
||||
let baseURI = base ? ios.newURI(base, null, null) : null;
|
||||
@ -64,7 +66,12 @@ let toFilename = exports.toFilename = function toFilename(url) {
|
||||
if (uri.scheme == "resource")
|
||||
uri = newURI(resolveResourceURI(uri));
|
||||
if (uri.scheme == "chrome") {
|
||||
var channel = ios.newChannelFromURI(uri);
|
||||
var channel = ios.newChannelFromURI2(uri,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
try {
|
||||
channel = channel.QueryInterface(Ci.nsIFileChannel);
|
||||
return channel.file.path;
|
||||
|
@ -172,7 +172,14 @@ function serializeStack(frames) {
|
||||
exports.serializeStack = serializeStack;
|
||||
|
||||
function readURI(uri) {
|
||||
let stream = NetUtil.newChannel(uri, 'UTF-8', null).open();
|
||||
let stream = NetUtil.newChannel2(uri,
|
||||
'UTF-8',
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
systemPrincipal,
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER).open();
|
||||
let count = stream.available();
|
||||
let data = NetUtil.readInputStreamToString(stream, count, {
|
||||
charset: 'UTF-8'
|
||||
|
@ -26,6 +26,7 @@ const appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
|
||||
getService(Ci.nsIVersionComparator);
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
|
||||
'install', 'uninstall', 'upgrade', 'downgrade' ];
|
||||
@ -42,7 +43,14 @@ let nukeTimer = null;
|
||||
function readURI(uri) {
|
||||
let ioservice = Cc['@mozilla.org/network/io-service;1'].
|
||||
getService(Ci.nsIIOService);
|
||||
let channel = ioservice.newChannel(uri, 'UTF-8', null);
|
||||
let channel = ioservice.newChannel2(uri,
|
||||
'UTF-8',
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = channel.open();
|
||||
|
||||
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
|
||||
|
@ -26,6 +26,7 @@ const appInfo = Cc["@mozilla.org/xre/app-info;1"].
|
||||
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
|
||||
getService(Ci.nsIVersionComparator);
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const REASON = [ 'unknown', 'startup', 'shutdown', 'enable', 'disable',
|
||||
'install', 'uninstall', 'upgrade', 'downgrade' ];
|
||||
@ -42,7 +43,14 @@ let nukeTimer = null;
|
||||
function readURI(uri) {
|
||||
let ioservice = Cc['@mozilla.org/network/io-service;1'].
|
||||
getService(Ci.nsIIOService);
|
||||
let channel = ioservice.newChannel(uri, 'UTF-8', null);
|
||||
let channel = ioservice.newChannel2(uri,
|
||||
'UTF-8',
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
let stream = channel.open();
|
||||
|
||||
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
|
||||
|
@ -66,7 +66,14 @@ exports.testIsPrivateBrowsingFalseDefault = function(assert) {
|
||||
};
|
||||
|
||||
exports.testNSIPrivateBrowsingChannel = function(assert) {
|
||||
let channel = Services.io.newChannel("about:blank", null, null);
|
||||
let channel = Services.io.newChannel2("about:blank",
|
||||
null,
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
channel.QueryInterface(Ci.nsIPrivateBrowsingChannel);
|
||||
assert.equal(isPrivate(channel), false, 'isPrivate detects non-private channels');
|
||||
channel.setPrivate(true);
|
||||
|
@ -132,10 +132,15 @@ function testRegister(assert, text) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
|
||||
var channel = ios.newChannel(
|
||||
var channel = ios.newChannel2(
|
||||
"data:text/plain;charset=utf-8," + text,
|
||||
null,
|
||||
null
|
||||
null,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER
|
||||
);
|
||||
|
||||
channel.originalURI = aURI;
|
||||
@ -162,7 +167,12 @@ function testRegister(assert, text) {
|
||||
);
|
||||
|
||||
var aboutURI = ios.newURI("about:boop", null, null);
|
||||
var channel = ios.newChannelFromURI(aboutURI);
|
||||
var channel = ios.newChannelFromURI2(aboutURI,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
var iStream = channel.open();
|
||||
var siStream = Cc['@mozilla.org/scriptableinputstream;1']
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
@ -1182,6 +1182,12 @@ pref("browser.tabs.remote.desktopbehavior", true);
|
||||
// This will require a restart.
|
||||
pref("security.sandbox.windows.log", false);
|
||||
|
||||
// Controls whether the Windows NPAPI plugin process is sandboxed by default.
|
||||
// To get a different setting for a particular plugin replace "default", with
|
||||
// the plugin's nice file name, see: nsPluginTag::GetNiceFileName.
|
||||
pref("dom.ipc.plugins.sandbox.default", false);
|
||||
pref("dom.ipc.plugins.sandbox.flash", false);
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
// This controls whether the Windows content process sandbox is using a more
|
||||
// strict sandboxing policy. This will require a restart.
|
||||
@ -1803,7 +1809,14 @@ pref("dom.ipc.cpow.timeout", 500);
|
||||
// Enable e10s hang monitoring (slow script checking and plugin hang
|
||||
// detection).
|
||||
pref("dom.ipc.processHangMonitor", true);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Don't report hangs in DEBUG builds. They're too slow and often a
|
||||
// debugger is attached.
|
||||
pref("dom.ipc.reportProcessHangs", false);
|
||||
#else
|
||||
pref("dom.ipc.reportProcessHangs", true);
|
||||
#endif
|
||||
|
||||
// Disable reader mode by default.
|
||||
pref("reader.parse-on-load.enabled", false);
|
||||
|
@ -653,7 +653,7 @@ function runTest(testNum) {
|
||||
"context-cut", false,
|
||||
"context-copy", false,
|
||||
"context-paste", null, // ignore clipboard state
|
||||
"context-delete", false,
|
||||
"context-delete", true,
|
||||
"---", null,
|
||||
"context-selectall", true,
|
||||
"---", null,
|
||||
|
@ -9,7 +9,7 @@ Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
var stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://browser/locale/aboutPrivateBrowsing.properties");
|
||||
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
|
||||
document.title = stringBundle.GetStringFromName("title.normal");
|
||||
setFavIcon("chrome://global/skin/icons/question-16.png");
|
||||
} else {
|
||||
@ -34,7 +34,7 @@ function setFavIcon(url) {
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
|
||||
document.body.setAttribute("class", "normal");
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ add_task(function*() {
|
||||
let {toolbox, inspector, view} = yield openRuleView();
|
||||
|
||||
let value = getRuleViewProperty(view, "body", "background").valueSpan;
|
||||
let swatch = value.querySelector(".ruleview-colorswatch");
|
||||
let swatch = value.querySelectorAll(".ruleview-colorswatch")[1];
|
||||
let url = value.querySelector(".theme-link");
|
||||
yield testImageTooltipAfterColorChange(swatch, url, view);
|
||||
});
|
||||
|
@ -167,7 +167,7 @@ function* testParagraph(inspector, view) {
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementFirstLineRule.textProps),
|
||||
"background: none repeat scroll 0% 0% blue",
|
||||
"background: blue none repeat scroll 0% 0%",
|
||||
"Paragraph first-line properties are correct"
|
||||
);
|
||||
|
||||
@ -191,7 +191,7 @@ function* testParagraph(inspector, view) {
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementSelectionRule.textProps),
|
||||
"color: white; background: none repeat scroll 0% 0% black",
|
||||
"color: white; background: black none repeat scroll 0% 0%",
|
||||
"Paragraph first-letter properties are correct"
|
||||
);
|
||||
}
|
||||
@ -244,4 +244,4 @@ function assertGutters(view) {
|
||||
is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
|
||||
|
||||
return gutters;
|
||||
}
|
||||
}
|
||||
|
@ -96,14 +96,14 @@ function* testPropertyChange5(inspector, ruleView, testElement) {
|
||||
|
||||
function* testPropertyChange6(inspector, ruleView, testElement) {
|
||||
info("Add an entirely new property again");
|
||||
yield changeElementStyle(testElement, "background: url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red", inspector);
|
||||
yield changeElementStyle(testElement, "background: red url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%", inspector);
|
||||
|
||||
let rule = ruleView._elementStyle.rules[0];
|
||||
is(rule.editor.element.querySelectorAll(".ruleview-property").length, 5, "Added a property");
|
||||
validateTextProp(rule.textProps[4], true, "background",
|
||||
"url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red",
|
||||
"red url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%",
|
||||
"shortcut property correctly set",
|
||||
"url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% #F00");
|
||||
"#F00 url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%");
|
||||
}
|
||||
|
||||
function* changeElementStyle(testElement, style, inspector) {
|
||||
|
@ -74,12 +74,18 @@ private:
|
||||
virtual void run(const MatchFinder::MatchResult &Result);
|
||||
};
|
||||
|
||||
class NoAddRefReleaseOnReturnChecker : public MatchFinder::MatchCallback {
|
||||
public:
|
||||
virtual void run(const MatchFinder::MatchResult &Result);
|
||||
};
|
||||
|
||||
ScopeChecker stackClassChecker;
|
||||
ScopeChecker globalClassChecker;
|
||||
NonHeapClassChecker nonheapClassChecker;
|
||||
ArithmeticArgChecker arithmeticArgChecker;
|
||||
TrivialCtorDtorChecker trivialCtorDtorChecker;
|
||||
NaNExprChecker nanExprChecker;
|
||||
NoAddRefReleaseOnReturnChecker noAddRefReleaseOnReturnChecker;
|
||||
MatchFinder astMatcher;
|
||||
};
|
||||
|
||||
@ -389,6 +395,12 @@ AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) {
|
||||
return MozChecker::hasCustomAnnotation(&Node, "moz_trivial_ctor_dtor");
|
||||
}
|
||||
|
||||
/// This matcher will match any function declaration that is marked to prohibit
|
||||
/// calling AddRef or Release on its return value.
|
||||
AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) {
|
||||
return MozChecker::hasCustomAnnotation(&Node, "moz_no_addref_release_on_return");
|
||||
}
|
||||
|
||||
/// This matcher will match all arithmetic binary operators.
|
||||
AST_MATCHER(BinaryOperator, binaryArithmeticOperator) {
|
||||
BinaryOperatorKind opcode = Node.getOpcode();
|
||||
@ -458,6 +470,17 @@ AST_MATCHER(BinaryOperator, isInSkScalarDotH) {
|
||||
return llvm::sys::path::rbegin(FileName)->equals("SkScalar.h");
|
||||
}
|
||||
|
||||
/// This matcher will match all accesses to AddRef or Release methods.
|
||||
AST_MATCHER(MemberExpr, isAddRefOrRelease) {
|
||||
ValueDecl *Member = Node.getMemberDecl();
|
||||
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member);
|
||||
if (Method) {
|
||||
std::string Name = Method->getNameAsString();
|
||||
return Name == "AddRef" || Name == "Release";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,6 +571,12 @@ DiagnosticsMatcher::DiagnosticsMatcher()
|
||||
unless(anyOf(isInSystemHeader(), isInSkScalarDotH()))
|
||||
)).bind("node"),
|
||||
&nanExprChecker);
|
||||
|
||||
astMatcher.addMatcher(callExpr(callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
|
||||
hasParent(memberExpr(isAddRefOrRelease(),
|
||||
hasParent(callExpr())).bind("member")
|
||||
)).bind("node"),
|
||||
&noAddRefReleaseOnReturnChecker);
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::ScopeChecker::run(
|
||||
@ -733,6 +762,19 @@ void DiagnosticsMatcher::NaNExprChecker::run(
|
||||
}
|
||||
}
|
||||
|
||||
void DiagnosticsMatcher::NoAddRefReleaseOnReturnChecker::run(
|
||||
const MatchFinder::MatchResult &Result) {
|
||||
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
|
||||
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Error, "%1 cannot be called on the return value of %0");
|
||||
const Stmt *node = Result.Nodes.getNodeAs<Stmt>("node");
|
||||
const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func");
|
||||
const MemberExpr *member = Result.Nodes.getNodeAs<MemberExpr>("member");
|
||||
const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(member->getMemberDecl());
|
||||
|
||||
Diag.Report(node->getLocStart(), errorID) << func << method;
|
||||
}
|
||||
|
||||
class MozCheckAction : public PluginASTAction {
|
||||
public:
|
||||
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override {
|
||||
|
@ -3,9 +3,9 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Build without any warning flags, and with clang verify flag for a
|
||||
# syntax-only build (no codegen).
|
||||
OS_CFLAGS := $(filter-out -W%,$(OS_CFLAGS)) -fsyntax-only -Xclang -verify
|
||||
OS_CXXFLAGS := $(filter-out -W%,$(OS_CXXFLAGS)) -fsyntax-only -Xclang -verify
|
||||
# syntax-only build (no codegen), without a limit on the number of errors.
|
||||
OS_CFLAGS := $(filter-out -W%,$(OS_CFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0
|
||||
OS_CXXFLAGS := $(filter-out -W%,$(OS_CXXFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
65
build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp
Normal file
65
build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
|
||||
|
||||
struct Test {
|
||||
void AddRef();
|
||||
void Release();
|
||||
void foo();
|
||||
};
|
||||
|
||||
struct S {
|
||||
Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
Test h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct X {
|
||||
T* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
T& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
T h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct SP {
|
||||
T* operator->() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
};
|
||||
|
||||
Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
Test h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
|
||||
|
||||
void test() {
|
||||
S s;
|
||||
s.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
|
||||
s.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
|
||||
s.f()->foo();
|
||||
s.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
|
||||
s.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
|
||||
s.g().foo();
|
||||
s.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
|
||||
s.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
|
||||
s.h().foo();
|
||||
X<Test> x;
|
||||
x.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
|
||||
x.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
|
||||
x.f()->foo();
|
||||
x.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
|
||||
x.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
|
||||
x.g().foo();
|
||||
x.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
|
||||
x.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
|
||||
x.h().foo();
|
||||
SP<Test> sp;
|
||||
sp->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'operator->'}}
|
||||
sp->Release(); // expected-error{{'Release' cannot be called on the return value of 'operator->'}}
|
||||
sp->foo();
|
||||
f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
|
||||
f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
|
||||
f()->foo();
|
||||
g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
|
||||
g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
|
||||
g().foo();
|
||||
h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
|
||||
h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
|
||||
h().foo();
|
||||
}
|
@ -11,6 +11,7 @@ SOURCES += [
|
||||
'TestMustOverride.cpp',
|
||||
'TestNANTestingExpr.cpp',
|
||||
'TestNANTestingExprC.c',
|
||||
'TestNoAddRefReleaseOnReturn.cpp',
|
||||
'TestNoArithmeticExprInArgument.cpp',
|
||||
'TestNonHeapClass.cpp',
|
||||
'TestStackClass.cpp',
|
||||
|
@ -3595,7 +3595,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
|
||||
_USE_SYSTEM_NSS=1 )
|
||||
|
||||
if test -n "$_USE_SYSTEM_NSS"; then
|
||||
AM_PATH_NSS(3.17.3, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
AM_PATH_NSS(3.17.4, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_NATIVE_NSS"; then
|
||||
|
@ -75,8 +75,8 @@ public:
|
||||
|
||||
JSObject* GetStack()
|
||||
{
|
||||
if (mStackTrace) {
|
||||
return mStackTrace->get();
|
||||
if (mStackTrace.initialized()) {
|
||||
return mStackTrace;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -89,7 +89,7 @@ protected:
|
||||
if (ctx) {
|
||||
JS::RootedObject stack(ctx);
|
||||
if (JS::CaptureCurrentStack(ctx, &stack)) {
|
||||
mStackTrace.emplace(ctx, stack.get());
|
||||
mStackTrace.init(ctx, stack.get());
|
||||
} else {
|
||||
JS_ClearPendingException(ctx);
|
||||
}
|
||||
@ -107,7 +107,7 @@ private:
|
||||
// in this case changing nsDocShell to participate in cycle
|
||||
// collection was deemed too invasive, and the markers are only held
|
||||
// here temporarily to boot.
|
||||
mozilla::Maybe<JS::PersistentRooted<JSObject*>> mStackTrace;
|
||||
JS::PersistentRooted<JSObject*> mStackTrace;
|
||||
};
|
||||
|
||||
#endif /* TimelineMarker_h__ */
|
||||
|
@ -8216,14 +8216,6 @@ nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, bool *aRestoring)
|
||||
|
||||
SetHistoryEntry(&mLSHE, aSHEntry);
|
||||
|
||||
// Add the request to our load group. We do this before swapping out
|
||||
// the content viewers so that consumers of STATE_START can access
|
||||
// the old document. We only deal with the toplevel load at this time --
|
||||
// to be consistent with normal document loading, subframes cannot start
|
||||
// loading until after data arrives, which is after STATE_START completes.
|
||||
|
||||
BeginRestore(viewer, true);
|
||||
|
||||
// Post an event that will remove the request after we've returned
|
||||
// to the event loop. This mimics the way it is called by nsIChannel
|
||||
// implementations.
|
||||
@ -8245,10 +8237,40 @@ nsDocShell::RestorePresentation(nsISHEntry *aSHEntry, bool *aRestoring)
|
||||
return rv;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class MOZ_STACK_CLASS PresentationEventForgetter
|
||||
{
|
||||
public:
|
||||
explicit PresentationEventForgetter(
|
||||
nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& aRestorePresentationEvent)
|
||||
: mRestorePresentationEvent(aRestorePresentationEvent)
|
||||
, mEvent(aRestorePresentationEvent.get())
|
||||
{
|
||||
}
|
||||
|
||||
~PresentationEventForgetter()
|
||||
{
|
||||
Forget();
|
||||
}
|
||||
|
||||
void Forget()
|
||||
{
|
||||
if (mRestorePresentationEvent.get() == mEvent) {
|
||||
mRestorePresentationEvent.Forget();
|
||||
mEvent = nullptr;
|
||||
}
|
||||
}
|
||||
private:
|
||||
nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>& mRestorePresentationEvent;
|
||||
nsRefPtr<nsDocShell::RestorePresentationEvent> mEvent;
|
||||
};
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::RestoreFromHistory()
|
||||
{
|
||||
mRestorePresentationEvent.Forget();
|
||||
MOZ_ASSERT(mRestorePresentationEvent.IsPending());
|
||||
PresentationEventForgetter forgetter(mRestorePresentationEvent);
|
||||
|
||||
// This section of code follows the same ordering as CreateContentViewer.
|
||||
if (!mLSHE)
|
||||
@ -8302,6 +8324,24 @@ nsDocShell::RestoreFromHistory()
|
||||
if (mLSHE != origLSHE)
|
||||
return NS_OK;
|
||||
|
||||
// Add the request to our load group. We do this before swapping out
|
||||
// the content viewers so that consumers of STATE_START can access
|
||||
// the old document. We only deal with the toplevel load at this time --
|
||||
// to be consistent with normal document loading, subframes cannot start
|
||||
// loading until after data arrives, which is after STATE_START completes.
|
||||
|
||||
nsRefPtr<RestorePresentationEvent> currentPresentationRestoration =
|
||||
mRestorePresentationEvent.get();
|
||||
Stop();
|
||||
// Make sure we're still restoring the same presentation.
|
||||
// If we aren't, docshell is in process doing another load already.
|
||||
NS_ENSURE_STATE(currentPresentationRestoration ==
|
||||
mRestorePresentationEvent.get());
|
||||
BeginRestore(viewer, true);
|
||||
NS_ENSURE_STATE(currentPresentationRestoration ==
|
||||
mRestorePresentationEvent.get());
|
||||
forgetter.Forget();
|
||||
|
||||
// Set mFiredUnloadEvent = false so that the unload handler for the
|
||||
// *new* document will fire.
|
||||
mFiredUnloadEvent = false;
|
||||
|
@ -693,6 +693,7 @@ protected:
|
||||
*/
|
||||
void MaybeInitTiming();
|
||||
|
||||
public:
|
||||
// Event type dispatched by RestorePresentation
|
||||
class RestorePresentationEvent : public nsRunnable {
|
||||
public:
|
||||
@ -702,6 +703,7 @@ protected:
|
||||
private:
|
||||
nsRefPtr<nsDocShell> mDocShell;
|
||||
};
|
||||
protected:
|
||||
|
||||
bool JustStartedNetworkLoad();
|
||||
|
||||
|
@ -105,3 +105,5 @@ support-files = file_framedhistoryframes.html
|
||||
[test_pushState_after_document_open.html]
|
||||
[test_windowedhistoryframes.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug1121701.html]
|
||||
skip-if = (buildapp == 'b2g' || buildapp == 'mulet')
|
||||
|
71
docshell/test/test_bug1121701.html
Normal file
71
docshell/test/test_bug1121701.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1121701
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1121701</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1121701 **/
|
||||
|
||||
var testUrl1 = "data:text/html,<script>window.onpageshow = function(e) { opener.child1PageShow(e); } <" + "/script>";
|
||||
var testUrl2 = "data:text/html,<script>window.onpageshow = function(e) { opener.child2PageShow(e); } <" + "/script>";
|
||||
var testWin;
|
||||
|
||||
var page1LoadCount = 0;
|
||||
function child1PageShow(e) {
|
||||
++page1LoadCount;
|
||||
if (page1LoadCount == 1) {
|
||||
SimpleTest.executeSoon(function() {
|
||||
is(e.persisted, false, "Initial page load shouldn't be persisted.");
|
||||
testWin.document.body.innerHTML = "modified";
|
||||
testWin.onpagehide = function(e) {
|
||||
testWin.onpagehide = null;
|
||||
ok(e.persisted, "test page 1 should have been persisted");
|
||||
is(testWin.document.body.innerHTML, "modified");
|
||||
}
|
||||
testWin.location.href = testUrl2;
|
||||
});
|
||||
} else if (page1LoadCount == 2) {
|
||||
is(e.persisted, true, "Page load from bfcache should be persisted.");
|
||||
is(testWin.document.body.innerHTML, "modified");
|
||||
testWin.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function child2PageShow(e) {
|
||||
testWin.document.body.innerHTML = "<img>";
|
||||
SimpleTest.executeSoon(function() {
|
||||
testWin.onmessage = function() {
|
||||
ok(true, "Got message");
|
||||
testWin.document.body.firstChild.src = location.href;
|
||||
}
|
||||
testWin.onbeforeunload = function() {
|
||||
testWin.postMessage("foo", "*");
|
||||
}
|
||||
testWin.history.back();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
testWin = window.open(testUrl1);
|
||||
});
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121701">Mozilla Bug 1121701</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -509,6 +509,7 @@ this.PermissionsTable = { geolocation: {
|
||||
},
|
||||
"tv": {
|
||||
app: DENY_ACTION,
|
||||
trusted: DENY_ACTION,
|
||||
privileged: DENY_ACTION,
|
||||
certified: ALLOW_ACTION
|
||||
},
|
||||
|
@ -1268,7 +1268,7 @@ Console::ProcessCallData(ConsoleCallData* aData)
|
||||
innerID.AppendInt(aData->mInnerIDNumber);
|
||||
}
|
||||
|
||||
if (NS_FAILED(mStorage->RecordPendingEvent(innerID, outerID, eventValue))) {
|
||||
if (NS_FAILED(mStorage->RecordEvent(innerID, outerID, eventValue))) {
|
||||
NS_WARNING("Failed to record a console event.");
|
||||
}
|
||||
}
|
||||
|
@ -11,18 +11,12 @@ let Cc = Components.classes;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// The console API events have to be scheduled when stored using
|
||||
// |recordPendingEvent|.
|
||||
const CALL_DELAY = 15 // milliseconds
|
||||
|
||||
// This constant tells how many messages to process in a single timer execution.
|
||||
const MESSAGES_IN_INTERVAL = 1500
|
||||
|
||||
const STORAGE_MAX_EVENTS = 200;
|
||||
|
||||
var _consoleStorage = new Map();
|
||||
var _consolePendingStorage = new Map();
|
||||
var _timer;
|
||||
|
||||
const CONSOLEAPISTORAGE_CID = Components.ID('{96cf7855-dfa9-4c6d-8276-f9705b4890f2}');
|
||||
|
||||
@ -141,51 +135,6 @@ ConsoleAPIStorageService.prototype = {
|
||||
Services.obs.notifyObservers(aEvent, "console-storage-cache-event", aId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Similar to recordEvent, but these events are scheduled and stored any
|
||||
* CALL_DELAY millisecs.
|
||||
*/
|
||||
recordPendingEvent: function CS_recordPendingEvent(aId, aOuterId, aEvent)
|
||||
{
|
||||
if (!_consolePendingStorage.has(aId)) {
|
||||
_consolePendingStorage.set(aId, []);
|
||||
}
|
||||
|
||||
let storage = _consolePendingStorage.get(aId);
|
||||
storage.push({ outerId: aOuterId, event: aEvent });
|
||||
|
||||
if (!_timer) {
|
||||
_timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
_timer.initWithCallback(function() { self.flushPendingEvents(); },
|
||||
CALL_DELAY, Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
},
|
||||
|
||||
/**
|
||||
* Processes the pending event queue.
|
||||
*/
|
||||
flushPendingEvents: function CS_flushPendingEvents()
|
||||
{
|
||||
for (let [id, objs] of _consolePendingStorage) {
|
||||
for (let i = 0; i < objs.length && i < MESSAGES_IN_INTERVAL; ++i) {
|
||||
this.recordEvent(id, objs[i].outerId, objs[i].event);
|
||||
}
|
||||
|
||||
if (objs.length <= MESSAGES_IN_INTERVAL) {
|
||||
_consolePendingStorage.delete(id);
|
||||
} else {
|
||||
_consolePendingStorage.set(id, objs.splice(MESSAGES_IN_INTERVAL));
|
||||
}
|
||||
}
|
||||
|
||||
if (_timer && _consolePendingStorage.size == 0) {
|
||||
_timer.cancel();
|
||||
_timer = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
|
@ -2553,7 +2553,7 @@ IsVoidTag(nsIAtom* aTag)
|
||||
static const nsIAtom* voidElements[] = {
|
||||
nsGkAtoms::area, nsGkAtoms::base, nsGkAtoms::basefont,
|
||||
nsGkAtoms::bgsound, nsGkAtoms::br, nsGkAtoms::col,
|
||||
nsGkAtoms::command, nsGkAtoms::embed, nsGkAtoms::frame,
|
||||
nsGkAtoms::embed, nsGkAtoms::frame,
|
||||
nsGkAtoms::hr, nsGkAtoms::img, nsGkAtoms::input,
|
||||
nsGkAtoms::keygen, nsGkAtoms::link, nsGkAtoms::meta,
|
||||
nsGkAtoms::param, nsGkAtoms::source, nsGkAtoms::track,
|
||||
|
@ -47,9 +47,6 @@
|
||||
#include "nsStringBuffer.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
|
||||
@ -324,34 +321,19 @@ nsDocumentEncoder::IncludeInContext(nsINode *aNode)
|
||||
static
|
||||
bool
|
||||
IsInvisibleBreak(nsINode *aNode) {
|
||||
// xxxehsan: we should probably figure out a way to determine
|
||||
// if a BR node is visible without using the editor.
|
||||
Element* elt = aNode->AsElement();
|
||||
if (!elt->IsHTML(nsGkAtoms::br) ||
|
||||
!aNode->IsEditable()) {
|
||||
if (!aNode->IsElement() || !aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
|
||||
if (!frame || frame->GetType() != nsGkAtoms::brFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the editor associated with the document
|
||||
nsIDocument *doc = aNode->GetComposedDoc();
|
||||
if (doc) {
|
||||
nsPIDOMWindow *window = doc->GetWindow();
|
||||
if (window) {
|
||||
nsIDocShell *docShell = window->GetDocShell();
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
docShell->GetEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (htmlEditor) {
|
||||
bool isVisible = false;
|
||||
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
|
||||
htmlEditor->BreakIsVisible(domNode, &isVisible);
|
||||
return !isVisible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// If the BRFrame has caused a visible line break, it should have a next
|
||||
// sibling, or otherwise no siblings and a non-zero height.
|
||||
bool visible = frame->GetNextSibling() ||
|
||||
(!frame->GetPrevSibling() && frame->GetRect().Height() != 0);
|
||||
return !visible;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(cce39123-585e-411b-9edd-2513f7cf7e47)]
|
||||
[scriptable, uuid(9e32a7b6-c4d1-4d9a-87b9-1ef6b75c27a9)]
|
||||
interface nsIConsoleAPIStorage : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -35,22 +35,6 @@ interface nsIConsoleAPIStorage : nsISupports
|
||||
*/
|
||||
void recordEvent(in DOMString aId, in DOMString aOuterId, in jsval aEvent);
|
||||
|
||||
/**
|
||||
* Similar to recordEvent() but these events will be collected
|
||||
* and dispatched with a timer in order to avoid flooding the devtools
|
||||
* webconsole.
|
||||
*
|
||||
* @param string aId
|
||||
* The ID of the inner window for which the event occurred or "jsm" for
|
||||
* messages logged from JavaScript modules..
|
||||
* @param string aOuterId
|
||||
* This ID is used as 3rd parameters for the console-api-log-event
|
||||
* notification.
|
||||
* @param object aEvent
|
||||
* A JavaScript object you want to store.
|
||||
*/
|
||||
void recordPendingEvent(in DOMString aId, in DOMString aOuterId, in jsval aEvent);
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
|
@ -32,7 +32,7 @@ class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsPlainTextSerializer : public nsIContentSerializer
|
||||
class nsPlainTextSerializer MOZ_FINAL : public nsIContentSerializer
|
||||
{
|
||||
public:
|
||||
nsPlainTextSerializer();
|
||||
@ -67,8 +67,8 @@ public:
|
||||
NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument,
|
||||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~nsPlainTextSerializer();
|
||||
private:
|
||||
~nsPlainTextSerializer();
|
||||
|
||||
nsresult GetAttributeValue(nsIAtom* aName, nsString& aValueRet);
|
||||
void AddToLine(const char16_t* aStringToAdd, int32_t aLength);
|
||||
@ -114,10 +114,9 @@ protected:
|
||||
|
||||
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
|
||||
|
||||
private:
|
||||
bool IsElementPreformatted(mozilla::dom::Element* aElement);
|
||||
|
||||
protected:
|
||||
private:
|
||||
nsString mCurrentLine;
|
||||
uint32_t mHeadLevel;
|
||||
bool mAtFirstColumn;
|
||||
|
@ -53,7 +53,6 @@ nsIAtom** const kElementsHTML[] = {
|
||||
&nsGkAtoms::code,
|
||||
&nsGkAtoms::col,
|
||||
&nsGkAtoms::colgroup,
|
||||
&nsGkAtoms::command,
|
||||
&nsGkAtoms::datalist,
|
||||
&nsGkAtoms::dd,
|
||||
&nsGkAtoms::del,
|
||||
|
@ -48,7 +48,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=525816
|
||||
(function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestLongerTimeout(TestRequests.length);
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
SimpleTest.requestFlakyTimeout("This is testing XHR timeouts.");
|
||||
var msg = "This test will take approximately " + (TestRequests.length * 10)
|
||||
msg += " seconds to complete, at most.";
|
||||
document.getElementById("content").firstChild.nodeValue = msg;
|
||||
|
@ -99,7 +99,8 @@ DOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
|
||||
void
|
||||
DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
|
||||
{
|
||||
if (mParentObject) {
|
||||
nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
|
||||
if (parentObject) {
|
||||
if (mOwnerWindow) {
|
||||
static_cast<nsGlobalWindow*>(mOwnerWindow)->RemoveEventTargetObject(this);
|
||||
mOwnerWindow = nullptr;
|
||||
@ -108,7 +109,8 @@ DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
|
||||
mHasOrHasHadOwnerWindow = false;
|
||||
}
|
||||
if (aOwner) {
|
||||
mParentObject = aOwner;
|
||||
mParentObject = do_GetWeakReference(aOwner);
|
||||
MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOwner)).get();
|
||||
if (mOwnerWindow) {
|
||||
@ -131,9 +133,10 @@ DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther)
|
||||
if (aOther) {
|
||||
mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
|
||||
if (aOther->GetParentObject()) {
|
||||
mParentObject = aOther->GetParentObject();
|
||||
mParentObject = do_GetWeakReference(aOther->GetParentObject());
|
||||
MOZ_ASSERT(mParentObject, "All nsIGlobalObjects must support nsISupportsWeakReference");
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(mParentObject)).get();
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindow>(do_QueryInterface(aOther->GetParentObject())).get();
|
||||
if (mOwnerWindow) {
|
||||
MOZ_ASSERT(mOwnerWindow->IsInnerWindow());
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
@ -138,7 +139,10 @@ public:
|
||||
void BindToOwner(nsPIDOMWindow* aOwner);
|
||||
void BindToOwner(DOMEventTargetHelper* aOther);
|
||||
virtual void DisconnectFromOwner();
|
||||
nsIGlobalObject* GetParentObject() const { return mParentObject; }
|
||||
nsIGlobalObject* GetParentObject() const {
|
||||
nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
|
||||
return parentObject;
|
||||
}
|
||||
bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
|
||||
|
||||
virtual void EventListenerAdded(nsIAtom* aType) MOZ_OVERRIDE;
|
||||
@ -164,10 +168,11 @@ protected:
|
||||
virtual void LastRelease() {}
|
||||
private:
|
||||
// Inner window or sandbox.
|
||||
nsIGlobalObject* mParentObject;
|
||||
nsWeakPtr mParentObject;
|
||||
// mParentObject pre QI-ed and cached (inner window)
|
||||
// (it is needed for off main thread access)
|
||||
nsPIDOMWindow* mOwnerWindow;
|
||||
// It is obtained in BindToOwner and reset in DisconnectFromOwner.
|
||||
nsPIDOMWindow* MOZ_NON_OWNING_REF mOwnerWindow;
|
||||
bool mHasOrHasHadOwnerWindow;
|
||||
};
|
||||
|
||||
|
@ -362,6 +362,20 @@ Event::GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EventTarget*
|
||||
Event::GetComposedTarget() const
|
||||
{
|
||||
EventTarget* et = GetOriginalTarget();
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(et);
|
||||
if (!content) {
|
||||
return et;
|
||||
}
|
||||
nsIContent* nonChrome = content->FindFirstNonChromeOnlyAccessContent();
|
||||
return nonChrome ?
|
||||
static_cast<EventTarget*>(nonChrome) :
|
||||
static_cast<EventTarget*>(content->GetComposedDoc());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
Event::SetTrusted(bool aTrusted)
|
||||
{
|
||||
|
@ -205,6 +205,7 @@ public:
|
||||
|
||||
EventTarget* GetOriginalTarget() const;
|
||||
EventTarget* GetExplicitOriginalTarget() const;
|
||||
EventTarget* GetComposedTarget() const;
|
||||
|
||||
bool GetPreventDefault() const;
|
||||
|
||||
|
@ -138,6 +138,7 @@ skip-if = toolkit == "gonk" || e10s
|
||||
support-files = bug1017086_inner.html
|
||||
[test_bug1017086_enable.html]
|
||||
support-files = bug1017086_inner.html
|
||||
[test_bug1079236.html]
|
||||
[test_clickevent_on_input.html]
|
||||
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||
[test_continuous_wheel_events.html]
|
||||
|
60
dom/events/test/test_bug1079236.html
Normal file
60
dom/events/test/test_bug1079236.html
Normal file
@ -0,0 +1,60 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1079236
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1079236</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1079236 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function runTests() {
|
||||
var c = document.getElementById("content");
|
||||
var sr = c.createShadowRoot();
|
||||
sr.innerHTML = "<input type='file'" + ">";
|
||||
var file = sr.firstChild;
|
||||
is(file.type, "file");
|
||||
file.offsetLeft; // Flush layout because dispatching mouse events.
|
||||
document.body.onmousemove = function(e) {
|
||||
is(e.target, c, "Event target should be the element in non-Shadow DOM");
|
||||
if (e.originalTarget == file) {
|
||||
is(e.originalTarget, file,
|
||||
"type='file' implementation doesn't seem to have native anonymous content");
|
||||
} else {
|
||||
var wrapped = SpecialPowers.wrap(e.originalTarget);
|
||||
isnot(wrapped, file, "Shouldn't have the same event.target and event.originalTarget");
|
||||
}
|
||||
|
||||
ok(!("composedTarget" in e), "Events shouldn't have composedTarget in non-chrome context!");
|
||||
e = SpecialPowers.wrap(e);
|
||||
var composedTarget = SpecialPowers.unwrap(e.composedTarget);
|
||||
ok(composedTarget, file, "composedTarget should be the file object.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var r = file.getBoundingClientRect();
|
||||
synthesizeMouse(file, r.width / 6, r.height / 2, { type: "mousemove"} );
|
||||
document.body.onmousemove = null;
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1079236">Mozilla Bug 1079236</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -10,9 +10,12 @@ EXPORTS += [
|
||||
'nsGeoPositionIPCSerialiser.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'nsGeolocation.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsGeoGridFuzzer.cpp',
|
||||
'nsGeolocation.cpp',
|
||||
'nsGeolocationSettings.cpp',
|
||||
'nsGeoPosition.cpp',
|
||||
]
|
||||
@ -45,4 +48,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/system/mac',
|
||||
]
|
||||
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/system/windows',
|
||||
]
|
||||
|
@ -49,6 +49,10 @@ class nsIPrincipal;
|
||||
#include "CoreLocationLocationProvider.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "WindowsLocationProvider.h"
|
||||
#endif
|
||||
|
||||
// Some limit to the number of get or watch geolocation requests
|
||||
// that a window can make.
|
||||
#define MAX_GEO_REQUESTS_PER_WINDOW 1500
|
||||
@ -810,6 +814,12 @@ nsresult nsGeolocationService::Init()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (Preferences::GetBool("geo.provider.ms-windows-location", false)) {
|
||||
mProvider = new WindowsLocationProvider();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Preferences::GetBool("geo.provider.use_mls", false)) {
|
||||
mProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
|
||||
}
|
||||
|
@ -193,6 +193,18 @@ HTMLAnchorElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsNodeInEditableRegion(nsINode* aNode)
|
||||
{
|
||||
while (aNode) {
|
||||
if (aNode->IsEditable()) {
|
||||
return true;
|
||||
}
|
||||
aNode = aNode->GetParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse,
|
||||
bool *aIsFocusable, int32_t *aTabIndex)
|
||||
@ -214,7 +226,9 @@ HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse,
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEditable()) {
|
||||
// Links that are in an editable region should never be focusable, even if
|
||||
// they are in a contenteditable="false" region.
|
||||
if (IsNodeInEditableRegion(this)) {
|
||||
if (aTabIndex) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
|
@ -979,7 +979,6 @@ nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
|
||||
: mTextCtrlElement(aOwningElement),
|
||||
mRestoringSelection(nullptr),
|
||||
mBoundFrame(nullptr),
|
||||
mTextListener(nullptr),
|
||||
mEverInited(false),
|
||||
mEditorInitialized(false),
|
||||
mInitializing(false),
|
||||
@ -1012,7 +1011,7 @@ nsTextEditorState::Clear()
|
||||
// for us.
|
||||
DestroyEditor();
|
||||
}
|
||||
NS_IF_RELEASE(mTextListener);
|
||||
mTextListener = nullptr;
|
||||
}
|
||||
|
||||
void nsTextEditorState::Unlink()
|
||||
@ -1125,8 +1124,8 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame)
|
||||
|
||||
// Create a SelectionController
|
||||
mSelCon = new nsTextInputSelectionImpl(frameSel, shell, rootNode);
|
||||
MOZ_ASSERT(!mTextListener, "Should not overwrite the object");
|
||||
mTextListener = new nsTextInputListener(mTextCtrlElement);
|
||||
NS_ADDREF(mTextListener);
|
||||
|
||||
mTextListener->SetFrame(mBoundFrame);
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
@ -1647,7 +1646,6 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
TrustedEventsAtSystemGroupBubble());
|
||||
}
|
||||
|
||||
NS_RELEASE(mTextListener);
|
||||
mTextListener = nullptr;
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ private:
|
||||
nsCOMPtr<mozilla::dom::Element> mRootNode;
|
||||
nsCOMPtr<mozilla::dom::Element> mPlaceholderDiv;
|
||||
nsTextControlFrame* mBoundFrame;
|
||||
nsTextInputListener* mTextListener;
|
||||
nsRefPtr<nsTextInputListener> mTextListener;
|
||||
nsAutoPtr<nsCString> mValue;
|
||||
nsRefPtr<nsAnonDivObserver> mMutationObserver;
|
||||
mutable nsString mCachedValue; // Caches non-hard-wrapped value on a multiline control.
|
||||
|
@ -355,7 +355,7 @@ let FormAssistant = {
|
||||
},
|
||||
|
||||
handleEvent: function fa_handleEvent(evt) {
|
||||
let target = evt.target;
|
||||
let target = evt.composedTarget;
|
||||
|
||||
let range = null;
|
||||
switch (evt.type) {
|
||||
|
@ -664,8 +664,8 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
* drag - msg1-n:TOUCH_CONTACT (moving), msgn+1:TOUCH_REMOVE
|
||||
* hover drag - msg1-n:TOUCH_HOVER (moving), msgn+1:TOUCH_REMOVE
|
||||
*
|
||||
* Widget support: Windows 8.0+, Winrt/Win32. Other widgets will
|
||||
* throw.
|
||||
* Widget support: Windows 8.0+, Winrt/Win32. Gonk supports CONTACT, REMOVE,
|
||||
* and CANCEL but no HOVER. Other widgets will throw.
|
||||
*
|
||||
* @param aPointerId The touch point id to create or update.
|
||||
* @param aTouchState one or more of the touch states listed above
|
||||
|
@ -132,7 +132,7 @@ parent:
|
||||
nsString aName,
|
||||
nsString aFeatures,
|
||||
nsString aBaseURI)
|
||||
returns (bool windowOpened, FrameScriptInfo[] frameScripts);
|
||||
returns (bool windowOpened, FrameScriptInfo[] frameScripts, nsCString urlToLoad);
|
||||
|
||||
sync SyncMessage(nsString aMessage, ClonedMessageData aData,
|
||||
CpowEntry[] aCpows, Principal aPrincipal)
|
||||
|
@ -25,6 +25,11 @@
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
// For IsDebuggerPresent()
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@ -527,6 +532,14 @@ HangMonitorParent::RecvHangEvidence(const HangData& aHangData)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Don't report hangs if we're debugging the process. You can comment this
|
||||
// line out for testing purposes.
|
||||
if (IsDebuggerPresent()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
mHangMonitor->InitiateCPOWTimeout();
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
@ -1520,6 +1520,7 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
nsString name(aName);
|
||||
nsAutoCString features(aFeatures);
|
||||
nsTArray<FrameScriptInfo> frameScripts;
|
||||
nsCString urlToLoad;
|
||||
|
||||
if (aIframeMoz) {
|
||||
newChild->SendBrowserFrameOpenWindow(this, url, name,
|
||||
@ -1559,7 +1560,8 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
name, NS_ConvertUTF8toUTF16(features),
|
||||
NS_ConvertUTF8toUTF16(baseURIString),
|
||||
aWindowIsNew,
|
||||
&frameScripts)) {
|
||||
&frameScripts,
|
||||
&urlToLoad)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
@ -1592,6 +1594,10 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
}
|
||||
}
|
||||
|
||||
if (!urlToLoad.IsEmpty()) {
|
||||
newChild->RecvLoadURL(urlToLoad);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
|
||||
win.forget(aReturn);
|
||||
return NS_OK;
|
||||
@ -3567,6 +3573,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
|
@ -65,7 +65,8 @@ class TabChildBase;
|
||||
class TabChildGlobal : public DOMEventTargetHelper,
|
||||
public nsIContentFrameMessageManager,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIGlobalObject
|
||||
public nsIGlobalObject,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
explicit TabChildGlobal(TabChildBase* aTabChild);
|
||||
|
@ -273,7 +273,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
||||
, mChromeFlags(aChromeFlags)
|
||||
, mInitedByParent(false)
|
||||
, mTabId(aTabId)
|
||||
, mSkipLoad(false)
|
||||
, mCreatingWindow(false)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
}
|
||||
@ -454,17 +454,21 @@ TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
|
||||
struct MOZ_STACK_CLASS TabParent::AutoUseNewTab MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
AutoUseNewTab(TabParent* aNewTab, bool* aWindowIsNew)
|
||||
: mNewTab(aNewTab), mWindowIsNew(aWindowIsNew)
|
||||
AutoUseNewTab(TabParent* aNewTab, bool* aWindowIsNew, nsCString* aURLToLoad)
|
||||
: mNewTab(aNewTab), mWindowIsNew(aWindowIsNew), mURLToLoad(aURLToLoad)
|
||||
{
|
||||
MOZ_ASSERT(!TabParent::sNextTabParent);
|
||||
MOZ_ASSERT(!aNewTab->mCreatingWindow);
|
||||
|
||||
TabParent::sNextTabParent = aNewTab;
|
||||
aNewTab->mSkipLoad = true;
|
||||
aNewTab->mCreatingWindow = true;
|
||||
aNewTab->mDelayedURL.Truncate();
|
||||
}
|
||||
|
||||
~AutoUseNewTab()
|
||||
{
|
||||
mNewTab->mSkipLoad = false;
|
||||
mNewTab->mCreatingWindow = false;
|
||||
*mURLToLoad = mNewTab->mDelayedURL;
|
||||
|
||||
if (TabParent::sNextTabParent) {
|
||||
MOZ_ASSERT(TabParent::sNextTabParent == mNewTab);
|
||||
@ -476,6 +480,7 @@ public:
|
||||
private:
|
||||
TabParent* mNewTab;
|
||||
bool* mWindowIsNew;
|
||||
nsCString* mURLToLoad;
|
||||
};
|
||||
|
||||
bool
|
||||
@ -489,7 +494,8 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts)
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
|
||||
nsCString* aURLToLoad)
|
||||
{
|
||||
// We always expect to open a new window here. If we don't, it's an error.
|
||||
*aWindowIsNew = true;
|
||||
@ -530,7 +536,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
params->SetReferrer(aBaseURI);
|
||||
params->SetIsPrivate(isPrivate);
|
||||
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew);
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
|
||||
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
|
||||
mBrowserDOMWindow->OpenURIInFrame(nullptr, params,
|
||||
@ -564,7 +570,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew);
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
|
||||
|
||||
rv = pwwatch->OpenWindow2(parent, finalURIString.get(),
|
||||
NS_ConvertUTF16toUTF8(aName).get(),
|
||||
@ -601,7 +607,7 @@ bool
|
||||
TabParent::SendLoadRemoteScript(const nsString& aURL,
|
||||
const bool& aRunInGlobalScope)
|
||||
{
|
||||
if (mSkipLoad) {
|
||||
if (mCreatingWindow) {
|
||||
mDelayedFrameScripts.AppendElement(FrameScriptInfo(aURL, aRunInGlobalScope));
|
||||
return true;
|
||||
}
|
||||
@ -615,11 +621,6 @@ TabParent::LoadURL(nsIURI* aURI)
|
||||
{
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
if (mSkipLoad) {
|
||||
// Don't send the message if the child wants to load its own URL.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
@ -627,6 +628,13 @@ TabParent::LoadURL(nsIURI* aURI)
|
||||
nsCString spec;
|
||||
aURI->GetSpec(spec);
|
||||
|
||||
if (mCreatingWindow) {
|
||||
// Don't send the message if the child wants to load its own URL.
|
||||
MOZ_ASSERT(mDelayedURL.IsEmpty());
|
||||
mDelayedURL = spec;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mShown) {
|
||||
NS_WARNING(nsPrintfCString("TabParent::LoadURL(%s) called before "
|
||||
"Show(). Ignoring LoadURL.\n",
|
||||
|
@ -144,7 +144,8 @@ public:
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts) MOZ_OVERRIDE;
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
|
||||
nsCString* aURLToLoad) MOZ_OVERRIDE;
|
||||
virtual bool RecvSyncMessage(const nsString& aMessage,
|
||||
const ClonedMessageData& aData,
|
||||
InfallibleTArray<CpowEntry>&& aCpows,
|
||||
@ -489,14 +490,23 @@ private:
|
||||
static TabParent* sNextTabParent;
|
||||
|
||||
// When loading a new tab or window via window.open, the child is
|
||||
// responsible for loading the URL it wants into the new
|
||||
// TabChild. Simultaneously, though, the parent sends a LoadURL message to
|
||||
// every new PBrowser (usually for about:blank). This message usually
|
||||
// arrives after the child has started to load the URL it wants, and
|
||||
// overrides it. To prevent this, we set mSkipLoad to true when creating the
|
||||
// new tab. This flag prevents the unwanted LoadURL message from being sent
|
||||
// by the parent.
|
||||
bool mSkipLoad;
|
||||
// responsible for loading the URL it wants into the new TabChild. When the
|
||||
// parent receives the CreateWindow message, though, it sends a LoadURL
|
||||
// message, usually for about:blank. It's important for the about:blank load
|
||||
// to get processed because the Firefox frontend expects every new window to
|
||||
// immediately start loading something (see bug 1123090). However, we want
|
||||
// the child to process the LoadURL message before it returns from
|
||||
// ProvideWindow so that the URL sent from the parent doesn't override the
|
||||
// child's URL. This is not possible using our IPC mechanisms. To solve the
|
||||
// problem, we skip sending the LoadURL message in the parent and instead
|
||||
// return the URL as a result from CreateWindow. The child simulates
|
||||
// receiving a LoadURL message before returning from ProvideWindow.
|
||||
//
|
||||
// The mCreatingWindow flag is set while dispatching CreateWindow. During
|
||||
// that time, any LoadURL calls are skipped and the URL is stored in
|
||||
// mSkippedURL.
|
||||
bool mCreatingWindow;
|
||||
nsCString mDelayedURL;
|
||||
|
||||
// When loading a new tab or window via window.open, we want to ensure that
|
||||
// frame scripts for that tab are loaded before any scripts start to run in
|
||||
|
@ -74,14 +74,9 @@ const BrowserElementIsPreloaded = true;
|
||||
Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci["nsIAppStartup"]);
|
||||
Cc["@mozilla.org/uriloader;1"].getService(Ci["nsIURILoader"]);
|
||||
Cc["@mozilla.org/cspcontext;1"].createInstance(Ci["nsIContentSecurityPolicy"]);
|
||||
Cc["@mozilla.org/settingsManager;1"].createInstance(Ci["nsISupports"]);
|
||||
|
||||
/* Applications Specific Helper */
|
||||
try {
|
||||
// May throw if we don't have the settings permission
|
||||
navigator.mozSettings;
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.sysmsg.enabled")) {
|
||||
Cc["@mozilla.org/system-message-manager;1"].getService(Ci["nsIDOMNavigatorSystemMessages"]);
|
||||
|
@ -258,8 +258,8 @@ public:
|
||||
}
|
||||
// Bilinear interpolation between adjacent samples in each table.
|
||||
float floorPhase = floorf(mPhase);
|
||||
uint32_t j1 = floorPhase;
|
||||
j1 &= indexMask;
|
||||
int j1Signed = static_cast<int>(floorPhase);
|
||||
uint32_t j1 = j1Signed & indexMask;
|
||||
uint32_t j2 = j1 + 1;
|
||||
j2 &= indexMask;
|
||||
|
||||
|
@ -127,7 +127,6 @@ skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' # Android: bu
|
||||
[test_oscillatorNode.html]
|
||||
[test_oscillatorNode2.html]
|
||||
[test_oscillatorNodeNegativeFrequency.html]
|
||||
skip-if = (toolkit == 'gonk') || (toolkit == 'android')
|
||||
[test_oscillatorNodePassThrough.html]
|
||||
[test_oscillatorNodeStart.html]
|
||||
[test_oscillatorTypeChange.html]
|
||||
|
@ -391,11 +391,21 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
bool enableSandbox = false;
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
nsAutoCString sandboxPref("dom.ipc.plugins.sandbox.");
|
||||
sandboxPref.Append(aPluginTag->GetNiceFileName());
|
||||
if (NS_FAILED(Preferences::GetBool(sandboxPref.get(), &enableSandbox))) {
|
||||
enableSandbox = Preferences::GetBool("dom.ipc.plugins.sandbox.default");
|
||||
}
|
||||
#endif
|
||||
|
||||
nsAutoPtr<PluginModuleChromeParent> parent(new PluginModuleChromeParent(aFilePath, aPluginId));
|
||||
UniquePtr<LaunchCompleteTask> onLaunchedRunnable(new LaunchedTask(parent));
|
||||
parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync);
|
||||
TimeStamp launchStart = TimeStamp::Now();
|
||||
bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable));
|
||||
bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable),
|
||||
enableSandbox);
|
||||
if (!launched) {
|
||||
// We never reached open
|
||||
parent->mShutdown = true;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/command_line.h"
|
||||
#include "base/string_util.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
#include "nsDebugImpl.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "nsCocoaFeatures.h"
|
||||
@ -23,6 +24,10 @@ extern "C" CGError CGSSetDebugOptions(int options);
|
||||
#ifdef XP_WIN
|
||||
#include <objbase.h>
|
||||
bool ShouldProtectPluginCurrentDirectory(char16ptr_t pluginFilePath);
|
||||
#if defined(MOZ_SANDBOX)
|
||||
#define TARGET_SANDBOX_EXPORTS
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using mozilla::ipc::IOThreadChild;
|
||||
@ -49,6 +54,8 @@ namespace plugins {
|
||||
bool
|
||||
PluginProcessChild::Init()
|
||||
{
|
||||
nsDebugImpl::SetMultiprocessMode("NPAPI");
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// Remove the trigger for "dyld interposing" that we added in
|
||||
// GeckoChildProcessHost::PerformAsyncLaunchInternal(), in the host
|
||||
@ -117,6 +124,13 @@ PluginProcessChild::Init()
|
||||
}
|
||||
|
||||
pluginFilename = WideToUTF8(values[0]);
|
||||
|
||||
#if defined(MOZ_SANDBOX)
|
||||
// This is probably the earliest we would want to start the sandbox.
|
||||
// As we attempt to tighten the sandbox, we may need to consider moving this
|
||||
// to later in the plugin initialization.
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
#else
|
||||
# error Sorry
|
||||
#endif
|
||||
|
@ -43,8 +43,18 @@ PluginProcessParent::~PluginProcessParent()
|
||||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask)
|
||||
PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
|
||||
bool aEnableSandbox)
|
||||
{
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
mEnableNPAPISandbox = aEnableSandbox;
|
||||
#else
|
||||
if (aEnableSandbox) {
|
||||
MOZ_ASSERT(false,
|
||||
"Can't enable an NPAPI process sandbox for platform/build.");
|
||||
}
|
||||
#endif
|
||||
|
||||
ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture();
|
||||
uint32_t containerArchitectures = GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin);
|
||||
|
||||
|
@ -50,8 +50,11 @@ public:
|
||||
*
|
||||
* @param aLaunchCompleteTask Task that is executed on the main
|
||||
* thread once the asynchonous launch has completed.
|
||||
* @param aEnableSandbox Enables a process sandbox if one is available for
|
||||
* this platform/build. Will assert if true passed and one is not available.
|
||||
*/
|
||||
bool Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask = UniquePtr<LaunchCompleteTask>());
|
||||
bool Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask = UniquePtr<LaunchCompleteTask>(),
|
||||
bool aEnableSandbox = false);
|
||||
|
||||
void Delete();
|
||||
|
||||
|
198
dom/system/windows/WindowsLocationProvider.cpp
Normal file
198
dom/system/windows/WindowsLocationProvider.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/* 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 "WindowsLocationProvider.h"
|
||||
#include "nsGeoPosition.h"
|
||||
#include "nsIDOMGeoPositionError.h"
|
||||
#include "prtime.h"
|
||||
|
||||
#include <LocationApi.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class LocationEvent MOZ_FINAL : public ILocationEvents
|
||||
{
|
||||
public:
|
||||
LocationEvent(nsIGeolocationUpdate* aCallback)
|
||||
: mCallback(aCallback), mCount(0) {
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
STDMETHODIMP_(ULONG) AddRef() MOZ_OVERRIDE;
|
||||
STDMETHODIMP_(ULONG) Release() MOZ_OVERRIDE;
|
||||
STDMETHODIMP QueryInterface(REFIID iid, void** ppv) MOZ_OVERRIDE;
|
||||
|
||||
// ILocationEvents interface
|
||||
STDMETHODIMP OnStatusChanged(REFIID aReportType,
|
||||
LOCATION_REPORT_STATUS aStatus) MOZ_OVERRIDE;
|
||||
STDMETHODIMP OnLocationChanged(REFIID aReportType,
|
||||
ILocationReport *aReport) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIGeolocationUpdate> mCallback;
|
||||
ULONG mCount;
|
||||
};
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
LocationEvent::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&mCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
LocationEvent::Release()
|
||||
{
|
||||
ULONG count = InterlockedDecrement(&mCount);
|
||||
if (!count) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
LocationEvent::QueryInterface(REFIID iid, void** ppv)
|
||||
{
|
||||
if (iid == IID_IUnknown) {
|
||||
*ppv = static_cast<IUnknown*>(this);
|
||||
} else if (iid == IID_ILocationEvents) {
|
||||
*ppv = static_cast<ILocationEvents*>(this);
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP
|
||||
LocationEvent::OnStatusChanged(REFIID aReportType,
|
||||
LOCATION_REPORT_STATUS aStatus)
|
||||
{
|
||||
if (aReportType != IID_ILatLongReport) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
uint16_t err;
|
||||
switch (aStatus) {
|
||||
case REPORT_ACCESS_DENIED:
|
||||
err = nsIDOMGeoPositionError::PERMISSION_DENIED;
|
||||
break;
|
||||
case REPORT_ERROR:
|
||||
err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
|
||||
break;
|
||||
default:
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
mCallback->NotifyError(err);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
LocationEvent::OnLocationChanged(REFIID aReportType,
|
||||
ILocationReport *aReport)
|
||||
{
|
||||
if (aReportType != IID_ILatLongReport) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<ILatLongReport> latLongReport;
|
||||
if (FAILED(aReport->QueryInterface(IID_ILatLongReport,
|
||||
getter_AddRefs(latLongReport)))) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
DOUBLE latitude = 0.0;
|
||||
latLongReport->GetLatitude(&latitude);
|
||||
|
||||
DOUBLE longitude = 0.0;
|
||||
latLongReport->GetLongitude(&longitude);
|
||||
|
||||
DOUBLE alt = 0.0;
|
||||
latLongReport->GetAltitude(&alt);
|
||||
|
||||
DOUBLE herror = 0.0;
|
||||
latLongReport->GetErrorRadius(&herror);
|
||||
|
||||
DOUBLE verror = 0.0;
|
||||
latLongReport->GetAltitudeError(&verror);
|
||||
|
||||
nsRefPtr<nsGeoPosition> position =
|
||||
new nsGeoPosition(latitude, longitude, alt, herror, verror, 0.0, 0.0,
|
||||
PR_Now());
|
||||
mCallback->Update(position);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(WindowsLocationProvider, nsIGeolocationProvider)
|
||||
|
||||
WindowsLocationProvider::WindowsLocationProvider()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsLocationProvider::Startup()
|
||||
{
|
||||
nsRefPtr<ILocation> location;
|
||||
if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER,
|
||||
IID_ILocation,
|
||||
getter_AddRefs(location)))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
IID reportTypes[] = { IID_ILatLongReport };
|
||||
if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mLocation = location;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
||||
{
|
||||
nsRefPtr<LocationEvent> event = new LocationEvent(aCallback);
|
||||
if (FAILED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsLocationProvider::Shutdown()
|
||||
{
|
||||
if (mLocation) {
|
||||
mLocation->UnregisterForReport(IID_ILatLongReport);
|
||||
mLocation = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsLocationProvider::SetHighAccuracy(bool enable)
|
||||
{
|
||||
if (!mLocation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOCATION_DESIRED_ACCURACY desiredAccuracy;
|
||||
if (enable) {
|
||||
desiredAccuracy = LOCATION_DESIRED_ACCURACY_HIGH;
|
||||
} else {
|
||||
desiredAccuracy = LOCATION_DESIRED_ACCURACY_DEFAULT;
|
||||
}
|
||||
if (FAILED(mLocation->SetDesiredAccuracy(IID_ILatLongReport,
|
||||
desiredAccuracy))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
31
dom/system/windows/WindowsLocationProvider.h
Normal file
31
dom/system/windows/WindowsLocationProvider.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_WindowsLocationProvider_h__
|
||||
#define mozilla_dom_WindowsLocationProvider_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIGeolocationProvider.h"
|
||||
|
||||
#include <LocationApi.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WindowsLocationProvider MOZ_FINAL : public nsIGeolocationProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGEOLOCATIONPROVIDER
|
||||
|
||||
WindowsLocationProvider();
|
||||
|
||||
private:
|
||||
nsRefPtr<ILocation> mLocation;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_WindowsLocationProvider_h__
|
@ -6,6 +6,7 @@
|
||||
|
||||
SOURCES += [
|
||||
'nsHapticFeedback.cpp',
|
||||
'WindowsLocationProvider.cpp'
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
const TEST_URI = "http://example.com/browser/dom/tests/browser/test-console-api.html";
|
||||
|
||||
var gWindow, gLevel, gArgs, gTestDriver, gStyle;
|
||||
var gWindow, gLevel, gArgs, gStyle;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
@ -15,7 +15,7 @@ function test() {
|
||||
var browser = gBrowser.selectedBrowser;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gWindow = gLevel = gArgs = gTestDriver = null;
|
||||
gWindow = gLevel = gArgs = null;
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
@ -26,8 +26,7 @@ function test() {
|
||||
executeSoon(function test_executeSoon() {
|
||||
gWindow = browser.contentWindow;
|
||||
consoleAPISanityTest();
|
||||
gTestDriver = observeConsoleTest();
|
||||
gTestDriver.next();
|
||||
observeConsoleTest();
|
||||
});
|
||||
|
||||
}, false);
|
||||
@ -74,8 +73,6 @@ function testConsoleData(aMessageObject) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gTestDriver.next();
|
||||
}
|
||||
|
||||
function testLocationData(aMessageObject) {
|
||||
@ -215,127 +212,100 @@ function observeConsoleTest() {
|
||||
let win = XPCNativeWrapper.unwrap(gWindow);
|
||||
expect("log", "arg");
|
||||
win.console.log("arg");
|
||||
yield undefined;
|
||||
|
||||
expect("info", "arg", "extra arg");
|
||||
win.console.info("arg", "extra arg");
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %1.0f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.14");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %1.2f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.141590");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("warn", "Lesson 1: PI is approximately equal to 3.1415900");
|
||||
win.console.warn("Lesson %d: %s is approximately equal to %0.7f",
|
||||
1,
|
||||
"PI",
|
||||
3.14159);
|
||||
yield undefined;
|
||||
|
||||
expect("log", "%d, %s, %l");
|
||||
win.console.log("%d, %s, %l");
|
||||
yield undefined;
|
||||
|
||||
expect("log", "%a %b %g");
|
||||
win.console.log("%a %b %g");
|
||||
yield undefined;
|
||||
|
||||
expect("log", "%a %b %g", "a", "b");
|
||||
win.console.log("%a %b %g", "a", "b");
|
||||
yield undefined;
|
||||
|
||||
expect("log", "2, a, %l", 3);
|
||||
win.console.log("%d, %s, %l", 2, "a", 3);
|
||||
yield undefined;
|
||||
|
||||
// Bug #692550 handle null and undefined.
|
||||
expect("log", "null, undefined");
|
||||
win.console.log("%s, %s", null, undefined);
|
||||
yield undefined;
|
||||
|
||||
// Bug #696288 handle object as first argument.
|
||||
let obj = { a: 1 };
|
||||
expect("log", obj, "a");
|
||||
win.console.log(obj, "a");
|
||||
yield undefined;
|
||||
|
||||
expect("dir", win.toString());
|
||||
win.console.dir(win);
|
||||
yield undefined;
|
||||
|
||||
expect("error", "arg");
|
||||
win.console.error("arg");
|
||||
yield undefined;
|
||||
|
||||
expect("exception", "arg");
|
||||
win.console.exception("arg");
|
||||
yield undefined;
|
||||
|
||||
expect("log", "foobar");
|
||||
gStyle = ["color:red;foobar;;"];
|
||||
win.console.log("%cfoobar", gStyle[0]);
|
||||
yield undefined;
|
||||
|
||||
let obj4 = { d: 4 };
|
||||
expect("warn", "foobar", obj4, "test", "bazbazstr", "last");
|
||||
gStyle = [null, null, null, "color:blue;", "color:red"];
|
||||
win.console.warn("foobar%Otest%cbazbaz%s%clast", obj4, gStyle[3], "str", gStyle[4]);
|
||||
yield undefined;
|
||||
|
||||
let obj3 = { c: 3 };
|
||||
expect("info", "foobar", "bazbaz", obj3, "%comg", "color:yellow");
|
||||
gStyle = [null, "color:pink;"];
|
||||
win.console.info("foobar%cbazbaz", gStyle[1], obj3, "%comg", "color:yellow");
|
||||
yield undefined;
|
||||
|
||||
gStyle = null;
|
||||
let obj2 = { b: 2 };
|
||||
expect("log", "omg ", obj, " foo ", 4, obj2);
|
||||
win.console.log("omg %o foo %o", obj, 4, obj2);
|
||||
yield undefined;
|
||||
|
||||
expect("assert", "message");
|
||||
win.console.assert(false, "message");
|
||||
yield undefined;
|
||||
|
||||
expect("count", { label: "label a", count: 1 })
|
||||
win.console.count("label a");
|
||||
yield undefined;
|
||||
|
||||
expect("count", { label: "label b", count: 1 })
|
||||
win.console.count("label b");
|
||||
yield undefined;
|
||||
|
||||
expect("count", { label: "label a", count: 2 })
|
||||
win.console.count("label a");
|
||||
yield undefined;
|
||||
|
||||
expect("count", { label: "label b", count: 2 })
|
||||
win.console.count("label b");
|
||||
yield undefined;
|
||||
|
||||
startTraceTest();
|
||||
yield undefined;
|
||||
|
||||
startLocationTest();
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
function consoleAPISanityTest() {
|
||||
|
@ -56,6 +56,7 @@ partial interface Event {
|
||||
|
||||
readonly attribute EventTarget? originalTarget;
|
||||
readonly attribute EventTarget? explicitOriginalTarget;
|
||||
[ChromeOnly] readonly attribute EventTarget? composedTarget;
|
||||
[ChromeOnly] readonly attribute boolean multipleActionsPrevented;
|
||||
[ChromeOnly] readonly attribute boolean isSynthesized;
|
||||
|
||||
|
@ -1729,6 +1729,14 @@ private:
|
||||
bool mIsOffline;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
StartsWithExplicit(nsACString& s)
|
||||
{
|
||||
return StringBeginsWith(s, NS_LITERAL_CSTRING("explicit/"));
|
||||
}
|
||||
#endif
|
||||
|
||||
class WorkerJSRuntimeStats : public JS::RuntimeStats
|
||||
{
|
||||
const nsACString& mRtPath;
|
||||
@ -1761,6 +1769,9 @@ public:
|
||||
xpc::ZoneStatsExtras* extras = new xpc::ZoneStatsExtras;
|
||||
extras->pathPrefix = mRtPath;
|
||||
extras->pathPrefix += nsPrintfCString("zone(0x%p)/", (void *)aZone);
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->pathPrefix));
|
||||
|
||||
aZoneStats->extra = extras;
|
||||
}
|
||||
|
||||
@ -1787,6 +1798,9 @@ public:
|
||||
// This should never be used when reporting with workers (hence the "?!").
|
||||
extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");
|
||||
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->jsPathPrefix));
|
||||
MOZ_ASSERT(StartsWithExplicit(extras->domPathPrefix));
|
||||
|
||||
extras->location = nullptr;
|
||||
|
||||
aCompartmentStats->extra = extras;
|
||||
@ -2081,15 +2095,14 @@ public:
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Assumes that WorkerJSRuntimeStats will hold a reference to |path|, and
|
||||
// not a copy, as TryToMapAddon() may later modify if.
|
||||
// not a copy, as TryToMapAddon() may later modify it.
|
||||
nsCString path;
|
||||
WorkerJSRuntimeStats rtStats(path);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mWorkerPrivate ||
|
||||
!mWorkerPrivate->BlockAndCollectRuntimeStats(&rtStats, aAnonymize)) {
|
||||
if (!mWorkerPrivate) {
|
||||
// Returning NS_OK here will effectively report 0 memory.
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2113,6 +2126,11 @@ public:
|
||||
path.AppendPrintf(", 0x%p)/", static_cast<void*>(mWorkerPrivate));
|
||||
|
||||
TryToMapAddon(path);
|
||||
|
||||
if (!mWorkerPrivate->BlockAndCollectRuntimeStats(&rtStats, aAnonymize)) {
|
||||
// Returning NS_OK here will effectively report 0 memory.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return xpc::ReportJSRuntimeExplicitTreeStats(rtStats, path,
|
||||
@ -3502,7 +3520,7 @@ WorkerPrivateParent<Derived>::SetBaseURI(nsIURI* aBaseURI)
|
||||
if (NS_SUCCEEDED(aBaseURI->GetRef(temp)) && !temp.IsEmpty()) {
|
||||
nsCOMPtr<nsITextToSubURI> converter =
|
||||
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID);
|
||||
if (converter) {
|
||||
if (converter && nsContentUtils::EncodeDecodeURLHash()) {
|
||||
nsCString charset;
|
||||
nsAutoString unicodeRef;
|
||||
if (NS_SUCCEEDED(aBaseURI->GetOriginCharset(charset)) &&
|
||||
|
@ -95,6 +95,7 @@ NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScope)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
JSObject*
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/Headers.h"
|
||||
#include "mozilla/dom/RequestBinding.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -37,7 +38,8 @@ class WorkerNavigator;
|
||||
class Performance;
|
||||
|
||||
class WorkerGlobalScope : public DOMEventTargetHelper,
|
||||
public nsIGlobalObject
|
||||
public nsIGlobalObject,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
typedef mozilla::dom::indexedDB::IDBFactory IDBFactory;
|
||||
|
||||
|
@ -1133,6 +1133,12 @@ nsEditor::CanCopy(bool *aCanCut)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::CanDelete(bool *aCanDelete)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::Paste(int32_t aSelectionType)
|
||||
{
|
||||
|
@ -590,7 +590,7 @@ nsDeleteCommand::IsCommandEnabled(const char *aCommandName,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!nsCRT::strcmp("cmd_delete", aCommandName) && *outCmdEnabled) {
|
||||
rv = editor->CanCut(outCmdEnabled);
|
||||
rv = editor->CanDelete(outCmdEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -969,7 +969,6 @@ nsHTMLEditor::IsVisBreak(nsINode* aNode)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsHTMLEditor::IsVisBreak(nsIDOMNode* aNode)
|
||||
{
|
||||
@ -978,17 +977,6 @@ nsHTMLEditor::IsVisBreak(nsIDOMNode* aNode)
|
||||
return IsVisBreak(node);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::BreakIsVisible(nsIDOMNode *aNode, bool *aIsVisible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNode && aIsVisible);
|
||||
|
||||
*aIsVisible = IsVisBreak(aNode);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetIsDocumentEditable(bool *aIsDocumentEditable)
|
||||
{
|
||||
|
@ -1153,14 +1153,15 @@ nsPlaintextEditor::Redo(uint32_t aCount)
|
||||
}
|
||||
|
||||
bool
|
||||
nsPlaintextEditor::CanCutOrCopy()
|
||||
nsPlaintextEditor::CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed)
|
||||
{
|
||||
nsRefPtr<Selection> selection = GetSelection();
|
||||
if (!selection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsPasswordEditor())
|
||||
if (aPasswordFieldAllowed == ePasswordFieldNotAllowed &&
|
||||
IsPasswordEditor())
|
||||
return false;
|
||||
|
||||
return !selection->Collapsed();
|
||||
@ -1198,7 +1199,7 @@ NS_IMETHODIMP nsPlaintextEditor::Cut()
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanCut(bool *aCanCut)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanCut);
|
||||
*aCanCut = IsModifiable() && CanCutOrCopy();
|
||||
*aCanCut = IsModifiable() && CanCutOrCopy(ePasswordFieldNotAllowed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1211,7 +1212,14 @@ NS_IMETHODIMP nsPlaintextEditor::Copy()
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanCopy(bool *aCanCopy)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanCopy);
|
||||
*aCanCopy = CanCutOrCopy();
|
||||
*aCanCopy = CanCutOrCopy(ePasswordFieldNotAllowed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPlaintextEditor::CanDelete(bool *aCanDelete)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCanDelete);
|
||||
*aCanDelete = IsModifiable() && CanCutOrCopy(ePasswordFieldAllowed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ public:
|
||||
NS_IMETHOD CanCut(bool *aCanCut) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Copy() MOZ_OVERRIDE;
|
||||
NS_IMETHOD CanCopy(bool *aCanCopy) MOZ_OVERRIDE;
|
||||
NS_IMETHOD CanDelete(bool *aCanDelete) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Paste(int32_t aSelectionType) MOZ_OVERRIDE;
|
||||
NS_IMETHOD CanPaste(int32_t aSelectionType, bool *aCanPaste) MOZ_OVERRIDE;
|
||||
NS_IMETHOD PasteTransferable(nsITransferable *aTransferable) MOZ_OVERRIDE;
|
||||
@ -203,7 +204,11 @@ protected:
|
||||
/* small utility routine to test the eEditorReadonly bit */
|
||||
bool IsModifiable();
|
||||
|
||||
bool CanCutOrCopy();
|
||||
enum PasswordFieldAllowed {
|
||||
ePasswordFieldAllowed,
|
||||
ePasswordFieldNotAllowed
|
||||
};
|
||||
bool CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed);
|
||||
bool FireClipboardEvent(int32_t aType, int32_t aSelectionType);
|
||||
|
||||
bool UpdateMetaCharset(nsIDOMDocument* aDocument,
|
||||
|
@ -1198,7 +1198,9 @@ nsTextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
|
||||
if (!aSelection || !aInString || !aOutString) {return NS_ERROR_NULL_POINTER;}
|
||||
|
||||
nsresult res = NS_OK;
|
||||
*aOutString = *aInString;
|
||||
if (!aOutString->Assign(*aInString, mozilla::fallible_t())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (aTruncated) {
|
||||
*aTruncated = false;
|
||||
}
|
||||
@ -1233,6 +1235,8 @@ nsTextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
|
||||
const int32_t resultingDocLength = docLength - selectionLength - oldCompStrLength;
|
||||
if (resultingDocLength >= aMaxLength)
|
||||
{
|
||||
// This call is guaranteed to reduce the capacity of the string, so it
|
||||
// cannot cause an OOM.
|
||||
aOutString->Truncate();
|
||||
if (aTruncated) {
|
||||
*aTruncated = true;
|
||||
@ -1253,6 +1257,8 @@ nsTextEditRules::TruncateInsertionIfNeeded(Selection* aSelection,
|
||||
}
|
||||
// XXX What should we do if we're removing IVS and its preceding
|
||||
// character won't be removed?
|
||||
// This call is guaranteed to reduce the capacity of the string, so it
|
||||
// cannot cause an OOM.
|
||||
aOutString->Truncate(newLength);
|
||||
if (aTruncated) {
|
||||
*aTruncated = true;
|
||||
|
@ -34,12 +34,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1067255
|
||||
|
||||
ok(editor1.canCopy(), "can copy, text");
|
||||
ok(editor1.canCut(), "can cut, text");
|
||||
ok(editor1.canDelete(), "can delete, text");
|
||||
|
||||
password.focus();
|
||||
password.select();
|
||||
|
||||
ok(!editor2.canCopy(), "can copy, password");
|
||||
ok(!editor2.canCut(), "can cut, password");
|
||||
ok(editor1.canDelete(), "can delete, password");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ interface nsIEditActionListener;
|
||||
interface nsIInlineSpellChecker;
|
||||
interface nsITransferable;
|
||||
|
||||
[scriptable, uuid(a1ddae68-35d0-11e4-9329-cb55463f21c9)]
|
||||
|
||||
[scriptable, uuid(094be624-f0bf-400f-89e2-6a84baab9474)]
|
||||
interface nsIEditor : nsISupports
|
||||
{
|
||||
%{C++
|
||||
@ -305,18 +304,22 @@ interface nsIEditor : nsISupports
|
||||
* collapsed selection.
|
||||
*/
|
||||
boolean canCut();
|
||||
|
||||
|
||||
/** copy the currently selected text, putting it into the OS clipboard
|
||||
* What if no text is selected?
|
||||
* What about mixed selections?
|
||||
* What are the clipboard formats?
|
||||
*/
|
||||
void copy();
|
||||
|
||||
|
||||
/** Can we copy? True if we have a non-collapsed selection.
|
||||
*/
|
||||
boolean canCopy();
|
||||
|
||||
|
||||
/** Can we delete? True if we have a non-collapsed selection.
|
||||
*/
|
||||
boolean canDelete();
|
||||
|
||||
/** paste the text in the OS clipboard at the cursor position, replacing
|
||||
* the selected text (if any)
|
||||
*/
|
||||
|
@ -22,8 +22,7 @@ class Element;
|
||||
|
||||
[ptr] native Element (mozilla::dom::Element);
|
||||
|
||||
[scriptable, uuid(393a364f-e8e2-48a1-a271-a0067b6bac9b)]
|
||||
|
||||
[scriptable, uuid(87ee993e-985f-4a43-a974-0d9512da2fb0)]
|
||||
interface nsIHTMLEditor : nsISupports
|
||||
{
|
||||
%{C++
|
||||
@ -551,11 +550,6 @@ interface nsIHTMLEditor : nsISupports
|
||||
*/
|
||||
attribute boolean returnInParagraphCreatesNewParagraph;
|
||||
|
||||
/**
|
||||
* Checks whether a BR node is visible to the user.
|
||||
*/
|
||||
boolean breakIsVisible(in nsIDOMNode aNode);
|
||||
|
||||
/**
|
||||
* Get an active editor's editing host in DOM window. If this editor isn't
|
||||
* active in the DOM window, this returns NULL.
|
||||
|
@ -24,14 +24,14 @@ using mozilla::AutoSafeJSContext;
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
static mozilla::Maybe<JS::PersistentRooted<JSObject *> > autoconfigSb;
|
||||
static JS::PersistentRooted<JSObject *> autoconfigSb;
|
||||
|
||||
nsresult CentralizedAdminPrefManagerInit()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// If the sandbox is already created, no need to create it again.
|
||||
if (autoconfigSb)
|
||||
if (autoconfigSb.initialized())
|
||||
return NS_OK;
|
||||
|
||||
// Grab XPConnect.
|
||||
@ -53,14 +53,14 @@ nsresult CentralizedAdminPrefManagerInit()
|
||||
|
||||
// Unwrap, store and root the sandbox.
|
||||
NS_ENSURE_STATE(sandbox->GetJSObject());
|
||||
autoconfigSb.emplace(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
|
||||
autoconfigSb.init(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult CentralizedAdminPrefManagerFinish()
|
||||
{
|
||||
if (autoconfigSb) {
|
||||
if (autoconfigSb.initialized()) {
|
||||
AutoSafeJSContext cx;
|
||||
autoconfigSb.reset();
|
||||
JS_MaybeGC(cx);
|
||||
@ -103,12 +103,12 @@ nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
|
||||
}
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoCompartment ac(cx, *autoconfigSb);
|
||||
JSAutoCompartment ac(cx, autoconfigSb);
|
||||
|
||||
nsAutoCString script(js_buffer, length);
|
||||
JS::RootedValue v(cx);
|
||||
rv = xpc->EvalInSandboxObject(NS_ConvertASCIItoUTF16(script), filename, cx,
|
||||
*autoconfigSb, &v);
|
||||
autoconfigSb, &v);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include <d3d10_1.h>
|
||||
#include "d3d10/ImageLayerD3D10.h"
|
||||
#include "D3D9SurfaceImage.h"
|
||||
#endif
|
||||
|
||||
|
@ -403,5 +403,20 @@ CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
forwarder->UseTexture(this, mFrontTex);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClientSharedSurface::ClearSurfaces()
|
||||
{
|
||||
if (mFrontTex && (mFront || mPrevFront)) {
|
||||
// Force a synchronous destruction so that the TextureHost does not
|
||||
// outlive the SharedSurface. This won't be needed once TextureClient/Host
|
||||
// and SharedSurface are merged.
|
||||
mFrontTex->ForceRemove(true /* sync */);
|
||||
mFrontTex = nullptr;
|
||||
}
|
||||
// It is important to destroy the SharedSurface *after* the TextureClient.
|
||||
mFront = nullptr;
|
||||
mPrevFront = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -119,25 +119,30 @@ private:
|
||||
|
||||
RefPtr<TextureClient> mFrontTex;
|
||||
|
||||
void ClearSurfaces();
|
||||
|
||||
public:
|
||||
CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
|
||||
TextureFlags aFlags);
|
||||
|
||||
~CanvasClientSharedSurface()
|
||||
{
|
||||
ClearSurfaces();
|
||||
}
|
||||
|
||||
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE {
|
||||
return TextureInfo(CompositableType::IMAGE);
|
||||
}
|
||||
|
||||
virtual void Clear() MOZ_OVERRIDE {
|
||||
mFront = nullptr;
|
||||
mPrevFront = nullptr;
|
||||
mFrontTex = nullptr;
|
||||
ClearSurfaces();
|
||||
}
|
||||
|
||||
virtual void Update(gfx::IntSize aSize,
|
||||
ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
|
||||
|
||||
virtual void OnDetach() MOZ_OVERRIDE {
|
||||
CanvasClientSharedSurface::Clear();
|
||||
ClearSurfaces();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -503,10 +503,10 @@ TextureClient::KeepUntilFullDeallocation(KeepAlive* aKeep)
|
||||
mActor->mKeep = aKeep;
|
||||
}
|
||||
|
||||
void TextureClient::ForceRemove()
|
||||
void TextureClient::ForceRemove(bool sync)
|
||||
{
|
||||
if (mValid && mActor) {
|
||||
if (GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
|
||||
if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
|
||||
MOZ_PERFORMANCE_WARNING("gfx", "TextureClient/Host pair requires synchronous deallocation");
|
||||
if (mActor->IPCOpen()) {
|
||||
mActor->SendClearTextureHostSync();
|
||||
|
@ -426,8 +426,10 @@ public:
|
||||
* If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
|
||||
* will be synchronously coordinated with the compositor side, otherwise it
|
||||
* will be done asynchronously.
|
||||
* If sync is true, the destruction will be synchronous regardless of the
|
||||
* texture's flags (bad for performance, use with care).
|
||||
*/
|
||||
void ForceRemove();
|
||||
void ForceRemove(bool sync = false);
|
||||
|
||||
virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
|
||||
{
|
||||
|
@ -1,241 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "CanvasLayerD3D10.h"
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "SharedSurfaceANGLE.h"
|
||||
#include "SharedSurfaceGL.h"
|
||||
#include "gfxContext.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: CanvasLayer(aManager, nullptr)
|
||||
, LayerD3D10(aManager)
|
||||
, mDataIsPremultiplied(true)
|
||||
, mOriginPos(gl::OriginPos::TopLeft)
|
||||
, mHasAlpha(true)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
CanvasLayerD3D10::~CanvasLayerD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::Initialize(const Data& aData)
|
||||
{
|
||||
NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
|
||||
|
||||
if (aData.mGLContext) {
|
||||
mGLContext = aData.mGLContext;
|
||||
NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
|
||||
mDataIsPremultiplied = aData.mIsGLAlphaPremult;
|
||||
mOriginPos = gl::OriginPos::TopLeft;
|
||||
|
||||
GLScreenBuffer* screen = mGLContext->Screen();
|
||||
|
||||
UniquePtr<SurfaceFactory> factory = nullptr;
|
||||
if (!gfxPrefs::WebGLForceLayersReadback()) {
|
||||
if (mGLContext->IsANGLE()) {
|
||||
factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext,
|
||||
screen->mCaps);
|
||||
}
|
||||
}
|
||||
|
||||
if (factory) {
|
||||
screen->Morph(Move(factory));
|
||||
}
|
||||
} else if (aData.mDrawTarget) {
|
||||
mDrawTarget = aData.mDrawTarget;
|
||||
void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE);
|
||||
|
||||
if (texture) {
|
||||
mTexture = static_cast<ID3D10Texture2D*>(texture);
|
||||
|
||||
NS_ASSERTION(!aData.mGLContext,
|
||||
"CanvasLayer can't have both DrawTarget and WebGLContext/Surface");
|
||||
|
||||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX we should store mDrawTarget and use it directly in UpdateSurface,
|
||||
// bypassing Thebes
|
||||
mSurface = mDrawTarget->Snapshot();
|
||||
} else {
|
||||
MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
|
||||
}
|
||||
|
||||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
mIsD2DTexture = false;
|
||||
|
||||
// Create a texture in case we need to readback.
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create texture for CanvasLayer!");
|
||||
return;
|
||||
}
|
||||
|
||||
device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mUploadSRView));
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::UpdateSurface()
|
||||
{
|
||||
if (!IsDirty())
|
||||
return;
|
||||
Painted();
|
||||
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->Flush();
|
||||
} else if (mIsD2DTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
SharedSurface* surf = nullptr;
|
||||
if (mGLContext) {
|
||||
auto screen = mGLContext->Screen();
|
||||
MOZ_ASSERT(screen);
|
||||
|
||||
surf = screen->Front()->Surf();
|
||||
if (!surf)
|
||||
return;
|
||||
surf->WaitSync();
|
||||
|
||||
if (surf->mType == SharedSurfaceType::EGLSurfaceANGLE) {
|
||||
SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf);
|
||||
HANDLE shareHandle = shareSurf->GetShareHandle();
|
||||
|
||||
HRESULT hr = device()->OpenSharedResource(shareHandle,
|
||||
__uuidof(ID3D10Texture2D),
|
||||
getter_AddRefs(mTexture));
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
hr = device()->CreateShaderResourceView(mTexture,
|
||||
nullptr,
|
||||
getter_AddRefs(mSRView));
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to lock CanvasLayer texture.";
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> destTarget =
|
||||
Factory::CreateDrawTargetForD3D10Texture(mTexture,
|
||||
SurfaceFormat::R8G8B8A8);
|
||||
|
||||
if (!destTarget) {
|
||||
gfxWarning() << "Invalid D3D10 texture target R8G8B8A8";
|
||||
return;
|
||||
}
|
||||
|
||||
if (surf) {
|
||||
if (!ReadbackSharedSurface(surf, destTarget)) {
|
||||
gfxWarning() << "Failed to readback into texture.";
|
||||
}
|
||||
} else if (mSurface) {
|
||||
Rect r(Point(0, 0), ToRect(mBounds).Size());
|
||||
destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(),
|
||||
DrawOptions(1.0F, CompositionOp::OP_SOURCE));
|
||||
}
|
||||
|
||||
mTexture->Unmap(0);
|
||||
mSRView = mUploadSRView;
|
||||
}
|
||||
|
||||
Layer*
|
||||
CanvasLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::RenderLayer()
|
||||
{
|
||||
FirePreTransactionCallback();
|
||||
UpdateSurface();
|
||||
FireDidTransactionCallback();
|
||||
|
||||
if (!mTexture)
|
||||
return;
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
SetEffectTransformAndOpacity();
|
||||
|
||||
uint8_t shaderFlags = 0;
|
||||
shaderFlags |= LoadMaskTexture();
|
||||
shaderFlags |= mDataIsPremultiplied
|
||||
? SHADER_PREMUL : SHADER_NON_PREMUL | SHADER_RGBA;
|
||||
shaderFlags |= mHasAlpha ? SHADER_RGBA : SHADER_RGB;
|
||||
shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST
|
||||
? SHADER_POINT : SHADER_LINEAR;
|
||||
ID3D10EffectTechnique* technique = SelectShader(shaderFlags);
|
||||
|
||||
if (mSRView) {
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
|
||||
}
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)mBounds.x,
|
||||
(float)mBounds.y,
|
||||
(float)mBounds.width,
|
||||
(float)mBounds.height)
|
||||
);
|
||||
|
||||
const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
|
||||
|
||||
if (needsYFlip) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
0,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f)
|
||||
);
|
||||
}
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
|
||||
if (needsYFlip) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
@ -1,73 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_CANVASLAYERD3D10_H
|
||||
#define GFX_CANVASLAYERD3D10_H
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CanvasLayerD3D10 : public CanvasLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
CanvasLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
~CanvasLayerD3D10();
|
||||
|
||||
// CanvasLayer implementation
|
||||
virtual void Initialize(const Data& aData);
|
||||
|
||||
// LayerD3D10 implementation
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer();
|
||||
|
||||
private:
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
void UpdateSurface();
|
||||
|
||||
RefPtr<gfx::SourceSurface> mSurface;
|
||||
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mUploadSRView;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
|
||||
bool mDataIsPremultiplied;
|
||||
gl::OriginPos mOriginPos;
|
||||
bool mIsD2DTexture;
|
||||
bool mHasAlpha;
|
||||
|
||||
nsAutoArrayPtr<uint8_t> mCachedTempBlob;
|
||||
uint32_t mCachedTempBlob_Size;
|
||||
|
||||
uint8_t* GetTempBlob(const uint32_t aSize)
|
||||
{
|
||||
if (!mCachedTempBlob || aSize != mCachedTempBlob_Size) {
|
||||
mCachedTempBlob = new uint8_t[aSize];
|
||||
mCachedTempBlob_Size = aSize;
|
||||
}
|
||||
|
||||
return mCachedTempBlob;
|
||||
}
|
||||
|
||||
void DiscardTempBlob()
|
||||
{
|
||||
mCachedTempBlob = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_CANVASLAYERD3D10_H */
|
@ -1,60 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "ColorLayerD3D10.h"
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ColorLayerD3D10::ColorLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ColorLayer(aManager, nullptr)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
Layer*
|
||||
ColorLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
ColorLayerD3D10::RenderLayer()
|
||||
{
|
||||
float color[4];
|
||||
// output color is premultiplied, so we need to adjust all channels.
|
||||
// mColor is not premultiplied.
|
||||
float opacity = GetEffectiveOpacity() * mColor.a;
|
||||
color[0] = (float)(mColor.r * opacity);
|
||||
color[1] = (float)(mColor.g * opacity);
|
||||
color[2] = (float)(mColor.b * opacity);
|
||||
color[3] = opacity;
|
||||
|
||||
const gfx::Matrix4x4& transform = GetEffectiveTransform();
|
||||
void* raw = &const_cast<gfx::Matrix4x4&>(transform)._11;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64);
|
||||
effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
|
||||
|
||||
ID3D10EffectTechnique *technique = SelectShader(SHADER_SOLID | LoadMaskTexture());
|
||||
|
||||
nsIntRect bounds = GetBounds();
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)bounds.x,
|
||||
(float)bounds.y,
|
||||
(float)bounds.width,
|
||||
(float)bounds.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
@ -1,27 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_COLORLAYERD3D10_H
|
||||
#define GFX_COLORLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ColorLayerD3D10 : public ColorLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ColorLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer();
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_PAINTEDLAYERD3D10_H */
|
@ -1,268 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "ContainerLayerD3D10.h"
|
||||
|
||||
#include "PaintedLayerD3D10.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ContainerLayer(aManager, nullptr)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
ContainerLayerD3D10::~ContainerLayerD3D10()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
}
|
||||
|
||||
Layer*
|
||||
ContainerLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
LayerD3D10*
|
||||
ContainerLayerD3D10::GetFirstChildD3D10()
|
||||
{
|
||||
if (!mFirstChild) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<LayerD3D10*>(mFirstChild->ImplData());
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::RenderLayer()
|
||||
{
|
||||
float renderTargetOffset[] = { 0, 0 };
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
float opacity = GetEffectiveOpacity();
|
||||
bool useIntermediate = UseIntermediateSurface();
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> previousRTView;
|
||||
nsRefPtr<ID3D10Texture2D> renderTexture;
|
||||
nsRefPtr<ID3D10RenderTargetView> rtView;
|
||||
float previousRenderTargetOffset[2];
|
||||
nsIntSize previousViewportSize;
|
||||
|
||||
gfx3DMatrix oldViewMatrix;
|
||||
|
||||
if (useIntermediate) {
|
||||
device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), nullptr);
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC));
|
||||
desc.ArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Width = visibleRect.width;
|
||||
desc.Height = visibleRect.height;
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
HRESULT hr;
|
||||
hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(renderTexture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create new texture for ContainerLayerD3D10!"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
hr = device()->CreateRenderTargetView(renderTexture, nullptr, getter_AddRefs(rtView));
|
||||
NS_ASSERTION(SUCCEEDED(hr), "Failed to create render target view for ContainerLayerD3D10!");
|
||||
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
GetRawValue(previousRenderTargetOffset, 0, 8);
|
||||
|
||||
previousViewportSize = mD3DManager->GetViewport();
|
||||
|
||||
if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) {
|
||||
Matrix4x4 transform3D = GetEffectiveTransform();
|
||||
Matrix transform;
|
||||
// If we have an opaque ancestor layer, then we can be sure that
|
||||
// all the pixels we draw into are either opaque already or will be
|
||||
// covered by something opaque. Otherwise copying up the background is
|
||||
// not safe.
|
||||
if (mSupportsComponentAlphaChildren) {
|
||||
bool is2d = transform3D.Is2D(&transform);
|
||||
NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren.");
|
||||
|
||||
// Copy background up from below. This applies any 2D transform that is
|
||||
// applied to use relative to our parent, and compensates for the offset
|
||||
// that was applied on our parent's rendering.
|
||||
D3D10_BOX srcBox;
|
||||
srcBox.left = std::max<int32_t>(visibleRect.x + int32_t(transform._31) - int32_t(previousRenderTargetOffset[0]), 0);
|
||||
srcBox.top = std::max<int32_t>(visibleRect.y + int32_t(transform._32) - int32_t(previousRenderTargetOffset[1]), 0);
|
||||
srcBox.right = std::min<int32_t>(srcBox.left + visibleRect.width, previousViewportSize.width);
|
||||
srcBox.bottom = std::min<int32_t>(srcBox.top + visibleRect.height, previousViewportSize.height);
|
||||
srcBox.back = 1;
|
||||
srcBox.front = 0;
|
||||
|
||||
nsRefPtr<ID3D10Resource> srcResource;
|
||||
previousRTView->GetResource(getter_AddRefs(srcResource));
|
||||
|
||||
device()->CopySubresourceRegion(renderTexture, 0,
|
||||
0, 0, 0,
|
||||
srcResource, 0,
|
||||
&srcBox);
|
||||
} else {
|
||||
float black[] = { 0, 0, 0, 0};
|
||||
device()->ClearRenderTargetView(rtView, black);
|
||||
}
|
||||
}
|
||||
|
||||
ID3D10RenderTargetView *rtViewPtr = rtView;
|
||||
device()->OMSetRenderTargets(1, &rtViewPtr, nullptr);
|
||||
|
||||
renderTargetOffset[0] = (float)visibleRect.x;
|
||||
renderTargetOffset[1] = (float)visibleRect.y;
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
SetRawValue(renderTargetOffset, 0, 8);
|
||||
|
||||
mD3DManager->SetViewport(nsIntSize(visibleRect.Size()));
|
||||
}
|
||||
|
||||
D3D10_RECT oldD3D10Scissor;
|
||||
UINT numRects = 1;
|
||||
device()->RSGetScissorRects(&numRects, &oldD3D10Scissor);
|
||||
// Convert scissor to an nsIntRect. D3D10_RECT's are exclusive
|
||||
// on the bottom and right values.
|
||||
nsIntRect oldScissor(oldD3D10Scissor.left,
|
||||
oldD3D10Scissor.top,
|
||||
oldD3D10Scissor.right - oldD3D10Scissor.left,
|
||||
oldD3D10Scissor.bottom - oldD3D10Scissor.top);
|
||||
|
||||
nsAutoTArray<Layer*, 12> children;
|
||||
SortChildrenBy3DZOrder(children);
|
||||
|
||||
/*
|
||||
* Render this container's contents.
|
||||
*/
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
LayerD3D10* layerToRender = static_cast<LayerD3D10*>(children.ElementAt(i)->ImplData());
|
||||
|
||||
if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsIntRect scissorRect =
|
||||
RenderTargetPixel::ToUntyped(layerToRender->GetLayer()->CalculateScissorRect(RenderTargetPixel::FromUntyped(oldScissor)));
|
||||
if (scissorRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
D3D10_RECT d3drect;
|
||||
d3drect.left = scissorRect.x;
|
||||
d3drect.top = scissorRect.y;
|
||||
d3drect.right = scissorRect.x + scissorRect.width;
|
||||
d3drect.bottom = scissorRect.y + scissorRect.height;
|
||||
device()->RSSetScissorRects(1, &d3drect);
|
||||
|
||||
layerToRender->RenderLayer();
|
||||
}
|
||||
|
||||
device()->RSSetScissorRects(1, &oldD3D10Scissor);
|
||||
|
||||
if (useIntermediate) {
|
||||
mD3DManager->SetViewport(previousViewportSize);
|
||||
ID3D10RenderTargetView *rtView = previousRTView;
|
||||
device()->OMSetRenderTargets(1, &rtView, nullptr);
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
SetRawValue(previousRenderTargetOffset, 0, 8);
|
||||
|
||||
SetEffectTransformAndOpacity();
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
if (LoadMaskTexture()) {
|
||||
if (GetTransform().CanDraw2D()) {
|
||||
technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK);
|
||||
} else {
|
||||
technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK_3D);
|
||||
}
|
||||
} else {
|
||||
technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_NO_MASK);
|
||||
}
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)visibleRect.x,
|
||||
(float)visibleRect.y,
|
||||
(float)visibleRect.width,
|
||||
(float)visibleRect.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
|
||||
ID3D10ShaderResourceView *view;
|
||||
device()->CreateShaderResourceView(renderTexture, nullptr, &view);
|
||||
device()->PSSetShaderResources(0, 1, &view);
|
||||
device()->Draw(4, 0);
|
||||
view->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::LayerManagerDestroyed()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
GetFirstChildD3D10()->LayerManagerDestroyed();
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::Validate()
|
||||
{
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
mSupportsComponentAlphaChildren = false;
|
||||
|
||||
if (UseIntermediateSurface()) {
|
||||
Matrix4x4 transform3D = GetEffectiveTransform();
|
||||
Matrix transform;
|
||||
|
||||
if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
|
||||
// don't need a background, we're going to paint all opaque stuff
|
||||
mSupportsComponentAlphaChildren = true;
|
||||
} else {
|
||||
if (HasOpaqueAncestorLayer(this) &&
|
||||
transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation() &&
|
||||
GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect))
|
||||
{
|
||||
// In this case we can copy up the background. See RenderLayer.
|
||||
mSupportsComponentAlphaChildren = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
|
||||
(mParent && mParent->SupportsComponentAlphaChildren());
|
||||
}
|
||||
|
||||
ReadbackProcessor readback;
|
||||
readback.BuildUpdates(this);
|
||||
|
||||
Layer *layer = GetFirstChild();
|
||||
while (layer) {
|
||||
if (layer->GetType() == TYPE_PAINTED) {
|
||||
static_cast<PaintedLayerD3D10*>(layer)->Validate(&readback);
|
||||
} else {
|
||||
static_cast<LayerD3D10*>(layer->ImplData())->Validate();
|
||||
}
|
||||
layer = layer->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
@ -1,42 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_CONTAINERLAYERD3D10_H
|
||||
#define GFX_CONTAINERLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ContainerLayerD3D10 : public ContainerLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ContainerLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
~ContainerLayerD3D10();
|
||||
|
||||
nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual LayerD3D10* GetFirstChildD3D10();
|
||||
|
||||
virtual void RenderLayer();
|
||||
virtual void Validate();
|
||||
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
|
||||
{
|
||||
DefaultComputeEffectiveTransforms(aTransformToSurface);
|
||||
}
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
#endif /* GFX_CONTAINERLAYERD3D10_H */
|
@ -1,400 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "ImageLayerD3D10.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "yuv_convert.h"
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
#include "D3D9SurfaceImage.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static already_AddRefed<ID3D10Texture2D>
|
||||
DataToTexture(ID3D10Device *aDevice,
|
||||
unsigned char *data,
|
||||
int stride,
|
||||
const IntSize &aSize)
|
||||
{
|
||||
D3D10_SUBRESOURCE_DATA srdata;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
srdata.pSysMem = data;
|
||||
srdata.SysMemPitch = stride;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
HRESULT hr = aDevice->CreateTexture2D(&desc, &srdata, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for data"),
|
||||
hr);
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
}
|
||||
|
||||
static already_AddRefed<ID3D10Texture2D>
|
||||
SurfaceToTexture(ID3D10Device *aDevice,
|
||||
SourceSurface *aSurface,
|
||||
const IntSize &aSize)
|
||||
{
|
||||
if (!aSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *nativeSurf =
|
||||
aSurface->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE);
|
||||
if (nativeSurf) {
|
||||
nsRefPtr<ID3D10Texture2D> texture =
|
||||
static_cast<ID3D10Texture2D*>(nativeSurf);
|
||||
ID3D10Device *dev;
|
||||
texture->GetDevice(&dev);
|
||||
if (dev == aDevice) {
|
||||
return texture.forget();
|
||||
}
|
||||
}
|
||||
RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
|
||||
if (!dataSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<ID3D10Texture2D> texture =
|
||||
DataToTexture(aDevice, map.mData, map.mStride, aSize);
|
||||
dataSurface->Unmap();
|
||||
return texture.forget();
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shader resource view for an image.
|
||||
* Returns nullptr if unsuccessful.
|
||||
* If successful, aHasAlpha will be true iff the resulting texture
|
||||
* has an alpha component.
|
||||
*/
|
||||
ID3D10ShaderResourceView*
|
||||
ImageLayerD3D10::GetImageSRView(Image* aImage, bool& aHasAlpha, IDXGIKeyedMutex **aMutex)
|
||||
{
|
||||
NS_ASSERTION(aImage, "Null image.");
|
||||
|
||||
if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
|
||||
CairoImage *cairoImage =
|
||||
static_cast<CairoImage*>(aImage);
|
||||
|
||||
RefPtr<SourceSurface> surf = cairoImage->GetAsSourceSurface();
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) {
|
||||
nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
|
||||
dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize());
|
||||
|
||||
if (dat->mTexture) {
|
||||
device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView));
|
||||
aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, dat.forget());
|
||||
}
|
||||
}
|
||||
|
||||
aHasAlpha = surf->GetFormat() == SurfaceFormat::B8G8R8A8;
|
||||
} else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
|
||||
if (!aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) {
|
||||
// Use resource sharing to open the D3D9 texture as a D3D10 texture,
|
||||
HRESULT hr;
|
||||
D3D9SurfaceImage* d3dImage = reinterpret_cast<D3D9SurfaceImage*>(aImage);
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
hr = device()->OpenSharedResource(d3dImage->GetShareHandle(),
|
||||
IID_ID3D10Texture2D,
|
||||
(void**)getter_AddRefs(texture));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
|
||||
|
||||
nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
|
||||
dat->mTexture = texture;
|
||||
|
||||
hr = device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr) && dat->mSRView, nullptr);
|
||||
|
||||
aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, dat.forget());
|
||||
}
|
||||
aHasAlpha = false;
|
||||
} else {
|
||||
NS_WARNING("Incorrect image type.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TextureD3D10BackendData *data =
|
||||
static_cast<TextureD3D10BackendData*>(aImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10));
|
||||
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aMutex &&
|
||||
SUCCEEDED(data->mTexture->QueryInterface(IID_IDXGIKeyedMutex, (void**)aMutex))) {
|
||||
if (FAILED((*aMutex)->AcquireSync(0, 0))) {
|
||||
NS_WARNING("Failed to acquire sync on keyed mutex, plugin forgot to release?");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<ID3D10Device> dev;
|
||||
data->mTexture->GetDevice(getter_AddRefs(dev));
|
||||
if (dev != device()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data->mSRView;
|
||||
}
|
||||
|
||||
void
|
||||
ImageLayerD3D10::RenderLayer()
|
||||
{
|
||||
ImageContainer *container = GetContainer();
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoLockImage autoLock(container);
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
IntSize size = image->GetSize();
|
||||
|
||||
SetEffectTransformAndOpacity();
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
nsRefPtr<IDXGIKeyedMutex> keyedMutex;
|
||||
|
||||
if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
|
||||
image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
|
||||
NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
|
||||
!static_cast<CairoImage*>(image)->mSourceSurface ||
|
||||
static_cast<CairoImage*>(image)->mSourceSurface->GetFormat() != SurfaceFormat::A8,
|
||||
"Image layer has alpha image");
|
||||
bool hasAlpha = false;
|
||||
|
||||
nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex));
|
||||
if (!srView) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t shaderFlags = SHADER_PREMUL;
|
||||
shaderFlags |= LoadMaskTexture();
|
||||
shaderFlags |= hasAlpha
|
||||
? SHADER_RGBA : SHADER_RGB;
|
||||
shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST
|
||||
? SHADER_POINT : SHADER_LINEAR;
|
||||
technique = SelectShader(shaderFlags);
|
||||
|
||||
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(srView);
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)0,
|
||||
(float)0,
|
||||
(float)size.width,
|
||||
(float)size.height)
|
||||
);
|
||||
} else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImage *yuvImage =
|
||||
static_cast<PlanarYCbCrImage*>(image);
|
||||
|
||||
if (!yuvImage->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10)) {
|
||||
AllocateTexturesYCbCr(yuvImage);
|
||||
}
|
||||
|
||||
PlanarYCbCrD3D10BackendData *data =
|
||||
static_cast<PlanarYCbCrD3D10BackendData*>(yuvImage->GetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10));
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<ID3D10Device> dev;
|
||||
data->mYTexture->GetDevice(getter_AddRefs(dev));
|
||||
if (dev != device()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: At some point we should try to deal with mFilter here, you don't
|
||||
// really want to use point filtering in the case of NEAREST, since that
|
||||
// would also use point filtering for Chroma upsampling. Where most likely
|
||||
// the user would only want point filtering for final RGB image upsampling.
|
||||
|
||||
technique = SelectShader(SHADER_YCBCR | LoadMaskTexture());
|
||||
|
||||
effect()->GetVariableByName("tY")->AsShaderResource()->SetResource(data->mYView);
|
||||
effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(data->mCbView);
|
||||
effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(data->mCrView);
|
||||
|
||||
/*
|
||||
* Send 3d control data and metadata to NV3DVUtils
|
||||
*/
|
||||
if (GetNv3DVUtils()) {
|
||||
Nv_Stereo_Mode mode;
|
||||
switch (yuvImage->GetData()->mStereoMode) {
|
||||
case StereoMode::LEFT_RIGHT:
|
||||
mode = NV_STEREO_MODE_LEFT_RIGHT;
|
||||
break;
|
||||
case StereoMode::RIGHT_LEFT:
|
||||
mode = NV_STEREO_MODE_RIGHT_LEFT;
|
||||
break;
|
||||
case StereoMode::BOTTOM_TOP:
|
||||
mode = NV_STEREO_MODE_BOTTOM_TOP;
|
||||
break;
|
||||
case StereoMode::TOP_BOTTOM:
|
||||
mode = NV_STEREO_MODE_TOP_BOTTOM;
|
||||
break;
|
||||
case StereoMode::MONO:
|
||||
mode = NV_STEREO_MODE_MONO;
|
||||
break;
|
||||
}
|
||||
|
||||
// Send control data even in mono case so driver knows to leave stereo mode.
|
||||
GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
|
||||
|
||||
if (yuvImage->GetData()->mStereoMode != StereoMode::MONO) {
|
||||
// Dst resource is optional
|
||||
GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetData()->mYSize.width,
|
||||
(unsigned int)yuvImage->GetData()->mYSize.height, (HANDLE)(data->mYTexture), (HANDLE)(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)0,
|
||||
(float)0,
|
||||
(float)size.width,
|
||||
(float)size.height)
|
||||
);
|
||||
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width,
|
||||
(float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height,
|
||||
(float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width,
|
||||
(float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height)
|
||||
);
|
||||
} else {
|
||||
MOZ_CRASH("unexpected image format");
|
||||
}
|
||||
|
||||
bool resetTexCoords = image->GetFormat() == ImageFormat::PLANAR_YCBCR;
|
||||
image = nullptr;
|
||||
autoLock.Unlock();
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
|
||||
if (keyedMutex) {
|
||||
keyedMutex->ReleaseSync(0);
|
||||
}
|
||||
|
||||
if (resetTexCoords) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
GetContainer()->NotifyPaintedImage(image);
|
||||
}
|
||||
|
||||
void ImageLayerD3D10::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
|
||||
{
|
||||
nsAutoPtr<PlanarYCbCrD3D10BackendData> backendData(
|
||||
new PlanarYCbCrD3D10BackendData);
|
||||
|
||||
const PlanarYCbCrData *data = aImage->GetData();
|
||||
|
||||
D3D10_SUBRESOURCE_DATA dataY;
|
||||
D3D10_SUBRESOURCE_DATA dataCb;
|
||||
D3D10_SUBRESOURCE_DATA dataCr;
|
||||
CD3D10_TEXTURE2D_DESC descY(DXGI_FORMAT_A8_UNORM,
|
||||
data->mYSize.width,
|
||||
data->mYSize.height, 1, 1);
|
||||
CD3D10_TEXTURE2D_DESC descCbCr(DXGI_FORMAT_A8_UNORM,
|
||||
data->mCbCrSize.width,
|
||||
data->mCbCrSize.height, 1, 1);
|
||||
|
||||
descY.Usage = descCbCr.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
dataY.pSysMem = data->mYChannel;
|
||||
dataY.SysMemPitch = data->mYStride;
|
||||
dataCb.pSysMem = data->mCbChannel;
|
||||
dataCb.SysMemPitch = data->mCbCrStride;
|
||||
dataCr.pSysMem = data->mCrChannel;
|
||||
dataCr.SysMemPitch = data->mCbCrStride;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&descY, &dataY, getter_AddRefs(backendData->mYTexture));
|
||||
if (!FAILED(hr)) {
|
||||
hr = device()->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(backendData->mCbTexture));
|
||||
}
|
||||
if (!FAILED(hr)) {
|
||||
hr = device()->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(backendData->mCrTexture));
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D10::AllocateTextures(): Failed to create texture"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
device()->CreateShaderResourceView(backendData->mYTexture, nullptr, getter_AddRefs(backendData->mYView));
|
||||
device()->CreateShaderResourceView(backendData->mCbTexture, nullptr, getter_AddRefs(backendData->mCbView));
|
||||
device()->CreateShaderResourceView(backendData->mCrTexture, nullptr, getter_AddRefs(backendData->mCrView));
|
||||
|
||||
aImage->SetBackendData(mozilla::layers::LayersBackend::LAYERS_D3D10, backendData.forget());
|
||||
}
|
||||
|
||||
already_AddRefed<ID3D10ShaderResourceView>
|
||||
ImageLayerD3D10::GetAsTexture(gfx::IntSize* aSize)
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoLockImage autoLock(GetContainer());
|
||||
|
||||
Image *image = autoLock.GetImage();
|
||||
if (!image) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*aSize = image->GetSize();
|
||||
bool dontCare;
|
||||
nsRefPtr<ID3D10ShaderResourceView> result = GetImageSRView(image, dontCare);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
@ -1,60 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_IMAGELAYERD3D10_H
|
||||
#define GFX_IMAGELAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "yuv_convert.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ImageLayerD3D10 : public ImageLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ImageLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ImageLayer(aManager, nullptr)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
// LayerD3D10 Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer();
|
||||
|
||||
void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage);
|
||||
|
||||
virtual already_AddRefed<ID3D10ShaderResourceView> GetAsTexture(gfx::IntSize* aSize);
|
||||
|
||||
private:
|
||||
ID3D10ShaderResourceView* GetImageSRView(Image* aImage, bool& aHasAlpha,
|
||||
IDXGIKeyedMutex **aMutex = nullptr);
|
||||
};
|
||||
|
||||
struct PlanarYCbCrD3D10BackendData : public ImageBackendData
|
||||
{
|
||||
nsRefPtr<ID3D10Texture2D> mYTexture;
|
||||
nsRefPtr<ID3D10Texture2D> mCrTexture;
|
||||
nsRefPtr<ID3D10Texture2D> mCbTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mYView;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mCbView;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mCrView;
|
||||
};
|
||||
|
||||
struct TextureD3D10BackendData : public ImageBackendData
|
||||
{
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_IMAGELAYERD3D10_H */
|
@ -1,888 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 <algorithm>
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "LayerManagerD3D10Effect.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "gfxFailure.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "dxgi.h"
|
||||
|
||||
#include "ContainerLayerD3D10.h"
|
||||
#include "PaintedLayerD3D10.h"
|
||||
#include "ColorLayerD3D10.h"
|
||||
#include "CanvasLayerD3D10.h"
|
||||
#include "ReadbackLayerD3D10.h"
|
||||
#include "ImageLayerD3D10.h"
|
||||
#include "mozilla/layers/PLayerChild.h"
|
||||
#include "mozilla/WidgetUtils.h"
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#ifdef MOZ_METRO
|
||||
#include "DXGI1_2.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace std;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float position[2];
|
||||
};
|
||||
|
||||
// {592BF306-0EED-4F76-9D03-A0846450F472}
|
||||
static const GUID sDeviceAttachments =
|
||||
{ 0x592bf306, 0xeed, 0x4f76, { 0x9d, 0x3, 0xa0, 0x84, 0x64, 0x50, 0xf4, 0x72 } };
|
||||
// {716AEDB1-C9C3-4B4D-8332-6F65D44AF6A8}
|
||||
static const GUID sLayerManagerCount =
|
||||
{ 0x716aedb1, 0xc9c3, 0x4b4d, { 0x83, 0x32, 0x6f, 0x65, 0xd4, 0x4a, 0xf6, 0xa8 } };
|
||||
|
||||
LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget)
|
||||
: mWidget(aWidget)
|
||||
, mDisableSequenceForNextFrame(false)
|
||||
{
|
||||
}
|
||||
|
||||
struct DeviceAttachments
|
||||
{
|
||||
nsRefPtr<ID3D10Effect> mEffect;
|
||||
nsRefPtr<ID3D10InputLayout> mInputLayout;
|
||||
nsRefPtr<ID3D10Buffer> mVertexBuffer;
|
||||
nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
|
||||
};
|
||||
|
||||
LayerManagerD3D10::~LayerManagerD3D10()
|
||||
{
|
||||
if (mDevice) {
|
||||
int referenceCount = 0;
|
||||
UINT size = sizeof(referenceCount);
|
||||
HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
|
||||
NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device.");
|
||||
referenceCount--;
|
||||
mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
|
||||
|
||||
if (!referenceCount) {
|
||||
DeviceAttachments *attachments;
|
||||
size = sizeof(attachments);
|
||||
mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments);
|
||||
// No LayerManagers left for this device. Clear out interfaces stored which
|
||||
// hold a reference to the device.
|
||||
mDevice->SetPrivateData(sDeviceAttachments, 0, nullptr);
|
||||
|
||||
delete attachments;
|
||||
}
|
||||
}
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetHRESULT(HRESULT* aHresultPtr, HRESULT aHresult)
|
||||
{
|
||||
if (aHresultPtr) {
|
||||
*aHresultPtr = aHresult;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
LayerManagerD3D10::Initialize(bool force, HRESULT* aHresultPtr)
|
||||
{
|
||||
ScopedGfxFeatureReporter reporter("D3D10 Layers", force);
|
||||
|
||||
HRESULT hr = E_UNEXPECTED;
|
||||
|
||||
/* Create an Nv3DVUtils instance */
|
||||
if (!mNv3DVUtils) {
|
||||
mNv3DVUtils = new Nv3DVUtils();
|
||||
if (!mNv3DVUtils) {
|
||||
NS_WARNING("Could not create a new instance of Nv3DVUtils.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the Nv3DVUtils object */
|
||||
if (mNv3DVUtils) {
|
||||
mNv3DVUtils->Initialize();
|
||||
}
|
||||
|
||||
mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!mDevice) {
|
||||
SetHRESULT(aHresultPtr, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do some post device creation setup
|
||||
*/
|
||||
if (mNv3DVUtils) {
|
||||
IUnknown* devUnknown = nullptr;
|
||||
if (mDevice) {
|
||||
mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown);
|
||||
}
|
||||
mNv3DVUtils->SetDeviceInfo(devUnknown);
|
||||
}
|
||||
|
||||
int referenceCount = 0;
|
||||
UINT size = sizeof(referenceCount);
|
||||
// If this isn't there yet it'll fail, count will remain 0, which is correct.
|
||||
mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
|
||||
referenceCount++;
|
||||
mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
|
||||
|
||||
DeviceAttachments *attachments;
|
||||
size = sizeof(DeviceAttachments*);
|
||||
if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
|
||||
attachments = new DeviceAttachments;
|
||||
mDevice->SetPrivateData(sDeviceAttachments, sizeof(attachments), &attachments);
|
||||
|
||||
SetLastError(0);
|
||||
decltype(D3D10CreateEffectFromMemory)* createEffect =
|
||||
(decltype(D3D10CreateEffectFromMemory)*)
|
||||
GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory");
|
||||
if (!createEffect) {
|
||||
SetHRESULT(aHresultPtr, HRESULT_FROM_WIN32(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = createEffect((void*)g_main,
|
||||
sizeof(g_main),
|
||||
D3D10_EFFECT_SINGLE_THREADED,
|
||||
mDevice,
|
||||
nullptr,
|
||||
getter_AddRefs(mEffect));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetHRESULT(aHresultPtr, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
attachments->mEffect = mEffect;
|
||||
|
||||
D3D10_INPUT_ELEMENT_DESC layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
D3D10_PASS_DESC passDesc;
|
||||
mEffect->GetTechniqueByName("RenderRGBLayerPremul")->GetPassByIndex(0)->
|
||||
GetDesc(&passDesc);
|
||||
|
||||
hr = mDevice->CreateInputLayout(layout,
|
||||
sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
|
||||
passDesc.pIAInputSignature,
|
||||
passDesc.IAInputSignatureSize,
|
||||
getter_AddRefs(mInputLayout));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetHRESULT(aHresultPtr, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
attachments->mInputLayout = mInputLayout;
|
||||
|
||||
Vertex vertices[] = { {{0.0, 0.0}}, {{1.0, 0.0}}, {{0.0, 1.0}}, {{1.0, 1.0}} };
|
||||
CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = (void*)vertices;
|
||||
|
||||
hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
SetHRESULT(aHresultPtr, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
attachments->mVertexBuffer = mVertexBuffer;
|
||||
} else {
|
||||
mEffect = attachments->mEffect;
|
||||
mVertexBuffer = attachments->mVertexBuffer;
|
||||
mInputLayout = attachments->mInputLayout;
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIDevice> dxgiDevice;
|
||||
nsRefPtr<IDXGIAdapter> dxgiAdapter;
|
||||
|
||||
mDevice->QueryInterface(dxgiDevice.StartAssignment());
|
||||
dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
|
||||
|
||||
#ifdef MOZ_METRO
|
||||
if (IsRunningInWindowsMetro()) {
|
||||
nsRefPtr<IDXGIFactory2> dxgiFactory;
|
||||
dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
|
||||
// Automatically detect the width and the height from the winrt CoreWindow
|
||||
swapDesc.Width = rect.width;
|
||||
swapDesc.Height = rect.height;
|
||||
// This is the most common swapchain format
|
||||
swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
swapDesc.Stereo = false;
|
||||
// Don't use multi-sampling
|
||||
swapDesc.SampleDesc.Count = 1;
|
||||
swapDesc.SampleDesc.Quality = 0;
|
||||
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
// Use double buffering to enable flip
|
||||
swapDesc.BufferCount = 2;
|
||||
swapDesc.Scaling = DXGI_SCALING_NONE;
|
||||
// All Metro style apps must use this SwapEffect
|
||||
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
swapDesc.Flags = 0;
|
||||
|
||||
/**
|
||||
* Create a swap chain, this swap chain will contain the backbuffer for
|
||||
* the window we draw to. The front buffer is the full screen front
|
||||
* buffer.
|
||||
*/
|
||||
nsRefPtr<IDXGISwapChain1> swapChain1;
|
||||
hr = dxgiFactory->CreateSwapChainForCoreWindow(
|
||||
dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW),
|
||||
&swapDesc, nullptr, getter_AddRefs(swapChain1));
|
||||
if (FAILED(hr)) {
|
||||
SetHRESULT(aHresultPtr, hr);
|
||||
return false;
|
||||
}
|
||||
mSwapChain = swapChain1;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
nsRefPtr<IDXGIFactory> dxgiFactory;
|
||||
dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
::ZeroMemory(&swapDesc, sizeof(swapDesc));
|
||||
swapDesc.BufferDesc.Width = 0;
|
||||
swapDesc.BufferDesc.Height = 0;
|
||||
swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
|
||||
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
|
||||
swapDesc.SampleDesc.Count = 1;
|
||||
swapDesc.SampleDesc.Quality = 0;
|
||||
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapDesc.BufferCount = 1;
|
||||
swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
swapDesc.Windowed = TRUE;
|
||||
// We don't really need this flag, however it seems on some NVidia hardware
|
||||
// smaller area windows do not present properly without this flag. This flag
|
||||
// should have no negative consequences by itself. See bug 613790. This flag
|
||||
// is broken on optimus devices. As a temporary solution we don't set it
|
||||
// there, the only way of reliably detecting we're on optimus is looking for
|
||||
// the DLL. See Bug 623807.
|
||||
if (gfxWindowsPlatform::IsOptimus()) {
|
||||
swapDesc.Flags = 0;
|
||||
} else {
|
||||
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a swap chain, this swap chain will contain the backbuffer for
|
||||
* the window we draw to. The front buffer is the full screen front
|
||||
* buffer.
|
||||
*/
|
||||
hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, getter_AddRefs(mSwapChain));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need this because we don't want DXGI to respond to Alt+Enter.
|
||||
dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||
}
|
||||
|
||||
reporter.SetSuccessful();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::Destroy()
|
||||
{
|
||||
if (!IsDestroyed()) {
|
||||
if (mRoot) {
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->LayerManagerDestroyed();
|
||||
}
|
||||
// XXX need to be careful here about surface destruction
|
||||
// racing with share-to-chrome message
|
||||
}
|
||||
LayerManager::Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetRoot(Layer *aRoot)
|
||||
{
|
||||
mRoot = aRoot;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::BeginTransaction()
|
||||
{
|
||||
mInTransaction = true;
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
MOZ_LAYERS_LOG(("[----- BeginTransaction"));
|
||||
Log();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget)
|
||||
{
|
||||
mInTransaction = true;
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
bool
|
||||
LayerManagerD3D10::EndEmptyTransaction(EndTransactionFlags aFlags)
|
||||
{
|
||||
mInTransaction = false;
|
||||
|
||||
if (!mRoot)
|
||||
return false;
|
||||
|
||||
EndTransaction(nullptr, nullptr, aFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags)
|
||||
{
|
||||
mInTransaction = false;
|
||||
|
||||
if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
|
||||
mCurrentCallbackInfo.Callback = aCallback;
|
||||
mCurrentCallbackInfo.CallbackData = aCallbackData;
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
// Apply pending tree updates before recomputing effective
|
||||
// properties.
|
||||
mRoot->ApplyPendingUpdatesToSubtree();
|
||||
}
|
||||
|
||||
// The results of our drawing always go directly into a pixel buffer,
|
||||
// so we don't need to pass any global transform here.
|
||||
mRoot->ComputeEffectiveTransforms(Matrix4x4());
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
|
||||
Log();
|
||||
#endif
|
||||
|
||||
Render(aFlags);
|
||||
mCurrentCallbackInfo.Callback = nullptr;
|
||||
mCurrentCallbackInfo.CallbackData = nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
Log();
|
||||
MOZ_LAYERS_LOG(("]----- EndTransaction"));
|
||||
#endif
|
||||
|
||||
mTarget = nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<PaintedLayer>
|
||||
LayerManagerD3D10::CreatePaintedLayer()
|
||||
{
|
||||
nsRefPtr<PaintedLayer> layer = new PaintedLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ContainerLayer>
|
||||
LayerManagerD3D10::CreateContainerLayer()
|
||||
{
|
||||
nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageLayer>
|
||||
LayerManagerD3D10::CreateImageLayer()
|
||||
{
|
||||
nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ColorLayer>
|
||||
LayerManagerD3D10::CreateColorLayer()
|
||||
{
|
||||
nsRefPtr<ColorLayer> layer = new ColorLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CanvasLayer>
|
||||
LayerManagerD3D10::CreateCanvasLayer()
|
||||
{
|
||||
nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ReadbackLayer>
|
||||
LayerManagerD3D10::CreateReadbackLayer()
|
||||
{
|
||||
nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
LayerManagerD3D10::CreateOptimalDrawTarget(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
if ((aFormat != SurfaceFormat::B8G8R8X8 &&
|
||||
aFormat != SurfaceFormat::B8G8R8A8)) {
|
||||
return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
|
||||
return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> dt =
|
||||
Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
|
||||
|
||||
if (!dt) {
|
||||
return LayerManager::CreateOptimalDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
LayerManagerD3D10::CreateOptimalMaskDrawTarget(const IntSize &aSize)
|
||||
{
|
||||
return CreateOptimalDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
|
||||
}
|
||||
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
if ((aFormat != SurfaceFormat::B8G8R8A8 &&
|
||||
aFormat != SurfaceFormat::B8G8R8X8) ||
|
||||
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() != BackendType::DIRECT2D) {
|
||||
return LayerManager::CreateDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!");
|
||||
return LayerManager::CreateDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> surface =
|
||||
Factory::CreateDrawTargetForD3D10Texture(texture, aFormat);
|
||||
|
||||
if (!surface) {
|
||||
return LayerManager::CreateDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10*
|
||||
LayerManagerD3D10::readbackManager()
|
||||
{
|
||||
EnsureReadbackManager();
|
||||
return mReadbackManager;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetViewport(const nsIntSize &aViewport)
|
||||
{
|
||||
mViewport = aViewport;
|
||||
|
||||
D3D10_VIEWPORT viewport;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.MinDepth = 0;
|
||||
viewport.Width = aViewport.width;
|
||||
viewport.Height = aViewport.height;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
|
||||
mDevice->RSSetViewports(1, &viewport);
|
||||
|
||||
gfx3DMatrix projection;
|
||||
/*
|
||||
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
|
||||
* <1.0, -1.0> bottomright)
|
||||
*/
|
||||
projection._11 = 2.0f / aViewport.width;
|
||||
projection._22 = -2.0f / aViewport.height;
|
||||
projection._33 = 0.0f;
|
||||
projection._41 = -1.0f;
|
||||
projection._42 = 1.0f;
|
||||
projection._44 = 1.0f;
|
||||
|
||||
HRESULT hr = mEffect->GetVariableByName("mProjection")->
|
||||
SetRawValue(&projection._11, 0, 64);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set projection matrix.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetupInputAssembler()
|
||||
{
|
||||
mDevice->IASetInputLayout(mInputLayout);
|
||||
|
||||
UINT stride = sizeof(Vertex);
|
||||
UINT offset = 0;
|
||||
ID3D10Buffer *buffer = mVertexBuffer;
|
||||
mDevice->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
|
||||
mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetupPipeline()
|
||||
{
|
||||
VerifyBufferSize();
|
||||
UpdateRenderTarget();
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = mEffect->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set Texture Coordinates.");
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D10RenderTargetView *view = mRTView;
|
||||
mDevice->OMSetRenderTargets(1, &view, nullptr);
|
||||
|
||||
SetupInputAssembler();
|
||||
|
||||
SetViewport(nsIntSize(rect.width, rect.height));
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::UpdateRenderTarget()
|
||||
{
|
||||
if (mRTView || !mSwapChain) {
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> backBuf;
|
||||
hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
mDevice->CreateRenderTargetView(backBuf, nullptr, getter_AddRefs(mRTView));
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::VerifyBufferSize()
|
||||
{
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
if (mSwapChain) {
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
mSwapChain->GetDesc(&swapDesc);
|
||||
|
||||
if (swapDesc.BufferDesc.Width == rect.width &&
|
||||
swapDesc.BufferDesc.Height == rect.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRTView = nullptr;
|
||||
if (IsRunningInWindowsMetro()) {
|
||||
mSwapChain->ResizeBuffers(2, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
mDisableSequenceForNextFrame = true;
|
||||
} else if (gfxWindowsPlatform::IsOptimus()) {
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0);
|
||||
} else {
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::EnsureReadbackManager()
|
||||
{
|
||||
if (mReadbackManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceAttachments *attachments;
|
||||
UINT size = sizeof(DeviceAttachments*);
|
||||
if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
|
||||
// Strange! This shouldn't happen ... return a readback manager for this
|
||||
// layer manager only.
|
||||
mReadbackManager = new ReadbackManagerD3D10();
|
||||
gfx::LogFailure(NS_LITERAL_CSTRING("Couldn't get device attachments for device."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachments->mReadbackManager) {
|
||||
mReadbackManager = attachments->mReadbackManager;
|
||||
return;
|
||||
}
|
||||
|
||||
mReadbackManager = new ReadbackManagerD3D10();
|
||||
attachments->mReadbackManager = mReadbackManager;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::Render(EndTransactionFlags aFlags)
|
||||
{
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
|
||||
|
||||
if (aFlags & END_NO_COMPOSITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetupPipeline();
|
||||
|
||||
float black[] = { 0, 0, 0, 0 };
|
||||
device()->ClearRenderTargetView(mRTView, black);
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
const nsIntRect *clipRect = mRoot->GetClipRect();
|
||||
D3D10_RECT r;
|
||||
if (clipRect) {
|
||||
r.left = (LONG)clipRect->x;
|
||||
r.top = (LONG)clipRect->y;
|
||||
r.right = (LONG)(clipRect->x + clipRect->width);
|
||||
r.bottom = (LONG)(clipRect->y + clipRect->height);
|
||||
} else {
|
||||
r.left = r.top = 0;
|
||||
r.right = rect.width;
|
||||
r.bottom = rect.height;
|
||||
}
|
||||
device()->RSSetScissorRects(1, &r);
|
||||
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
|
||||
|
||||
if (!mRegionToClear.IsEmpty()) {
|
||||
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
gfx::Matrix4x4 transform;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64);
|
||||
effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
|
||||
|
||||
ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer");
|
||||
|
||||
nsIntRegionRectIterator iter(mRegionToClear);
|
||||
const nsIntRect *r;
|
||||
while ((r = iter.Next())) {
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)r->x,
|
||||
(float)r->y,
|
||||
(float)r->width,
|
||||
(float)r->height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// See bug 630197 - we have some reasons to believe if an earlier call
|
||||
// returned an error, the upcoming present call may raise an exception.
|
||||
// This will check if any of the calls done recently has returned an error
|
||||
// and bails on composition. On the -next- frame we will then abandon
|
||||
// hardware acceleration from gfxWindowsPlatform::VerifyD2DDevice.
|
||||
// This might not be the 'optimal' solution but it will help us assert
|
||||
// whether our thoughts of the causes of the issues are correct.
|
||||
if (FAILED(mDevice->GetDeviceRemovedReason())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTarget) {
|
||||
PaintToTarget();
|
||||
} else {
|
||||
mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
|
||||
mDisableSequenceForNextFrame = false;
|
||||
}
|
||||
RecordFrame();
|
||||
PostPresent();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::PaintToTarget()
|
||||
{
|
||||
nsRefPtr<ID3D10Texture2D> backBuf;
|
||||
|
||||
mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
|
||||
|
||||
D3D10_TEXTURE2D_DESC bbDesc;
|
||||
backBuf->GetDesc(&bbDesc);
|
||||
|
||||
CD3D10_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
|
||||
softDesc.MipLevels = 1;
|
||||
softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
softDesc.Usage = D3D10_USAGE_STAGING;
|
||||
softDesc.BindFlags = 0;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> readTexture;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
|
||||
if (FAILED(hr)) {
|
||||
ReportFailure(NS_LITERAL_CSTRING("LayerManagerD3D10::PaintToTarget(): Failed to create texture"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
device()->CopyResource(readTexture, backBuf);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
readTexture->Map(0, D3D10_MAP_READ, 0, &map);
|
||||
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface((unsigned char*)map.pData,
|
||||
gfxIntSize(bbDesc.Width, bbDesc.Height),
|
||||
map.RowPitch,
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
mTarget->SetSource(tmpSurface);
|
||||
mTarget->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
mTarget->Paint();
|
||||
|
||||
readTexture->Unmap(0);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::ReportFailure(const nsACString &aMsg, HRESULT aCode)
|
||||
{
|
||||
// We could choose to abort here when hr == E_OUTOFMEMORY.
|
||||
nsCString msg;
|
||||
msg.Append(aMsg);
|
||||
msg.AppendLiteral(" Error code: ");
|
||||
msg.AppendInt(uint32_t(aCode));
|
||||
NS_WARNING(msg.BeginReading());
|
||||
|
||||
gfx::LogFailure(msg);
|
||||
}
|
||||
|
||||
LayerD3D10::LayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: mD3DManager(aManager)
|
||||
{
|
||||
}
|
||||
|
||||
ID3D10EffectTechnique*
|
||||
LayerD3D10::SelectShader(uint8_t aFlags)
|
||||
{
|
||||
switch (aFlags) {
|
||||
case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerNonPremulMask");
|
||||
case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerNonPremul");
|
||||
case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPoint");
|
||||
case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPointMask");
|
||||
case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK_3D):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerPremulMask3D");
|
||||
case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerPremulMask");
|
||||
case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerPremulPointMask");
|
||||
case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
|
||||
case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBLayerPremulPointMask");
|
||||
case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBLayerPremulPoint");
|
||||
case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBLayerPremulMask");
|
||||
case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderRGBLayerPremul");
|
||||
case (SHADER_SOLID | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderSolidColorLayerMask");
|
||||
case (SHADER_SOLID | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderSolidColorLayer");
|
||||
case (SHADER_COMPONENT_ALPHA | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderComponentAlphaLayerMask");
|
||||
case (SHADER_COMPONENT_ALPHA | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderComponentAlphaLayer");
|
||||
case (SHADER_YCBCR | SHADER_MASK):
|
||||
return effect()->GetTechniqueByName("RenderYCbCrLayerMask");
|
||||
case (SHADER_YCBCR | SHADER_NO_MASK):
|
||||
return effect()->GetTechniqueByName("RenderYCbCrLayer");
|
||||
default:
|
||||
NS_ERROR("Invalid shader.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
LayerD3D10::LoadMaskTexture()
|
||||
{
|
||||
if (Layer* maskLayer = GetLayer()->GetMaskLayer()) {
|
||||
IntSize size;
|
||||
nsRefPtr<ID3D10ShaderResourceView> maskSRV =
|
||||
static_cast<LayerD3D10*>(maskLayer->ImplData())->GetAsTexture(&size);
|
||||
|
||||
if (!maskSRV) {
|
||||
return SHADER_NO_MASK;
|
||||
}
|
||||
|
||||
Matrix maskTransform;
|
||||
Matrix4x4 effectiveTransform = maskLayer->GetEffectiveTransform();
|
||||
bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform);
|
||||
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
|
||||
Rect bounds = Rect(Point(), Size(size));
|
||||
bounds = maskTransform.TransformBounds(bounds);
|
||||
|
||||
effect()->GetVariableByName("vMaskQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)bounds.x,
|
||||
(float)bounds.y,
|
||||
(float)bounds.width,
|
||||
(float)bounds.height)
|
||||
);
|
||||
|
||||
effect()->GetVariableByName("tMask")->AsShaderResource()->SetResource(maskSRV);
|
||||
return SHADER_MASK;
|
||||
}
|
||||
|
||||
return SHADER_NO_MASK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,605 +0,0 @@
|
||||
typedef float4 rect;
|
||||
cbuffer PerLayer {
|
||||
rect vTextureCoords;
|
||||
rect vLayerQuad;
|
||||
rect vMaskQuad;
|
||||
float fLayerOpacity;
|
||||
float4x4 mLayerTransform;
|
||||
}
|
||||
|
||||
cbuffer PerOccasionalLayer {
|
||||
float4 vRenderTargetOffset;
|
||||
float4 fLayerColor;
|
||||
}
|
||||
|
||||
cbuffer PerLayerManager {
|
||||
float4x4 mProjection;
|
||||
}
|
||||
|
||||
BlendState Premul
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = One;
|
||||
DestBlend = Inv_Src_Alpha;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = One;
|
||||
DestBlendAlpha = Inv_Src_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
BlendState NonPremul
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = Src_Alpha;
|
||||
DestBlend = Inv_Src_Alpha;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = One;
|
||||
DestBlendAlpha = Inv_Src_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
BlendState NoBlendDual
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = FALSE;
|
||||
BlendEnable[1] = FALSE;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
RenderTargetWriteMask[1] = 0x0F; // All
|
||||
};
|
||||
|
||||
BlendState ComponentAlphaBlend
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = One;
|
||||
DestBlend = Inv_Src1_Color;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = One;
|
||||
DestBlendAlpha = Inv_Src_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
RasterizerState LayerRast
|
||||
{
|
||||
ScissorEnable = True;
|
||||
CullMode = None;
|
||||
};
|
||||
|
||||
Texture2D tRGB;
|
||||
Texture2D tY;
|
||||
Texture2D tCb;
|
||||
Texture2D tCr;
|
||||
Texture2D tRGBWhite;
|
||||
Texture2D tMask;
|
||||
|
||||
SamplerState LayerTextureSamplerLinear
|
||||
{
|
||||
Filter = MIN_MAG_MIP_LINEAR;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
SamplerState LayerTextureSamplerPoint
|
||||
{
|
||||
Filter = MIN_MAG_MIP_POINT;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
struct VS_INPUT {
|
||||
float2 vPosition : POSITION;
|
||||
};
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 vPosition : SV_Position;
|
||||
float2 vTexCoords : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct VS_MASK_OUTPUT {
|
||||
float4 vPosition : SV_Position;
|
||||
float2 vTexCoords : TEXCOORD0;
|
||||
float2 vMaskCoords : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct VS_MASK_3D_OUTPUT {
|
||||
float4 vPosition : SV_Position;
|
||||
float2 vTexCoords : TEXCOORD0;
|
||||
float3 vMaskCoords : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct PS_OUTPUT {
|
||||
float4 vSrc;
|
||||
float4 vAlpha;
|
||||
};
|
||||
|
||||
struct PS_DUAL_OUTPUT {
|
||||
float4 vOutput1 : SV_Target0;
|
||||
float4 vOutput2 : SV_Target1;
|
||||
};
|
||||
|
||||
float2 TexCoords(const float2 aPosition)
|
||||
{
|
||||
float2 result;
|
||||
const float2 size = vTextureCoords.zw;
|
||||
result.x = vTextureCoords.x + aPosition.x * size.x;
|
||||
result.y = vTextureCoords.y + aPosition.y * size.y;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 TransformedPostion(float2 aInPosition)
|
||||
{
|
||||
// the current vertex's position on the quad
|
||||
float4 position = float4(0, 0, 0, 1);
|
||||
|
||||
// We use 4 component floats to uniquely describe a rectangle, by the structure
|
||||
// of x, y, width, height. This allows us to easily generate the 4 corners
|
||||
// of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
|
||||
// stream source for our LayerQuad vertex shader. We do this by doing:
|
||||
// Xout = x + Xin * width
|
||||
// Yout = y + Yin * height
|
||||
float2 size = vLayerQuad.zw;
|
||||
position.x = vLayerQuad.x + aInPosition.x * size.x;
|
||||
position.y = vLayerQuad.y + aInPosition.y * size.y;
|
||||
|
||||
position = mul(mLayerTransform, position);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
float4 VertexPosition(float4 aTransformedPosition)
|
||||
{
|
||||
float4 result;
|
||||
result.w = aTransformedPosition.w;
|
||||
result.xyz = aTransformedPosition.xyz / aTransformedPosition.w;
|
||||
result -= vRenderTargetOffset;
|
||||
result.xyz *= result.w;
|
||||
|
||||
result = mul(mProjection, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
|
||||
{
|
||||
VS_OUTPUT outp;
|
||||
float4 position = TransformedPostion(aVertex.vPosition);
|
||||
|
||||
outp.vPosition = VertexPosition(position);
|
||||
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
|
||||
|
||||
return outp;
|
||||
}
|
||||
|
||||
VS_MASK_OUTPUT LayerQuadMaskVS(const VS_INPUT aVertex)
|
||||
{
|
||||
VS_MASK_OUTPUT outp;
|
||||
float4 position = TransformedPostion(aVertex.vPosition);
|
||||
|
||||
outp.vPosition = VertexPosition(position);
|
||||
|
||||
// calculate the position on the mask texture
|
||||
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
|
||||
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
|
||||
|
||||
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
|
||||
|
||||
return outp;
|
||||
}
|
||||
|
||||
VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex)
|
||||
{
|
||||
VS_MASK_3D_OUTPUT outp;
|
||||
float4 position = TransformedPostion(aVertex.vPosition);
|
||||
|
||||
outp.vPosition = VertexPosition(position);
|
||||
|
||||
// calculate the position on the mask texture
|
||||
position.xyz /= position.w;
|
||||
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
|
||||
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
|
||||
// We use the w coord to do non-perspective correct interpolation:
|
||||
// the quad might be transformed in 3D, in which case it will have some
|
||||
// perspective. The graphics card will do perspective-correct interpolation
|
||||
// of the texture, but our mask is already transformed and so we require
|
||||
// linear interpolation. Therefore, we must correct the interpolation
|
||||
// ourselves, we do this by multiplying all coords by w here, and dividing by
|
||||
// w in the pixel shader (post-interpolation), we pass w in outp.vMaskCoords.z.
|
||||
// See http://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness
|
||||
outp.vMaskCoords.z = 1;
|
||||
outp.vMaskCoords *= position.w;
|
||||
|
||||
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
|
||||
|
||||
return outp;
|
||||
}
|
||||
|
||||
float4 RGBAShaderMask(const VS_MASK_OUTPUT aVertex, uniform sampler aSampler) : SV_Target
|
||||
{
|
||||
float2 maskCoords = aVertex.vMaskCoords;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
return tRGB.Sample(aSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
|
||||
}
|
||||
|
||||
float4 RGBAShaderLinearMask3D(const VS_MASK_3D_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
return tRGB.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords) * fLayerOpacity * mask;
|
||||
}
|
||||
|
||||
float4 RGBShaderMask(const VS_MASK_OUTPUT aVertex, uniform sampler aSampler) : SV_Target
|
||||
{
|
||||
float4 result;
|
||||
result = tRGB.Sample(aSampler, aVertex.vTexCoords) * fLayerOpacity;
|
||||
result.a = fLayerOpacity;
|
||||
|
||||
float2 maskCoords = aVertex.vMaskCoords;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
return result * mask;
|
||||
}
|
||||
|
||||
/* From Rec601:
|
||||
[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16]
|
||||
[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128]
|
||||
[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128]
|
||||
|
||||
For [0,1] instead of [0,255], and to 5 places:
|
||||
[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
|
||||
[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
|
||||
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
|
||||
*/
|
||||
|
||||
float4 CalculateYCbCrColor(const float2 aTexCoords)
|
||||
{
|
||||
float4 yuv;
|
||||
float4 color;
|
||||
|
||||
yuv.r = tCr.Sample(LayerTextureSamplerLinear, aTexCoords).a - 0.50196;
|
||||
yuv.g = tY.Sample(LayerTextureSamplerLinear, aTexCoords).a - 0.06275;
|
||||
yuv.b = tCb.Sample(LayerTextureSamplerLinear, aTexCoords).a - 0.50196;
|
||||
|
||||
color.r = yuv.g * 1.16438 + yuv.r * 1.59603;
|
||||
color.g = yuv.g * 1.16438 - 0.81297 * yuv.r - 0.39176 * yuv.b;
|
||||
color.b = yuv.g * 1.16438 + yuv.b * 2.01723;
|
||||
color.a = 1.0f;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 YCbCrShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float2 maskCoords = aVertex.vMaskCoords;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
|
||||
return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity * mask;
|
||||
}
|
||||
|
||||
PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
PS_OUTPUT result;
|
||||
|
||||
result.vSrc = tRGB.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords);
|
||||
result.vAlpha = 1.0 - tRGBWhite.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords) + result.vSrc;
|
||||
result.vSrc.a = result.vAlpha.g;
|
||||
|
||||
float2 maskCoords = aVertex.vMaskCoords;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
result.vSrc *= fLayerOpacity * mask;
|
||||
result.vAlpha *= fLayerOpacity * mask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 SolidColorShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float2 maskCoords = aVertex.vMaskCoords;
|
||||
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
|
||||
return fLayerColor * mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Un-masked versions
|
||||
*************************************************************
|
||||
*/
|
||||
float4 RGBAShader(const VS_OUTPUT aVertex, uniform sampler aSampler) : SV_Target
|
||||
{
|
||||
return tRGB.Sample(aSampler, aVertex.vTexCoords) * fLayerOpacity;
|
||||
}
|
||||
|
||||
float4 RGBShader(const VS_OUTPUT aVertex, uniform sampler aSampler) : SV_Target
|
||||
{
|
||||
float4 result;
|
||||
result = tRGB.Sample(aSampler, aVertex.vTexCoords) * fLayerOpacity;
|
||||
result.a = fLayerOpacity;
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 YCbCrShader(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity;
|
||||
}
|
||||
|
||||
PS_OUTPUT ComponentAlphaShader(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
PS_OUTPUT result;
|
||||
|
||||
result.vSrc = tRGB.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords);
|
||||
result.vAlpha = 1.0 - tRGBWhite.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords) + result.vSrc;
|
||||
result.vSrc.a = result.vAlpha.g;
|
||||
result.vSrc *= fLayerOpacity;
|
||||
result.vAlpha *= fLayerOpacity;
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 SolidColorShader(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
return fLayerColor;
|
||||
}
|
||||
|
||||
PS_DUAL_OUTPUT AlphaExtractionPrepareShader(const VS_OUTPUT aVertex)
|
||||
{
|
||||
PS_DUAL_OUTPUT result;
|
||||
result.vOutput1 = float4(0, 0, 0, 1);
|
||||
result.vOutput2 = float4(1, 1, 1, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShader(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShader(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShader(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShader(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShader(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShader(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderYCbCrLayer
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, YCbCrShader() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderComponentAlphaLayer
|
||||
{
|
||||
Pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( ComponentAlphaBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, ComponentAlphaShader() ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
technique10 RenderSolidColorLayer
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderClearLayer
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NoBlendDual, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 PrepareAlphaExtractionTextures
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NoBlendDual, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, AlphaExtractionPrepareShader() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremulMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShaderMask(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremulPointMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShaderMask(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremulMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderMask(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremulMask3D
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMask3DVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderLinearMask3D() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremulMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderMask(LayerTextureSamplerLinear) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremulPointMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderMask(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremulPointMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderMask(LayerTextureSamplerPoint) ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderYCbCrLayerMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, YCbCrShaderMask() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderComponentAlphaLayerMask
|
||||
{
|
||||
Pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( ComponentAlphaBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, ComponentAlphaShaderMask() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderSolidColorLayerMask
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadMaskVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShaderMask() ) );
|
||||
}
|
||||
}
|
||||
|
@ -1,288 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_LAYERMANAGERD3D10_H
|
||||
#define GFX_LAYERMANAGERD3D10_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d10_1.h>
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "mozilla/gfx/UserData.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "ReadbackManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class DummyRoot;
|
||||
class Nv3DVUtils;
|
||||
|
||||
/**
|
||||
* This structure is used to pass rectangles to our shader constant. We can use
|
||||
* this for passing rectangular areas to SetVertexShaderConstant. In the format
|
||||
* of a 4 component float(x,y,width,height). Our vertex shader can then use
|
||||
* this to construct rectangular positions from the 0,0-1,1 quad that we source
|
||||
* it with.
|
||||
*/
|
||||
struct ShaderConstantRectD3D10
|
||||
{
|
||||
float mX, mY, mWidth, mHeight;
|
||||
ShaderConstantRectD3D10(float aX, float aY, float aWidth, float aHeight)
|
||||
: mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
|
||||
{ }
|
||||
|
||||
// For easy passing to SetVertexShaderConstantF.
|
||||
operator float* () { return &mX; }
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the LayerManager used for Direct3D 10. For now this will
|
||||
* render on the main thread.
|
||||
*
|
||||
* For the time being, LayerManagerD3D10 forwards layers
|
||||
* transactions.
|
||||
*/
|
||||
class LayerManagerD3D10 : public LayerManager {
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::IntSize IntSize;
|
||||
typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
|
||||
|
||||
public:
|
||||
LayerManagerD3D10(nsIWidget *aWidget);
|
||||
virtual ~LayerManagerD3D10();
|
||||
|
||||
/*
|
||||
* Initializes the layer manager, this is when the layer manager will
|
||||
* actually access the device and attempt to create the swap chain used
|
||||
* to draw to the window. If this method fails the device cannot be used.
|
||||
* This function is not threadsafe.
|
||||
*
|
||||
* return True is initialization was succesful, false when it was not.
|
||||
*/
|
||||
bool Initialize(bool force = false, HRESULT* aHresultPtr = nullptr);
|
||||
|
||||
/*
|
||||
* LayerManager implementation.
|
||||
*/
|
||||
virtual void Destroy();
|
||||
|
||||
virtual void SetRoot(Layer *aLayer);
|
||||
|
||||
virtual void BeginTransaction();
|
||||
|
||||
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
|
||||
|
||||
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT);
|
||||
|
||||
struct CallbackInfo {
|
||||
DrawPaintedLayerCallback Callback;
|
||||
void *CallbackData;
|
||||
};
|
||||
|
||||
virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT);
|
||||
|
||||
const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
|
||||
|
||||
// D3D10 guarantees textures can be at least this size
|
||||
enum {
|
||||
MAX_TEXTURE_SIZE = 8192
|
||||
};
|
||||
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize)
|
||||
{
|
||||
return aSize <= gfx::IntSize(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE);
|
||||
}
|
||||
|
||||
virtual int32_t GetMaxTextureSize() const
|
||||
{
|
||||
return MAX_TEXTURE_SIZE;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<PaintedLayer> CreatePaintedLayer();
|
||||
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
|
||||
virtual already_AddRefed<ImageLayer> CreateImageLayer();
|
||||
virtual already_AddRefed<ColorLayer> CreateColorLayer();
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
|
||||
|
||||
virtual TemporaryRef<DrawTarget>
|
||||
CreateOptimalDrawTarget(const IntSize &aSize,
|
||||
SurfaceFormat aSurfaceFormat);
|
||||
|
||||
virtual TemporaryRef<DrawTarget>
|
||||
CreateOptimalMaskDrawTarget(const IntSize &aSize);
|
||||
|
||||
virtual TemporaryRef<mozilla::gfx::DrawTarget>
|
||||
CreateDrawTarget(const gfx::IntSize &aSize,
|
||||
mozilla::gfx::SurfaceFormat aFormat);
|
||||
|
||||
virtual LayersBackend GetBackendType() { return LayersBackend::LAYERS_D3D10; }
|
||||
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Direct3D 10"); }
|
||||
|
||||
virtual const char* Name() const { return "D3D10"; }
|
||||
|
||||
// Public helpers
|
||||
|
||||
ID3D10Device1 *device() const { return mDevice; }
|
||||
|
||||
ID3D10Effect *effect() const { return mEffect; }
|
||||
IDXGISwapChain *SwapChain() const
|
||||
{
|
||||
return mSwapChain;
|
||||
}
|
||||
ReadbackManagerD3D10 *readbackManager();
|
||||
|
||||
void SetupInputAssembler();
|
||||
void SetViewport(const nsIntSize &aViewport);
|
||||
const nsIntSize &GetViewport() { return mViewport; }
|
||||
|
||||
/**
|
||||
* Return pointer to the Nv3DVUtils instance
|
||||
*/
|
||||
Nv3DVUtils *GetNv3DVUtils() { return mNv3DVUtils; }
|
||||
|
||||
static void ReportFailure(const nsACString &aMsg, HRESULT aCode);
|
||||
|
||||
private:
|
||||
void SetupPipeline();
|
||||
void UpdateRenderTarget();
|
||||
void VerifyBufferSize();
|
||||
void EnsureReadbackManager();
|
||||
|
||||
void Render(EndTransactionFlags aFlags);
|
||||
|
||||
nsRefPtr<ID3D10Device1> mDevice;
|
||||
|
||||
nsRefPtr<ID3D10Effect> mEffect;
|
||||
nsRefPtr<ID3D10InputLayout> mInputLayout;
|
||||
nsRefPtr<ID3D10Buffer> mVertexBuffer;
|
||||
nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> mRTView;
|
||||
|
||||
nsRefPtr<IDXGISwapChain> mSwapChain;
|
||||
|
||||
nsIWidget *mWidget;
|
||||
|
||||
bool mDisableSequenceForNextFrame;
|
||||
|
||||
CallbackInfo mCurrentCallbackInfo;
|
||||
|
||||
nsIntSize mViewport;
|
||||
|
||||
/* Nv3DVUtils instance */
|
||||
nsAutoPtr<Nv3DVUtils> mNv3DVUtils;
|
||||
|
||||
/*
|
||||
* Context target, nullptr when drawing directly to our swap chain.
|
||||
*/
|
||||
nsRefPtr<gfxContext> mTarget;
|
||||
|
||||
/*
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void PaintToTarget();
|
||||
};
|
||||
|
||||
/*
|
||||
* General information and tree management for OGL layers.
|
||||
*/
|
||||
class LayerD3D10
|
||||
{
|
||||
public:
|
||||
LayerD3D10(LayerManagerD3D10 *aManager);
|
||||
|
||||
virtual LayerD3D10 *GetFirstChildD3D10() { return nullptr; }
|
||||
|
||||
void SetFirstChild(LayerD3D10 *aParent);
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
/**
|
||||
* This will render a child layer to whatever render target is currently
|
||||
* active.
|
||||
*/
|
||||
virtual void RenderLayer() = 0;
|
||||
virtual void Validate() {}
|
||||
|
||||
ID3D10Device1 *device() const { return mD3DManager->device(); }
|
||||
ID3D10Effect *effect() const { return mD3DManager->effect(); }
|
||||
|
||||
/* Called by the layer manager when it's destroyed */
|
||||
virtual void LayerManagerDestroyed() {}
|
||||
|
||||
/**
|
||||
* Return pointer to the Nv3DVUtils instance. Calls equivalent method in LayerManager.
|
||||
*/
|
||||
Nv3DVUtils *GetNv3DVUtils() { return mD3DManager->GetNv3DVUtils(); }
|
||||
|
||||
/*
|
||||
* Returns a shader resource view of a texture containing the contents of this
|
||||
* layer. Will try to return an existing texture if possible, or a temporary
|
||||
* one if not. It is the callee's responsibility to release the shader
|
||||
* resource view. Will return null if a texture could not be constructed.
|
||||
* The texture will not be transformed, i.e., it will be in the same coord
|
||||
* space as this.
|
||||
* Any layer that can be used as a mask layer should override this method.
|
||||
* If aSize is non-null, it will contain the size of the texture.
|
||||
*/
|
||||
virtual already_AddRefed<ID3D10ShaderResourceView> GetAsTexture(gfx::IntSize* aSize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetEffectTransformAndOpacity()
|
||||
{
|
||||
Layer* layer = GetLayer();
|
||||
const gfx::Matrix4x4& transform = layer->GetEffectiveTransform();
|
||||
void* raw = &const_cast<gfx::Matrix4x4&>(transform)._11;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64);
|
||||
effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(layer->GetEffectiveOpacity());
|
||||
}
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Finds a texture for this layer's mask layer (if it has one) and sets it
|
||||
* as an input to the shaders.
|
||||
* Returns SHADER_MASK if a texture is loaded, SHADER_NO_MASK if there was no
|
||||
* mask layer, or a texture for the mask layer could not be loaded.
|
||||
*/
|
||||
uint8_t LoadMaskTexture();
|
||||
|
||||
/**
|
||||
* Select a shader technique using a combination of the following flags.
|
||||
* Not all combinations of flags are supported, and might cause an error,
|
||||
* check the fx file to see which shaders exist. In particular, aFlags should
|
||||
* include any combination of the 0x20 bit = 0 flags OR one of the 0x20 bit = 1
|
||||
* flags. Mask flags can be used in either case.
|
||||
*/
|
||||
ID3D10EffectTechnique* SelectShader(uint8_t aFlags);
|
||||
const static uint8_t SHADER_NO_MASK = 0;
|
||||
const static uint8_t SHADER_MASK = 0x1;
|
||||
const static uint8_t SHADER_MASK_3D = 0x2;
|
||||
// 0x20 bit = 0
|
||||
const static uint8_t SHADER_RGB = 0;
|
||||
const static uint8_t SHADER_RGBA = 0x4;
|
||||
const static uint8_t SHADER_NON_PREMUL = 0;
|
||||
const static uint8_t SHADER_PREMUL = 0x8;
|
||||
const static uint8_t SHADER_LINEAR = 0;
|
||||
const static uint8_t SHADER_POINT = 0x10;
|
||||
// 0x20 bit = 1
|
||||
const static uint8_t SHADER_YCBCR = 0x20;
|
||||
const static uint8_t SHADER_COMPONENT_ALPHA = 0x24;
|
||||
const static uint8_t SHADER_SOLID = 0x28;
|
||||
|
||||
LayerManagerD3D10 *mD3DManager;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
#endif /* GFX_LAYERMANAGERD3D9_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,478 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "mozilla/layers/PLayerTransaction.h"
|
||||
|
||||
// This must occur *after* layers/PLayerTransaction.h to avoid
|
||||
// typedefs conflicts.
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "PaintedLayerD3D10.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
#include "gfxD2DSurface.h"
|
||||
#endif
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
#include "gfxTeeSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "ReadbackLayer.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
PaintedLayerD3D10::PaintedLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: PaintedLayer(aManager, nullptr)
|
||||
, LayerD3D10(aManager)
|
||||
, mCurrentSurfaceMode(SurfaceMode::SURFACE_OPAQUE)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
PaintedLayerD3D10::~PaintedLayerD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mInvalidRegion.Or(mInvalidRegion, aRegion);
|
||||
mInvalidRegion.SimplifyOutward(20);
|
||||
mValidRegion.Sub(mValidRegion, mInvalidRegion);
|
||||
}
|
||||
|
||||
void PaintedLayerD3D10::CopyRegion(ID3D10Texture2D* aSrc, const nsIntPoint &aSrcOffset,
|
||||
ID3D10Texture2D* aDest, const nsIntPoint &aDestOffset,
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion)
|
||||
{
|
||||
nsIntRegion retainedRegion;
|
||||
nsIntRegionRectIterator iter(aCopyRegion);
|
||||
const nsIntRect *r;
|
||||
while ((r = iter.Next())) {
|
||||
// Calculate the retained rectangle's position on the old and the new
|
||||
// surface.
|
||||
D3D10_BOX box;
|
||||
box.left = r->x - aSrcOffset.x;
|
||||
box.top = r->y - aSrcOffset.y;
|
||||
box.right = box.left + r->width;
|
||||
box.bottom = box.top + r->height;
|
||||
box.back = 1;
|
||||
box.front = 0;
|
||||
|
||||
device()->CopySubresourceRegion(aDest, 0,
|
||||
r->x - aDestOffset.x,
|
||||
r->y - aDestOffset.y,
|
||||
0,
|
||||
aSrc, 0,
|
||||
&box);
|
||||
|
||||
retainedRegion.Or(retainedRegion, *r);
|
||||
}
|
||||
|
||||
// Areas which were valid and were retained are still valid
|
||||
aValidRegion->And(*aValidRegion, retainedRegion);
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::RenderLayer()
|
||||
{
|
||||
if (!mTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetEffectTransformAndOpacity();
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
switch (mCurrentSurfaceMode) {
|
||||
case SurfaceMode::SURFACE_COMPONENT_ALPHA:
|
||||
technique = SelectShader(SHADER_COMPONENT_ALPHA | LoadMaskTexture());
|
||||
break;
|
||||
case SurfaceMode::SURFACE_OPAQUE:
|
||||
technique = SelectShader(SHADER_RGB | SHADER_PREMUL | LoadMaskTexture());
|
||||
break;
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA:
|
||||
technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | LoadMaskTexture());
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown mode");
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegionRectIterator iter(mVisibleRegion);
|
||||
|
||||
const nsIntRect *iterRect;
|
||||
if (mSRView) {
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
|
||||
}
|
||||
if (mSRViewOnWhite) {
|
||||
effect()->GetVariableByName("tRGBWhite")->AsShaderResource()->SetResource(mSRViewOnWhite);
|
||||
}
|
||||
|
||||
while ((iterRect = iter.Next())) {
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)iterRect->x,
|
||||
(float)iterRect->y,
|
||||
(float)iterRect->width,
|
||||
(float)iterRect->height)
|
||||
);
|
||||
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)(iterRect->x - mTextureRect.x) / (float)mTextureRect.width,
|
||||
(float)(iterRect->y - mTextureRect.y) / (float)mTextureRect.height,
|
||||
(float)iterRect->width / (float)mTextureRect.width,
|
||||
(float)iterRect->height / (float)mTextureRect.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
// Set back to default.
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
||||
{
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FAILED(gfxWindowsPlatform::GetPlatform()->GetD3D10Device()->GetDeviceRemovedReason())) {
|
||||
// Device removed, this will be discovered on the next rendering pass.
|
||||
// Do no validate.
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect newTextureRect = mVisibleRegion.GetBounds();
|
||||
|
||||
SurfaceMode mode = GetSurfaceMode();
|
||||
if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA &&
|
||||
(!mParent || !mParent->SupportsComponentAlphaChildren())) {
|
||||
mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
// If we have a transform that requires resampling of our texture, then
|
||||
// we need to make sure we don't sample pixels that haven't been drawn.
|
||||
// We clamp sample coordinates to the texture rect, but when the visible region
|
||||
// doesn't fill the entire texture rect we need to make sure we draw all the
|
||||
// pixels in the texture rect anyway in case they get sampled.
|
||||
nsIntRegion neededRegion = mVisibleRegion;
|
||||
if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
|
||||
neededRegion.GetNumRects() > 1) {
|
||||
if (MayResample()) {
|
||||
neededRegion = newTextureRect;
|
||||
if (mode == SurfaceMode::SURFACE_OPAQUE) {
|
||||
// We're going to paint outside the visible region, but layout hasn't
|
||||
// promised that it will paint opaquely there, so we'll have to
|
||||
// treat this layer as transparent.
|
||||
mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
mCurrentSurfaceMode = mode;
|
||||
|
||||
VerifyContentType(mode);
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
nsIntRegion readbackRegion;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetPaintedLayerUpdates(this, &readbackUpdates, &readbackRegion);
|
||||
}
|
||||
|
||||
if (mTexture) {
|
||||
if (!mTextureRect.IsEqualInterior(newTextureRect)) {
|
||||
nsRefPtr<ID3D10Texture2D> oldTexture = mTexture;
|
||||
mTexture = nullptr;
|
||||
nsRefPtr<ID3D10Texture2D> oldTextureOnWhite = mTextureOnWhite;
|
||||
mTextureOnWhite = nullptr;
|
||||
|
||||
nsIntRegion retainRegion = mTextureRect;
|
||||
// Old visible region will become the region that is covered by both the
|
||||
// old and the new visible region.
|
||||
retainRegion.And(retainRegion, mVisibleRegion);
|
||||
// No point in retaining parts which were not valid.
|
||||
retainRegion.And(retainRegion, mValidRegion);
|
||||
|
||||
CreateNewTextures(gfx::IntSize(newTextureRect.width, newTextureRect.height), mode);
|
||||
|
||||
nsIntRect largeRect = retainRegion.GetLargestRectangle();
|
||||
|
||||
// If we had no hardware texture before, or have no retained area larger than
|
||||
// the retention threshold, we're not retaining and are done here.
|
||||
// If our texture creation failed this can mean a device reset is pending
|
||||
// and we should silently ignore the failure. In the future when device
|
||||
// failures are properly handled we should test for the type of failure
|
||||
// and gracefully handle different failures. See bug 569081.
|
||||
if (!oldTexture || !mTexture) {
|
||||
mValidRegion.SetEmpty();
|
||||
} else {
|
||||
CopyRegion(oldTexture, mTextureRect.TopLeft(),
|
||||
mTexture, newTextureRect.TopLeft(),
|
||||
retainRegion, &mValidRegion);
|
||||
if (oldTextureOnWhite) {
|
||||
CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(),
|
||||
mTextureOnWhite, newTextureRect.TopLeft(),
|
||||
retainRegion, &mValidRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mTextureRect = newTextureRect;
|
||||
|
||||
if (!mTexture || (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA && !mTextureOnWhite)) {
|
||||
CreateNewTextures(gfx::IntSize(newTextureRect.width, newTextureRect.height), mode);
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
|
||||
nsIntRegion drawRegion;
|
||||
drawRegion.Sub(neededRegion, mValidRegion);
|
||||
|
||||
if (!drawRegion.IsEmpty()) {
|
||||
LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
if (!cbInfo.Callback) {
|
||||
NS_ERROR("D3D10 should never need to update PaintedLayers in an empty transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
DrawRegion(drawRegion, mode);
|
||||
|
||||
if (readbackUpdates.Length() > 0) {
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
newTextureRect.width, newTextureRect.height,
|
||||
1, 1, 0, D3D10_USAGE_STAGING,
|
||||
D3D10_CPU_ACCESS_READ);
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> readbackTexture;
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(readbackTexture));
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("PaintedLayerD3D10::Validate(): Failed to create texture"),
|
||||
hr);
|
||||
return;
|
||||
}
|
||||
|
||||
device()->CopyResource(readbackTexture, mTexture);
|
||||
|
||||
for (uint32_t i = 0; i < readbackUpdates.Length(); i++) {
|
||||
mD3DManager->readbackManager()->PostTask(readbackTexture,
|
||||
&readbackUpdates[i],
|
||||
gfxPoint(newTextureRect.x, newTextureRect.y));
|
||||
}
|
||||
}
|
||||
|
||||
mValidRegion = neededRegion;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::LayerManagerDestroyed()
|
||||
{
|
||||
mD3DManager = nullptr;
|
||||
}
|
||||
|
||||
Layer*
|
||||
PaintedLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::VerifyContentType(SurfaceMode aMode)
|
||||
{
|
||||
if (mDrawTarget) {
|
||||
SurfaceFormat format = aMode != SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA ?
|
||||
SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
|
||||
|
||||
if (format != mDrawTarget->GetFormat()) {
|
||||
mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, format);
|
||||
|
||||
if (!mDrawTarget) {
|
||||
gfxWarning() << "Failed to create drawtarget for PaintedLayerD3D10.";
|
||||
return;
|
||||
}
|
||||
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
if (aMode != SurfaceMode::SURFACE_COMPONENT_ALPHA && mTextureOnWhite) {
|
||||
// If we've transitioned away from component alpha, we can delete those resources.
|
||||
mSRViewOnWhite = nullptr;
|
||||
mTextureOnWhite = nullptr;
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::FillTexturesBlackWhite(const nsIntRegion& aRegion, const nsIntPoint& aOffset)
|
||||
{
|
||||
if (mTexture && mTextureOnWhite) {
|
||||
// It would be more optimal to draw the actual geometry, but more code
|
||||
// and probably not worth the win here as this will often be a single
|
||||
// rect.
|
||||
nsRefPtr<ID3D10RenderTargetView> oldRT;
|
||||
device()->OMGetRenderTargets(1, getter_AddRefs(oldRT), nullptr);
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> viewBlack;
|
||||
nsRefPtr<ID3D10RenderTargetView> viewWhite;
|
||||
device()->CreateRenderTargetView(mTexture, nullptr, getter_AddRefs(viewBlack));
|
||||
device()->CreateRenderTargetView(mTextureOnWhite, nullptr, getter_AddRefs(viewWhite));
|
||||
|
||||
D3D10_RECT oldScissor;
|
||||
UINT numRects = 1;
|
||||
device()->RSGetScissorRects(&numRects, &oldScissor);
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTexture->GetDesc(&desc);
|
||||
|
||||
D3D10_RECT scissor = { 0, 0, desc.Width, desc.Height };
|
||||
device()->RSSetScissorRects(1, &scissor);
|
||||
|
||||
mD3DManager->SetupInputAssembler();
|
||||
nsIntSize oldVP = mD3DManager->GetViewport();
|
||||
|
||||
mD3DManager->SetViewport(nsIntSize(desc.Width, desc.Height));
|
||||
|
||||
ID3D10RenderTargetView *views[2] = { viewBlack, viewWhite };
|
||||
device()->OMSetRenderTargets(2, views, nullptr);
|
||||
|
||||
gfx3DMatrix transform;
|
||||
transform.Translate(Point3D(-aOffset.x, -aOffset.y, 0));
|
||||
void* raw = &const_cast<gfx3DMatrix&>(transform)._11;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64);
|
||||
|
||||
ID3D10EffectTechnique *technique =
|
||||
effect()->GetTechniqueByName("PrepareAlphaExtractionTextures");
|
||||
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)iterRect->x,
|
||||
(float)iterRect->y,
|
||||
(float)iterRect->width,
|
||||
(float)iterRect->height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
views[0] = oldRT;
|
||||
device()->OMSetRenderTargets(1, views, nullptr);
|
||||
mD3DManager->SetViewport(oldVP);
|
||||
device()->RSSetScissorRects(1, &oldScissor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
|
||||
{
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
if (!mDrawTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRegion.SimplifyOutwardByArea(100 * 100);
|
||||
|
||||
if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
||||
FillTexturesBlackWhite(aRegion, visibleRect.TopLeft());
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(mDrawTarget);
|
||||
|
||||
context->SetMatrix(
|
||||
context->CurrentMatrix().Translate(-visibleRect.x, -visibleRect.y));
|
||||
if (aMode == SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA) {
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
|
||||
}
|
||||
}
|
||||
|
||||
mDrawTarget->SetPermitSubpixelAA(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
|
||||
|
||||
LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, DrawRegionClip::DRAW, nsIntRegion(), cbInfo.CallbackData);
|
||||
}
|
||||
|
||||
void
|
||||
PaintedLayerD3D10::CreateNewTextures(const gfx::IntSize &aSize, SurfaceMode aMode)
|
||||
{
|
||||
if (aSize.width == 0 || aSize.height == 0) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
HRESULT hr;
|
||||
|
||||
if (!mTexture) {
|
||||
hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for PaintedLayerD3D10!");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create shader resource view for PaintedLayerD3D10.");
|
||||
}
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
}
|
||||
|
||||
if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA && !mTextureOnWhite) {
|
||||
hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTextureOnWhite));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for PaintedLayerD3D10!");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = device()->CreateShaderResourceView(mTextureOnWhite, nullptr, getter_AddRefs(mSRViewOnWhite));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create shader resource view for PaintedLayerD3D10.");
|
||||
}
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
}
|
||||
|
||||
if (!mDrawTarget) {
|
||||
if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
|
||||
mDrawTarget = Factory::CreateDualDrawTargetForD3D10Textures(mTexture, mTextureOnWhite, SurfaceFormat::B8G8R8X8);
|
||||
} else {
|
||||
mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, aMode != SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA ?
|
||||
SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8);
|
||||
}
|
||||
|
||||
if (!mDrawTarget) {
|
||||
gfxWarning() << "Failed to create DrawTarget for PaintedLayerD3D10.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
@ -1,73 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_PAINTEDLAYERD3D10_H
|
||||
#define GFX_PAINTEDLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class PaintedLayerD3D10 : public PaintedLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
PaintedLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
virtual ~PaintedLayerD3D10();
|
||||
|
||||
void Validate(ReadbackProcessor *aReadback);
|
||||
|
||||
/* PaintedLayer implementation */
|
||||
void InvalidateRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer();
|
||||
virtual void Validate() { Validate(nullptr); }
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
private:
|
||||
/* Texture with our surface data */
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
|
||||
/* Shader resource view for our texture */
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
|
||||
/* Texture for render-on-whitew when doing component alpha */
|
||||
nsRefPtr<ID3D10Texture2D> mTextureOnWhite;
|
||||
|
||||
/* Shader resource view for our render-on-white texture */
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRViewOnWhite;
|
||||
|
||||
/* Area of layer currently stored in texture(s) */
|
||||
nsIntRect mTextureRect;
|
||||
|
||||
/* Last surface mode set in Validate() */
|
||||
SurfaceMode mCurrentSurfaceMode;
|
||||
|
||||
/* Checks if our D2D surface has the right content type */
|
||||
void VerifyContentType(SurfaceMode aMode);
|
||||
|
||||
mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTextures(const gfx::IntSize &aSize, SurfaceMode aMode);
|
||||
|
||||
// Fill textures with opaque black and white in the specified region.
|
||||
void FillTexturesBlackWhite(const nsIntRegion& aRegion, const nsIntPoint& aOffset);
|
||||
|
||||
/* Copy a texture region */
|
||||
void CopyRegion(ID3D10Texture2D* aSrc, const nsIntPoint &aSrcOffset,
|
||||
ID3D10Texture2D* aDest, const nsIntPoint &aDestOffset,
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_PAINTEDLAYERD3D10_H */
|
@ -1,33 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef GFX_READBACKLAYERD3D10_H
|
||||
#define GFX_READBACKLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ReadbackLayerD3D10 :
|
||||
public ReadbackLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ReadbackLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ReadbackLayer(aManager, nullptr),
|
||||
LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer() {}
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_READBACKLAYERD3D10_H */
|
@ -1,225 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "ReadbackManagerD3D10.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// Structure that contains the information required to execute a readback task,
|
||||
// the only member accessed off the main thread here is mReadbackTexture. Since
|
||||
// mLayer may be released only on the main thread this object should always be
|
||||
// destroyed on the main thread!
|
||||
struct ReadbackTask {
|
||||
// The texture that we copied the contents of the paintedlayer to.
|
||||
nsRefPtr<ID3D10Texture2D> mReadbackTexture;
|
||||
// This exists purely to keep the ReadbackLayer alive for the lifetime of
|
||||
// mUpdate. Note that this addref and release should occur -solely- on the
|
||||
// main thread.
|
||||
nsRefPtr<ReadbackLayer> mLayer;
|
||||
ReadbackProcessor::Update mUpdate;
|
||||
// The origin in PaintedLayer coordinates of mReadbackTexture.
|
||||
gfxPoint mOrigin;
|
||||
// mLayer->GetBackgroundOffset() when the task is created. We have
|
||||
// to save this in the ReadbackTask because it might change before
|
||||
// the update is delivered to the readback sink.
|
||||
nsIntPoint mBackgroundOffset;
|
||||
};
|
||||
|
||||
// This class is created and dispatched from the Readback thread but it must be
|
||||
// destroyed by the main thread.
|
||||
class ReadbackResultWriter MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
~ReadbackResultWriter() {}
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
public:
|
||||
ReadbackResultWriter(ReadbackTask *aTask) : mTask(aTask) {}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
ReadbackProcessor::Update *update = &mTask->mUpdate;
|
||||
|
||||
if (!update->mLayer->GetSink()) {
|
||||
// This can happen when a plugin is destroyed.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIntPoint offset = mTask->mBackgroundOffset;
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTask->mReadbackTexture->GetDesc(&desc);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
// We know this map will immediately succeed, as we've already mapped this
|
||||
// copied data on our task thread.
|
||||
HRESULT hr = mTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// If this fails we're never going to get our PaintedLayer content.
|
||||
update->mLayer->GetSink()->SetUnknown(update->mSequenceCounter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> sourceSurface =
|
||||
new gfxImageSurface((unsigned char*)mappedTex.pData,
|
||||
gfxIntSize(desc.Width, desc.Height),
|
||||
mappedTex.RowPitch,
|
||||
gfxImageFormat::RGB24);
|
||||
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update->mLayer->GetSink()->BeginUpdate(update->mUpdateRect + offset,
|
||||
update->mSequenceCounter);
|
||||
|
||||
if (ctx) {
|
||||
ctx->SetMatrix(
|
||||
ctx->CurrentMatrix().Translate(offset.x, offset.y));
|
||||
ctx->SetSource(sourceSurface, gfxPoint(mTask->mOrigin.x,
|
||||
mTask->mOrigin.y));
|
||||
ctx->Paint();
|
||||
|
||||
update->mLayer->GetSink()->EndUpdate(ctx, update->mUpdateRect + offset);
|
||||
}
|
||||
|
||||
mTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<ReadbackTask> mTask;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ReadbackResultWriter, nsIRunnable)
|
||||
|
||||
DWORD WINAPI StartTaskThread(void *aManager)
|
||||
{
|
||||
static_cast<ReadbackManagerD3D10*>(aManager)->ProcessTasks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10::ReadbackManagerD3D10()
|
||||
: mRefCnt(0)
|
||||
{
|
||||
::InitializeCriticalSection(&mTaskMutex);
|
||||
mShutdownEvent = ::CreateEventA(nullptr, FALSE, FALSE, nullptr);
|
||||
mTaskSemaphore = ::CreateSemaphoreA(nullptr, 0, 1000000, nullptr);
|
||||
mTaskThread = ::CreateThread(nullptr, 0, StartTaskThread, this, 0, 0);
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10::~ReadbackManagerD3D10()
|
||||
{
|
||||
::SetEvent(mShutdownEvent);
|
||||
|
||||
// This shouldn't take longer than 5 seconds, if it does we're going to choose
|
||||
// to leak the thread and its synchronisation in favor of crashing or freezing
|
||||
DWORD result = ::WaitForSingleObject(mTaskThread, 5000);
|
||||
if (result != WAIT_TIMEOUT) {
|
||||
::DeleteCriticalSection(&mTaskMutex);
|
||||
::CloseHandle(mShutdownEvent);
|
||||
::CloseHandle(mTaskSemaphore);
|
||||
::CloseHandle(mTaskThread);
|
||||
} else {
|
||||
NS_RUNTIMEABORT("ReadbackManager: Task thread did not shutdown in 5 seconds.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D10::PostTask(ID3D10Texture2D *aTexture, void *aUpdate, const gfxPoint &aOrigin)
|
||||
{
|
||||
ReadbackTask *task = new ReadbackTask;
|
||||
task->mReadbackTexture = aTexture;
|
||||
task->mUpdate = *static_cast<ReadbackProcessor::Update*>(aUpdate);
|
||||
task->mOrigin = aOrigin;
|
||||
task->mLayer = task->mUpdate.mLayer;
|
||||
task->mBackgroundOffset = task->mLayer->GetBackgroundLayerOffset();
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
mPendingReadbackTasks.AppendElement(task);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
::ReleaseSemaphore(mTaskSemaphore, 1, nullptr);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ReadbackManagerD3D10::QueryInterface(REFIID riid, void **ppvObject)
|
||||
{
|
||||
if (!ppvObject) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (riid == IID_IUnknown) {
|
||||
*ppvObject = this;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ReadbackManagerD3D10::AddRef()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"ReadbackManagerD3D10 should only be refcounted on main thread.");
|
||||
return ++mRefCnt;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ReadbackManagerD3D10::Release()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"ReadbackManagerD3D10 should only be refcounted on main thread.");
|
||||
ULONG newRefCnt = --mRefCnt;
|
||||
if (!newRefCnt) {
|
||||
mRefCnt++;
|
||||
delete this;
|
||||
}
|
||||
return newRefCnt;
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D10::ProcessTasks()
|
||||
{
|
||||
HANDLE handles[] = { mTaskSemaphore, mShutdownEvent };
|
||||
|
||||
while (true) {
|
||||
DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (result != WAIT_OBJECT_0) {
|
||||
return;
|
||||
}
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
if (mPendingReadbackTasks.Length() == 0) {
|
||||
NS_RUNTIMEABORT("Trying to read from an empty array, bad bad bad");
|
||||
}
|
||||
ReadbackTask *nextReadbackTask = mPendingReadbackTasks[0].forget();
|
||||
mPendingReadbackTasks.RemoveElementAt(0);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
// We want to block here until the texture contents are available, the
|
||||
// easiest thing is to simply map and unmap.
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
nextReadbackTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
nextReadbackTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
// We can only send the update to the sink on the main thread, so post an
|
||||
// event there to do so. Ownership of the task is passed from
|
||||
// mPendingReadbackTasks to ReadbackResultWriter here.
|
||||
nsCOMPtr<nsIThread> thread = do_GetMainThread();
|
||||
thread->Dispatch(new ReadbackResultWriter(nextReadbackTask),
|
||||
nsIEventTarget::DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user