зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound on a CLOSED TREE
This commit is contained in:
Коммит
348b931e1c
5
CLOBBER
5
CLOBBER
|
@ -22,7 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Updating CLOBBER for Bug 1084342
|
||||
|
||||
There are some refactored files in in dom/bluetooth. Updating CLOBBER to not
|
||||
leave artifacts from older builds.
|
||||
Backing out bug 1087560 needs a CLOBBER
|
||||
|
|
|
@ -43,7 +43,7 @@ function runNext() {
|
|||
ok(false, 'unexpected success, permission request should be denied');
|
||||
runNext();
|
||||
}, function failure(err) {
|
||||
is(err.toLowerCase(), 'permission denied', 'expected permission denied');
|
||||
is(err.name, 'PermissionDeniedError', 'expected permission denied');
|
||||
runNext();
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -524,6 +524,20 @@ Sanitizer.prototype = {
|
|||
let features = "chrome,all,dialog=no," + this.privateStateForNewWindow;
|
||||
let newWindow = existingWindow.openDialog("chrome://browser/content/", "_blank",
|
||||
features, defaultArgs);
|
||||
#ifdef XP_MACOSX
|
||||
function onFullScreen(e) {
|
||||
newWindow.removeEventListener("fullscreen", onFullScreen);
|
||||
let docEl = newWindow.document.documentElement;
|
||||
let sizemode = docEl.getAttribute("sizemode");
|
||||
if (!newWindow.fullScreen && sizemode == "fullscreen") {
|
||||
docEl.setAttribute("sizemode", "normal");
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
newWindow.addEventListener("fullscreen", onFullScreen);
|
||||
#endif
|
||||
|
||||
// Window creation and destruction is asynchronous. We need to wait
|
||||
// until all existing windows are fully closed, and the new window is
|
||||
|
@ -537,6 +551,9 @@ Sanitizer.prototype = {
|
|||
return;
|
||||
|
||||
Services.obs.removeObserver(onWindowOpened, "browser-delayed-startup-finished");
|
||||
#ifdef XP_MACOSX
|
||||
newWindow.removeEventListener("fullscreen", onFullScreen);
|
||||
#endif
|
||||
newWindowOpened = true;
|
||||
// If we're the last thing to happen, invoke callback.
|
||||
if (numWindowsClosing == 0)
|
||||
|
|
|
@ -223,6 +223,8 @@ function checkNotSharing() {
|
|||
assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
const permissionError = "error: PermissionDeniedError: The user did not grant permission for the operation.";
|
||||
|
||||
let gTests = [
|
||||
|
||||
{
|
||||
|
@ -381,7 +383,7 @@ let gTests = [
|
|||
enableDevice("Camera", false);
|
||||
enableDevice("Microphone", false);
|
||||
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
});
|
||||
|
||||
|
@ -405,7 +407,7 @@ let gTests = [
|
|||
expectObserverCalled("getUserMedia:request");
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
activateSecondaryAction(kActionDeny);
|
||||
});
|
||||
|
||||
|
@ -482,7 +484,7 @@ let gTests = [
|
|||
enableDevice("Camera", aAllowVideo || aNever);
|
||||
|
||||
let expectedMessage =
|
||||
(aAllowVideo || aAllowAudio) ? "ok" : "error: PERMISSION_DENIED";
|
||||
(aAllowVideo || aAllowAudio) ? "ok" : permissionError;
|
||||
yield promiseMessage(expectedMessage, () => {
|
||||
activateSecondaryAction(aNever ? kActionNever : kActionAlways);
|
||||
});
|
||||
|
@ -587,14 +589,14 @@ let gTests = [
|
|||
expectObserverCalled("getUserMedia:request");
|
||||
|
||||
// Deny the request to cleanup...
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
activateSecondaryAction(kActionDeny);
|
||||
});
|
||||
expectObserverCalled("getUserMedia:response:deny");
|
||||
expectObserverCalled("recording-window-ended");
|
||||
}
|
||||
else {
|
||||
let expectedMessage = aExpectStream ? "ok" : "error: PERMISSION_DENIED";
|
||||
let expectedMessage = aExpectStream ? "ok" : permissionError;
|
||||
yield promiseMessage(expectedMessage, gum);
|
||||
|
||||
if (expectedMessage == "ok") {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DEFAULT]
|
||||
skip-if = buildapp == "mulet" || e10s
|
||||
skip-if = buildapp == "mulet"
|
||||
support-files =
|
||||
head.js
|
||||
support/test_967000_charEncoding_page.html
|
||||
|
@ -34,6 +34,7 @@ skip-if = os == "mac"
|
|||
skip-if = os == "linux"
|
||||
|
||||
[browser_901207_searchbar_in_panel.js]
|
||||
skip-if = e10s # bug 1090656
|
||||
[browser_913972_currentset_overflow.js]
|
||||
skip-if = os == "linux"
|
||||
|
||||
|
@ -54,7 +55,6 @@ skip-if = os == "mac"
|
|||
skip-if = os == "linux"
|
||||
|
||||
[browser_934951_zoom_in_toolbar.js]
|
||||
skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
|
||||
[browser_938980_navbar_collapsed.js]
|
||||
[browser_938995_indefaultstate_nonremovable.js]
|
||||
[browser_940013_registerToolbarNode_calls_registerArea.js]
|
||||
|
@ -83,7 +83,7 @@ skip-if = os == "linux" # Intermittent failures
|
|||
[browser_947914_button_paste.js]
|
||||
skip-if = os == "linux" # Intermittent failures
|
||||
[browser_947914_button_print.js]
|
||||
skip-if = os == "linux" # Intermittent failures
|
||||
skip-if = os == "linux" || (os == "win" && e10s) # Intermittent failures on Linux, e10s issues on Windows (bug 1088714)
|
||||
[browser_947914_button_savePage.js]
|
||||
skip-if = os == "linux" # Intermittent failures
|
||||
[browser_947914_button_zoomIn.js]
|
||||
|
@ -100,11 +100,9 @@ skip-if = os == "linux" # Intermittent failures
|
|||
[browser_962884_opt_in_disable_hyphens.js]
|
||||
[browser_963639_customizing_attribute_non_customizable_toolbar.js]
|
||||
[browser_967000_button_charEncoding.js]
|
||||
skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
|
||||
skip-if = e10s # Bug 1088710
|
||||
[browser_967000_button_feeds.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
|
||||
[browser_967000_button_sync.js]
|
||||
skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
|
||||
[browser_967000_button_tabView.js]
|
||||
[browser_968447_bookmarks_toolbar_items_in_panel.js]
|
||||
skip-if = os == "linux" # Intemittent failures - bug 979207
|
||||
|
@ -129,6 +127,7 @@ skip-if = os == "linux"
|
|||
skip-if = os == "linux"
|
||||
|
||||
[browser_985815_propagate_setToolbarVisibility.js]
|
||||
skip-if = e10s # bug 1090635
|
||||
[browser_981305_separator_insertion.js]
|
||||
[browser_988072_sidebar_events.js]
|
||||
[browser_989338_saved_placements_not_resaved.js]
|
||||
|
@ -138,6 +137,7 @@ skip-if = os == "linux"
|
|||
[browser_987185_syncButton.js]
|
||||
[browser_987492_window_api.js]
|
||||
[browser_987640_charEncoding.js]
|
||||
skip-if = e10s # Bug 1088710
|
||||
[browser_992747_toggle_noncustomizable_toolbar.js]
|
||||
[browser_993322_widget_notoolbar.js]
|
||||
[browser_995164_registerArea_during_customize_mode.js]
|
||||
|
|
|
@ -26,6 +26,37 @@ loop.shared.mixins = (function() {
|
|||
rootObject = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* window.location mixin. Handles changes in the call url.
|
||||
* Forces a reload of the page to ensure proper state of the webapp
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
var UrlHashChangeMixin = {
|
||||
propTypes: {
|
||||
onUrlHashChange: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
rootObject.addEventListener("hashchange", this.onUrlHashChange, false);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
rootObject.removeEventListener("hashchange", this.onUrlHashChange, false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Document location mixin.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
var DocumentLocationMixin = {
|
||||
locationReload: function() {
|
||||
rootObject.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dropdown menu mixin.
|
||||
* @type {Object}
|
||||
|
@ -151,6 +182,8 @@ loop.shared.mixins = (function() {
|
|||
AudioMixin: AudioMixin,
|
||||
setRootObject: setRootObject,
|
||||
DropdownMenuMixin: DropdownMenuMixin,
|
||||
DocumentVisibilityMixin: DocumentVisibilityMixin
|
||||
DocumentVisibilityMixin: DocumentVisibilityMixin,
|
||||
DocumentLocationMixin: DocumentLocationMixin,
|
||||
UrlHashChangeMixin: UrlHashChangeMixin
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -859,6 +859,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
|||
* of the webapp page.
|
||||
*/
|
||||
var WebappRootView = React.createClass({displayName: 'WebappRootView',
|
||||
|
||||
mixins: [sharedMixins.UrlHashChangeMixin,
|
||||
sharedMixins.DocumentLocationMixin],
|
||||
|
||||
propTypes: {
|
||||
client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
|
||||
conversation: React.PropTypes.oneOfType([
|
||||
|
@ -879,6 +883,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
|||
};
|
||||
},
|
||||
|
||||
onUrlHashChange: function() {
|
||||
this.locationReload();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.unsupportedDevice) {
|
||||
return UnsupportedDeviceView(null);
|
||||
|
|
|
@ -859,6 +859,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
|||
* of the webapp page.
|
||||
*/
|
||||
var WebappRootView = React.createClass({
|
||||
|
||||
mixins: [sharedMixins.UrlHashChangeMixin,
|
||||
sharedMixins.DocumentLocationMixin],
|
||||
|
||||
propTypes: {
|
||||
client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
|
||||
conversation: React.PropTypes.oneOfType([
|
||||
|
@ -879,6 +883,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
|||
};
|
||||
},
|
||||
|
||||
onUrlHashChange: function() {
|
||||
this.locationReload();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.unsupportedDevice) {
|
||||
return <UnsupportedDeviceView />;
|
||||
|
|
|
@ -21,6 +21,75 @@ describe("loop.shared.mixins", function() {
|
|||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("loop.webapp.UrlHashChangeMixin", function() {
|
||||
function createTestComponent(onUrlHashChange) {
|
||||
var TestComp = React.createClass({
|
||||
mixins: [loop.shared.mixins.UrlHashChangeMixin],
|
||||
onUrlHashChange: onUrlHashChange || function(){},
|
||||
render: function() {
|
||||
return React.DOM.div();
|
||||
}
|
||||
});
|
||||
return new TestComp();
|
||||
}
|
||||
|
||||
it("should watch for hashchange event", function() {
|
||||
var addEventListener = sandbox.spy();
|
||||
sharedMixins.setRootObject({
|
||||
addEventListener: addEventListener
|
||||
});
|
||||
|
||||
TestUtils.renderIntoDocument(createTestComponent());
|
||||
|
||||
sinon.assert.calledOnce(addEventListener);
|
||||
sinon.assert.calledWith(addEventListener, "hashchange");
|
||||
});
|
||||
|
||||
it("should call onUrlHashChange when the url is updated", function() {
|
||||
sharedMixins.setRootObject({
|
||||
addEventListener: function(name, cb) {
|
||||
if (name === "hashchange") {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
});
|
||||
var onUrlHashChange = sandbox.stub();
|
||||
|
||||
TestUtils.renderIntoDocument(createTestComponent(onUrlHashChange));
|
||||
|
||||
sinon.assert.calledOnce(onUrlHashChange);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.webapp.DocumentLocationMixin", function() {
|
||||
var reloadStub, TestComp;
|
||||
|
||||
beforeEach(function() {
|
||||
reloadStub = sandbox.stub();
|
||||
|
||||
sharedMixins.setRootObject({
|
||||
location: {
|
||||
reload: reloadStub
|
||||
}
|
||||
});
|
||||
|
||||
TestComp = React.createClass({
|
||||
mixins: [loop.shared.mixins.DocumentLocationMixin],
|
||||
render: function() {
|
||||
return React.DOM.div();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should call window.location.reload", function() {
|
||||
var comp = TestUtils.renderIntoDocument(TestComp());
|
||||
|
||||
comp.locationReload();
|
||||
|
||||
sinon.assert.calledOnce(reloadStub);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.DocumentVisibilityMixin", function() {
|
||||
var comp, TestComp, onDocumentVisibleStub, onDocumentHiddenStub;
|
||||
|
||||
|
|
|
@ -514,7 +514,8 @@ describe("loop.webapp", function() {
|
|||
notifications: notifications,
|
||||
sdk: sdk,
|
||||
conversation: conversationModel,
|
||||
feedbackApiClient: feedbackApiClient
|
||||
feedbackApiClient: feedbackApiClient,
|
||||
onUrlHashChange: sandbox.stub()
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ function handleRequest(aSubject, aTopic, aData) {
|
|||
constraints, devices, secure);
|
||||
},
|
||||
function (error) {
|
||||
// bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND
|
||||
// bug 827146 -- In the future, the UI should catch NotFoundError
|
||||
// and allow the user to plug in a device, instead of immediately failing.
|
||||
denyRequest({callID: aSubject.callID}, error);
|
||||
},
|
||||
|
@ -108,7 +108,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec
|
|||
requestTypes.push("Microphone");
|
||||
|
||||
if (!requestTypes.length) {
|
||||
denyRequest({callID: aCallID}, "NO_DEVICES_FOUND");
|
||||
denyRequest({callID: aCallID}, "NotFoundError");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -838,7 +838,17 @@ this.UITour = {
|
|||
highlighter.parentElement.setAttribute("targetName", aTarget.targetName);
|
||||
highlighter.parentElement.hidden = false;
|
||||
|
||||
let targetRect = aTarget.node.getBoundingClientRect();
|
||||
let highlightAnchor;
|
||||
// If the target is in the overflow panel, just highlight the overflow button.
|
||||
if (aTarget.node.getAttribute("overflowedItem")) {
|
||||
let doc = aTarget.node.ownerDocument;
|
||||
let placement = CustomizableUI.getPlacementOfWidget(aTarget.widgetName || aTarget.node.id);
|
||||
let areaNode = doc.getElementById(placement.area);
|
||||
highlightAnchor = areaNode.overflowable._chevron;
|
||||
} else {
|
||||
highlightAnchor = aTarget.node;
|
||||
}
|
||||
let targetRect = highlightAnchor.getBoundingClientRect();
|
||||
let highlightHeight = targetRect.height;
|
||||
let highlightWidth = targetRect.width;
|
||||
let minDimension = Math.min(highlightHeight, highlightWidth);
|
||||
|
@ -874,7 +884,7 @@ this.UITour = {
|
|||
let offsetY = paddingLeftPx
|
||||
- (Math.max(0, highlightHeightWithMin - targetRect.height) / 2);
|
||||
this._addAnnotationPanelMutationObserver(highlighter.parentElement);
|
||||
highlighter.parentElement.openPopup(aTarget.node, "overlap", offsetX, offsetY);
|
||||
highlighter.parentElement.openPopup(highlightAnchor, "overlap", offsetX, offsetY);
|
||||
}
|
||||
|
||||
// Prevent showing a panel at an undefined position.
|
||||
|
|
|
@ -18,6 +18,23 @@
|
|||
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
|
||||
%define conditionalForwardWithUrlbarWidth 30
|
||||
|
||||
:root {
|
||||
--toolbarbutton-hover-background: hsla(0,0%,100%,.3) linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.2));
|
||||
--toolbarbutton-hover-boxshadow: 0 1px 0 hsla(0,0%,100%,.3) inset, 0 0 0 1px hsla(0,0%,100%,.2) inset, 0 1px 0 hsla(0,0%,0%,.03);
|
||||
--toolbarbutton-hover-bordercolor: rgb(154,154,154);
|
||||
|
||||
--toolbarbutton-active-boxshadow: 0 1px 1px hsla(0,0%,0%,.1) inset, 0 0 1px hsla(0,0%,0%,.3) inset;
|
||||
--toolbarbutton-active-bordercolor: rgb(154,154,154);
|
||||
--toolbarbutton-active-background: rgba(154,154,154,.5) linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));
|
||||
|
||||
--toolbarbutton-checkedhover-backgroundcolor: rgba(90%,90%,90%,.4);
|
||||
|
||||
--toolbarbutton-combined-boxshadow: 0 0 0 1px hsla(0,0%,100%,.2);
|
||||
--toolbarbutton-combined-backgroundimage: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 18px);
|
||||
|
||||
--verified-identity-box-backgroundcolor: #fff;
|
||||
}
|
||||
|
||||
#menubar-items {
|
||||
-moz-box-orient: vertical; /* for flex hack */
|
||||
}
|
||||
|
@ -590,12 +607,11 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):not([open]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-badge-container > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-icon {
|
||||
background-color: hsla(0,0%,100%,.3);
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.2));
|
||||
border: 1px solid rgb(154,154,154);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.2) inset,
|
||||
0 1px 0 hsla(0,0%,0%,.03);
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--toolbarbutton-hover-bordercolor);
|
||||
box-shadow: var(--toolbarbutton-hover-boxshadow);
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
|
@ -608,16 +624,16 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container > .toolbarbutton-icon,
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon {
|
||||
background-color: rgba(154,154,154,.5);
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));
|
||||
border: 1px solid rgb(154,154,154);
|
||||
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
|
||||
0 0 1px hsla(0,0%,0%,.3) inset;
|
||||
background: var(--toolbarbutton-active-background);
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--toolbarbutton-active-bordercolor);
|
||||
transition-duration: 10ms;
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[checked]:not(:active):hover > .toolbarbutton-icon {
|
||||
background-color: rgba(90%,90%,90%,.4);
|
||||
background-color: var(--toolbarbutton-checkedhover-backgroundcolor);
|
||||
transition: background-color 150ms;
|
||||
}
|
||||
|
||||
|
@ -633,12 +649,12 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
width: 1px;
|
||||
height: 18px;
|
||||
-moz-margin-end: -1px;
|
||||
background-image: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 18px);
|
||||
background-image: var(--toolbarbutton-combined-backgroundimage);
|
||||
background-clip: padding-box;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1px 18px;
|
||||
box-shadow: 0 0 0 1px hsla(0,0%,100%,.2);
|
||||
box-shadow: var(--toolbarbutton-combined-boxshadow);
|
||||
}
|
||||
|
||||
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
||||
|
@ -971,7 +987,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
}
|
||||
|
||||
#identity-box.verifiedIdentity:not(:-moz-lwtheme) {
|
||||
background-color: #fff;
|
||||
background-color: var(--verified-identity-box-backgroundcolor);
|
||||
}
|
||||
|
||||
#identity-box:-moz-focusring {
|
||||
|
|
|
@ -17,6 +17,28 @@
|
|||
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
|
||||
%define conditionalForwardWithUrlbarWidth 30
|
||||
|
||||
:root {
|
||||
--toolbarbutton-hover-background: hsla(210,4%,10%,.08);
|
||||
--toolbarbutton-hover-bordercolor: hsla(210,4%,10%,.1);
|
||||
--toolbarbutton-hover-boxshadow: none;
|
||||
|
||||
--toolbarbutton-active-background: hsla(210,4%,10%,.12);
|
||||
--toolbarbutton-active-bordercolor: hsla(210,4%,10%,.2) transparent transparent;
|
||||
--toolbarbutton-active-boxshadow: 0 1px 0 0 hsla(210,4%,10%,.1) inset;
|
||||
|
||||
--toolbarbutton-checkedhover-backgroundcolor: hsla(210,4%,10%,.12);
|
||||
|
||||
--toolbarbutton-combined-boxshadow: none;
|
||||
--toolbarbutton-combined-backgroundimage: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 16px);
|
||||
|
||||
--verified-identity-box-backgroundcolor: #FFF;
|
||||
|
||||
--urlbar-dropmarker-url: url("chrome://browser/skin/urlbar-history-dropmarker.png");
|
||||
--urlbar-dropmarker-region: rect(0px, 11px, 14px, 0px);
|
||||
--urlbar-dropmarker-hover-region: rect(0px, 22px, 14px, 11px);
|
||||
--urlbar-dropmarker-active-region: rect(0px, 33px, 14px, 22px);
|
||||
}
|
||||
|
||||
#menubar-items {
|
||||
-moz-box-orient: vertical; /* for flex hack */
|
||||
}
|
||||
|
@ -663,6 +685,27 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
|
|||
(-moz-os-version: windows-win7) {
|
||||
%endif
|
||||
/* < Win8 */
|
||||
:root {
|
||||
--toolbarbutton-hover-background: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||
--toolbarbutton-hover-bordercolor: hsla(210,54%,20%,.15) hsla(210,54%,20%,.2) hsla(210,54%,20%,.25);
|
||||
--toolbarbutton-hover-boxshadow: 0 1px hsla(0,0%,100%,.3) inset,
|
||||
0 1px hsla(210,54%,20%,.03),
|
||||
0 0 2px hsla(210,54%,20%,.1);
|
||||
|
||||
--toolbarbutton-active-background: hsla(210,54%,20%,.15) linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||
--toolbarbutton-active-bordercolor: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
|
||||
--toolbarbutton-active-boxshadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
|
||||
0 0 1px hsla(210,54%,20%,.2) inset,
|
||||
/* allows keyhole-forward-clip-path to be used for non-hover as well as hover: */
|
||||
0 1px 0 hsla(210,54%,20%,0),
|
||||
0 0 2px hsla(210,54%,20%,0);
|
||||
|
||||
--toolbarbutton-checkedhover-backgroundcolor: rgba(90%,90%,90%,.4);
|
||||
|
||||
--toolbarbutton-combined-backgroundimage: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 18px);
|
||||
--toolbarbutton-combined-boxshadow: 0 0 0 1px hsla(0,0%,100%,.2);
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-text,
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-badge-container,
|
||||
|
@ -732,7 +775,8 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
width: 1px;
|
||||
height: 16px;
|
||||
-moz-margin-end: -1px;
|
||||
background-image: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 16px);
|
||||
background-image: var(--toolbarbutton-combined-backgroundimage);
|
||||
box-shadow: var(--toolbarbutton-combined-boxshadow);
|
||||
background-clip: padding-box;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
|
@ -751,8 +795,9 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
#nav-bar .toolbarbutton-1:not([disabled=true]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-badge-container,
|
||||
@conditionalForwardWithUrlbar@ > #forward-button:not([open]):not(:active):not([disabled]):hover > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([buttonover]):not([open]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon {
|
||||
background-color: hsla(210,4%,10%,.08);
|
||||
border-color: hsla(210,4%,10%,.1);
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
border-color: var(--toolbarbutton-hover-bordercolor);
|
||||
box-shadow: var(--toolbarbutton-hover-boxshadow);
|
||||
}
|
||||
|
||||
%ifdef WINDOWS_AERO
|
||||
|
@ -762,17 +807,8 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
/* < Win8 */
|
||||
#nav-bar .toolbarbutton-1:not(:hover):not(:active):not([open]) > .toolbarbutton-menubutton-dropmarker::before,
|
||||
#nav-bar .toolbaritem-combined-buttons > .toolbarbutton-1:-moz-any(:not(:hover):not([open]),[disabled]) + .toolbarbutton-1:-moz-any(:not(:hover):not([open]),[disabled])::before {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
width: 1px;
|
||||
height: 18px;
|
||||
-moz-margin-end: -1px;
|
||||
background-image: linear-gradient(hsla(210,54%,20%,.2) 0, hsla(210,54%,20%,.2) 18px);
|
||||
background-clip: padding-box;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1px 18px;
|
||||
box-shadow: 0 0 0 1px hsla(0,0%,100%,.2);
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(ltr),
|
||||
|
@ -787,21 +823,6 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]) > .toolbarbutton-menubutton-button[open] + .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-text,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-badge-container,
|
||||
@conditionalForwardWithUrlbar@ > .toolbarbutton-1:-moz-any([disabled],:not([open]):not([disabled]):not(:active)) > .toolbarbutton-icon {
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||
background-color: transparent;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.2) hsla(210,54%,20%,.25);
|
||||
box-shadow: 0 1px hsla(0,0%,100%,.3) inset,
|
||||
0 1px hsla(210,54%,20%,.03),
|
||||
0 0 2px hsla(210,54%,20%,.1);
|
||||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):not([open]):not(:active):hover > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([buttonover]):not([open]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon,
|
||||
@conditionalForwardWithUrlbar@ > #forward-button:not([open]):not(:active):not([disabled]):hover > .toolbarbutton-icon {
|
||||
|
@ -819,9 +840,9 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-text,
|
||||
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container {
|
||||
background-color: hsla(210,4%,10%,.12);
|
||||
border-top-color: hsla(210,4%,10%,.2);
|
||||
box-shadow: 0 1px 0 0 hsla(210,4%,10%,.1) inset;
|
||||
background: var(--toolbarbutton-active-background);
|
||||
border-color: var(--toolbarbutton-active-bordercolor);
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||
transition-duration: 10ms;
|
||||
}
|
||||
|
||||
|
@ -835,14 +856,6 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
#nav-bar .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-text,
|
||||
#nav-bar .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container {
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||
background-color: hsla(210,54%,20%,.15);
|
||||
border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
|
||||
box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
|
||||
0 0 1px hsla(210,54%,20%,.2) inset,
|
||||
/* allows keyhole-forward-clip-path to be used for non-hover as well as hover: */
|
||||
0 1px 0 hsla(210,54%,20%,0),
|
||||
0 0 2px hsla(210,54%,20%,0);
|
||||
text-shadow: none;
|
||||
transition: none;
|
||||
}
|
||||
|
@ -852,7 +865,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
}
|
||||
|
||||
#nav-bar .toolbarbutton-1[checked]:not(:active):hover > .toolbarbutton-icon {
|
||||
background-color: rgba(90%,90%,90%,.4);
|
||||
background-color: var(--toolbarbutton-checkedhover-backgroundcolor);
|
||||
transition: background-color .4s;
|
||||
}
|
||||
%ifdef WINDOWS_AERO
|
||||
|
@ -1317,7 +1330,7 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
|||
}
|
||||
|
||||
#identity-box.verifiedIdentity:not(:-moz-lwtheme) {
|
||||
background-color: #fff;
|
||||
background-color: var(--verified-identity-box-backgroundcolor);
|
||||
}
|
||||
|
||||
#identity-box:-moz-focusring {
|
||||
|
@ -1338,19 +1351,19 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
|||
background-color: transparent;
|
||||
border: none;
|
||||
width: auto;
|
||||
list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker.png");
|
||||
-moz-image-region: rect(0px, 11px, 14px, 0px);
|
||||
list-style-image: var(--urlbar-dropmarker-url);
|
||||
-moz-image-region: var(--urlbar-dropmarker-region);
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
-moz-image-region: rect(0px, 22px, 14px, 11px);
|
||||
-moz-image-region: var(--urlbar-dropmarker-hover-region);
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover:active,
|
||||
.urlbar-history-dropmarker[open="true"] {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), transparent);
|
||||
-moz-image-region: rect(0px, 33px, 14px, 22px);
|
||||
-moz-image-region: var(--urlbar-dropmarker-active-region);
|
||||
}
|
||||
|
||||
/* page proxy icon */
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
|
||||
/* emulating chrome://browser/content/places/menu.xml#places-popup-arrow but without the arrow */
|
||||
box-shadow: 0 0 4px rgba(0,0,0,0.2);
|
||||
background: #FFF;
|
||||
border: 1px solid rgba(0,0,0,0.25);
|
||||
background: var(--panel-arrowcontent-background);
|
||||
border: var(--panel-arrowcontent-border);
|
||||
border-radius: 3.5px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
* 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/. */
|
||||
|
||||
.searchbar-dropmarker-image {
|
||||
--searchbar-dropmarker-url: url("chrome://browser/skin/searchbar-dropdown-arrow.png");
|
||||
}
|
||||
|
||||
.autocomplete-textbox-container {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
@ -38,7 +42,7 @@
|
|||
}
|
||||
|
||||
.searchbar-dropmarker-image {
|
||||
list-style-image: url("chrome://browser/skin/searchbar-dropdown-arrow.png");
|
||||
list-style-image: var(--searchbar-dropmarker-url);
|
||||
-moz-image-region: rect(0, 13px, 11px, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,6 @@ if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
|
|||
fi
|
||||
else
|
||||
STLPORT_CPPFLAGS="-isystem $_topsrcdir/build/stlport/stlport -isystem $_topsrcdir/build/stlport/overrides -isystem $android_ndk/sources/cxx-stl/system/include"
|
||||
STLPORT_LIBS="$_objdir/build/stlport/libstlport_static.a -static-libstdc++"
|
||||
fi
|
||||
fi
|
||||
CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
|
||||
|
|
|
@ -4,7 +4,13 @@
|
|||
# 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/.
|
||||
|
||||
Library('stlport_static')
|
||||
Library('stlport')
|
||||
# Keep the same name as the NDK-provided library, while using a shorter
|
||||
# name for the Library for convenience in moz.build.
|
||||
STATIC_LIBRARY_NAME = 'stlport_static'
|
||||
|
||||
if not CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
OS_LIBS += ['-static-libstdc++']
|
||||
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
|
|
|
@ -5,19 +5,31 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
@template
|
||||
def StdCppCompat():
|
||||
'''Template for libstdc++ compatibility for target binaries.'''
|
||||
def Binary():
|
||||
'''Generic template for target binaries. Meant to be used by other
|
||||
templates.'''
|
||||
|
||||
if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
|
||||
USE_LIBS += ['stdc++compat']
|
||||
|
||||
# Ideally, we'd support not adding this to the LIB_IS_C_ONLY case,
|
||||
# but that variable is actually only set in db/sqlite/src, which
|
||||
# doesn't build a shared library on the relevant platforms anyways.
|
||||
# Eventually, though, we should detect LIB_IS_C_ONLY based on the
|
||||
# associated SOURCES (and there might actually be places where we
|
||||
# haven't set it but should have).
|
||||
if CONFIG['STLPORT_LIBS']:
|
||||
OS_LIBS += [CONFIG['STLPORT_LIBS']]
|
||||
elif CONFIG['OS_TARGET'] == 'Android':
|
||||
USE_LIBS += ['stlport']
|
||||
|
||||
|
||||
@template
|
||||
def Program(name):
|
||||
'''Template for program executables.'''
|
||||
PROGRAM = name
|
||||
|
||||
StdCppCompat()
|
||||
Binary()
|
||||
|
||||
|
||||
@template
|
||||
|
@ -29,7 +41,7 @@ def SimplePrograms(names, ext='.cpp'):
|
|||
SIMPLE_PROGRAMS += names
|
||||
SOURCES += ['%s%s' % (name, ext) for name in names]
|
||||
|
||||
StdCppCompat()
|
||||
Binary()
|
||||
|
||||
|
||||
@template
|
||||
|
@ -41,7 +53,7 @@ def CppUnitTests(names, ext='.cpp'):
|
|||
CPP_UNIT_TESTS += names
|
||||
SOURCES += ['%s%s' % (name, ext) for name in names]
|
||||
|
||||
StdCppCompat()
|
||||
Binary()
|
||||
|
||||
|
||||
@template
|
||||
|
@ -57,7 +69,7 @@ def SharedLibrary(name):
|
|||
|
||||
FORCE_SHARED_LIB = True
|
||||
|
||||
StdCppCompat()
|
||||
Binary()
|
||||
|
||||
|
||||
@template
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!env perl
|
||||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use File::Spec::Unix;
|
||||
use strict;
|
||||
|
||||
print "Usage: $0 dest_path start_path\n" if ($#ARGV+1 != 2);
|
||||
my $finish = my_canonpath(shift);
|
||||
my $start = my_canonpath(shift);
|
||||
|
||||
my $res = File::Spec::Unix->abs2rel($finish, $start);
|
||||
|
||||
#print STDERR "abs2rel($finish,$start) = $res\n";
|
||||
print "$res\n";
|
||||
|
||||
sub my_canonpath($) {
|
||||
my ($file) = @_;
|
||||
my (@inlist, @outlist, $dir);
|
||||
|
||||
# Do what File::Spec::Unix->no_upwards should do
|
||||
my @inlist = split(/\//, File::Spec::Unix->canonpath($file));
|
||||
foreach $dir (@inlist) {
|
||||
if ($dir eq '..') {
|
||||
pop @outlist;
|
||||
} else {
|
||||
push @outlist, $dir;
|
||||
}
|
||||
}
|
||||
$file = join '/',@outlist;
|
||||
return $file;
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ interface nsILoadContext;
|
|||
[ptr] native JSContextPtr(JSContext);
|
||||
[ptr] native JSObjectPtr(JSObject);
|
||||
|
||||
[scriptable, uuid(3b021962-975e-43b5-8a93-9fc2d20346e9)]
|
||||
[scriptable, uuid(f649959d-dae3-4027-83fd-5b7f8c8a8815)]
|
||||
interface nsIScriptSecurityManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -178,13 +178,6 @@ interface nsIScriptSecurityManager : nsISupports
|
|||
*/
|
||||
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Returns OK if aJSContext and target have the same "origin"
|
||||
* (scheme, host, and port).
|
||||
*/
|
||||
[noscript] void checkSameOrigin(in JSContextPtr aJSContext,
|
||||
in nsIURI aTargetURI);
|
||||
|
||||
/**
|
||||
* Returns OK if aSourceURI and target have the same "origin"
|
||||
* (scheme, host, and port).
|
||||
|
|
|
@ -346,6 +346,17 @@ nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrinc
|
|||
}
|
||||
}
|
||||
|
||||
// See if aURI is something like a Blob URI that is actually associated with
|
||||
// a principal.
|
||||
nsCOMPtr<nsIURIWithPrincipal> uriWithPrin = do_QueryInterface(aURI);
|
||||
nsCOMPtr<nsIPrincipal> uriPrin;
|
||||
if (uriWithPrin) {
|
||||
uriWithPrin->GetPrincipal(getter_AddRefs(uriPrin));
|
||||
}
|
||||
if (uriPrin && nsIPrincipal::Subsumes(uriPrin)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -441,39 +441,6 @@ nsScriptSecurityManager::JSPrincipalsSubsume(JSPrincipals *first,
|
|||
return nsJSPrincipals::get(first)->Subsumes(nsJSPrincipals::get(second));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
|
||||
nsIURI* aTargetURI)
|
||||
{
|
||||
MOZ_ASSERT_IF(cx, cx == nsContentUtils::GetCurrentJSContext());
|
||||
|
||||
// Get a principal from the context
|
||||
nsIPrincipal* sourcePrincipal = nsContentUtils::SubjectPrincipal();
|
||||
if (sourcePrincipal == mSystemPrincipal)
|
||||
{
|
||||
// This is a system (chrome) script, so allow access
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the original URI from the source principal.
|
||||
// This has the effect of ignoring any change to document.domain
|
||||
// which must be done to avoid DNS spoofing (bug 154930)
|
||||
nsCOMPtr<nsIURI> sourceURI;
|
||||
sourcePrincipal->GetDomain(getter_AddRefs(sourceURI));
|
||||
if (!sourceURI) {
|
||||
sourcePrincipal->GetURI(getter_AddRefs(sourceURI));
|
||||
NS_ENSURE_TRUE(sourceURI, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
// Compare origins
|
||||
if (!SecurityCompareURIs(sourceURI, aTargetURI))
|
||||
{
|
||||
ReportError(cx, NS_LITERAL_STRING("CheckSameOriginError"), sourceURI, aTargetURI);
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI,
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
#!/usr/bin/perl -w
|
||||
# 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/.
|
||||
|
||||
|
||||
#
|
||||
# Create a mapping from symbolic component name to directory name(s).
|
||||
#
|
||||
# Tue Oct 16 16:48:36 PDT 2001
|
||||
# <mcafee@netscape.com>
|
||||
|
||||
use strict;
|
||||
|
||||
# For --option1, --option2, ...
|
||||
use Getopt::Long;
|
||||
Getopt::Long::Configure("bundling_override");
|
||||
Getopt::Long::Configure("auto_abbrev");
|
||||
|
||||
# Globals
|
||||
my $list_only_mode = 0;
|
||||
my $opt_list_only;
|
||||
my $mapfile = "";
|
||||
my %map;
|
||||
|
||||
sub PrintUsage {
|
||||
die <<END_USAGE
|
||||
Prints out directories needed for a given list of components.
|
||||
usage: module2dir.pl [--list-only] [--mapfile mapfile] <component-name1> <component-name2> ...
|
||||
END_USAGE
|
||||
}
|
||||
|
||||
sub parse_map_file($) {
|
||||
my ($mapfile) = @_;
|
||||
my (%mod_map, $tmp, $dir, $mod, @mod_list);
|
||||
|
||||
undef %mod_map;
|
||||
open (MAPFILE, "$mapfile") || die ("$mapfile: $!\n");
|
||||
while ($tmp=<MAPFILE>) {
|
||||
chomp ($tmp);
|
||||
($dir, $mod, @mod_list) = split(/:/, $tmp, 3);
|
||||
$mod =~ s/[\s]*(\S+)[\s]*/$1/;
|
||||
$mod_map{$mod} .= "$dir ";
|
||||
}
|
||||
close(MAPFILE);
|
||||
foreach $mod (sort(keys %mod_map)) {
|
||||
my (@dirlist, @trimlist, $found, $tdir);
|
||||
@dirlist = split(/\s+/, $mod_map{$mod});
|
||||
$mod_map{$mod} = "";
|
||||
foreach $dir (@dirlist) {
|
||||
$found = 0;
|
||||
foreach $tdir (@trimlist) {
|
||||
$found++, last if ($dir =~ m/^$tdir\// || $dir eq $tdir);
|
||||
}
|
||||
push @trimlist, $dir if (!$found);
|
||||
}
|
||||
$map{$mod} = join(" ", @trimlist);
|
||||
#print "$mod: $map{$mod}\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub dir_for_required_component {
|
||||
my ($component) = @_;
|
||||
my $rv;
|
||||
my $dir;
|
||||
|
||||
$dir = $map{$component};
|
||||
if($dir) {
|
||||
# prepend "mozilla/" in front of directory names.
|
||||
$rv = "mozilla/$dir";
|
||||
$rv =~ s/\s+/ mozilla\//g; # Hack for 2 or more directories.
|
||||
} else {
|
||||
$rv = 0;
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
# Add stdin to the commandline. This makes commandline-only mode hang,
|
||||
# call it a bug. Not sure how to get around this.
|
||||
push (@ARGV, split(' ',<STDIN>));
|
||||
|
||||
PrintUsage() if !GetOptions('list-only' => \$opt_list_only,
|
||||
'mapfile=s' => \$mapfile);
|
||||
|
||||
# Pick up arguments, if any.
|
||||
if($opt_list_only) {
|
||||
$list_only_mode = 1;
|
||||
}
|
||||
|
||||
&parse_map_file($mapfile);
|
||||
|
||||
my $arg;
|
||||
my $dir;
|
||||
while ($arg = shift @ARGV) {
|
||||
$dir = dir_for_required_component($arg);
|
||||
if($dir) {
|
||||
if($list_only_mode) {
|
||||
print $dir, " ";
|
||||
} else {
|
||||
print "$arg: ", $dir, "\n";
|
||||
}
|
||||
} else {
|
||||
# do nothing
|
||||
}
|
||||
}
|
||||
if($dir && $list_only_mode) {
|
||||
print "\n";
|
||||
}
|
||||
}
|
|
@ -155,13 +155,8 @@ ifdef MOZ_LDAP_XPCOM
|
|||
ldap/target: config/external/nss/target mozglue/build/target
|
||||
toolkit/library/target: ldap/target
|
||||
endif
|
||||
ifndef MOZ_FOLD_LIBS
|
||||
ifndef MOZ_NATIVE_SQLITE
|
||||
config/external/nss/target: db/sqlite3/src/target
|
||||
endif
|
||||
endif
|
||||
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
|
||||
mozglue/build/target: memory/replace/dummy/target
|
||||
mozglue/build/target memory/replace/logalloc/replay/target: memory/replace/dummy/target
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -696,7 +696,7 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
|
||||
endif
|
||||
else # !WINNT || GNU_CC
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
|
||||
$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
$(call CHECK_BINARY,$@)
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -752,7 +752,7 @@ ifdef MSMANIFEST_TOOL
|
|||
fi
|
||||
endif # MSVC with manifest tool
|
||||
else
|
||||
$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
|
||||
$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS)
|
||||
$(call CHECK_BINARY,$@)
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
@ -834,10 +834,10 @@ ifdef DTRACE_LIB_DEPENDENT
|
|||
ifndef XP_MACOSX
|
||||
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
|
||||
endif
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
@$(RM) $(DTRACE_PROBE_OBJ)
|
||||
else # ! DTRACE_LIB_DEPENDENT
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE) $(if $(LIB_IS_C_ONLY),,$(STLPORT_LIBS))
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
endif # DTRACE_LIB_DEPENDENT
|
||||
$(call CHECK_BINARY,$@)
|
||||
|
||||
|
|
|
@ -229,7 +229,6 @@ if test -n "$gonkdir" ; then
|
|||
AC_MSG_ERROR([Couldn't find path to stlport sources in the gonk tree])
|
||||
fi
|
||||
STLPORT_CPPFLAGS="-I$_topsrcdir/build/stlport/stlport -I$gonkdir/ndk/sources/cxx-stl/system/include"
|
||||
STLPORT_LIBS="$_objdir/build/stlport/libstlport_static.a"
|
||||
|
||||
case "$target_cpu" in
|
||||
arm)
|
||||
|
@ -9060,8 +9059,6 @@ HAVE_SYS_VFS_H
|
|||
HAVE_SYS_MOUNT_H
|
||||
"
|
||||
|
||||
AC_SUBST(STLPORT_LIBS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl ICU Support
|
||||
dnl ========================================================
|
||||
|
|
|
@ -53,8 +53,9 @@
|
|||
var s2 = snapshotWindow($("f2").contentWindow);
|
||||
var s3 = snapshotWindow($("f3").contentWindow);
|
||||
|
||||
ok(!compareSnapshots(s2, s3, true)[0],
|
||||
"Should look different due to different sizing");
|
||||
// This test is broken - see bug 1090274
|
||||
//ok(!compareSnapshots(s2, s3, true)[0],
|
||||
// "Should look different due to different sizing");
|
||||
|
||||
function getDOM(id) {
|
||||
return $(id).contentDocument.documentElement.innerHTML;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "mozIThirdPartyUtil.h"
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
#include "mozilla/dom/MediaDevices.h"
|
||||
#include "MediaManager.h"
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT
|
||||
|
@ -1219,6 +1220,21 @@ Navigator::SendBeacon(const nsAString& aUrl,
|
|||
}
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
MediaDevices*
|
||||
Navigator::GetMediaDevices(ErrorResult& aRv)
|
||||
{
|
||||
if (!mMediaDevices) {
|
||||
if (!mWindow ||
|
||||
!mWindow->GetOuterWindow() ||
|
||||
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return nullptr;
|
||||
}
|
||||
mMediaDevices = new MediaDevices(mWindow);
|
||||
}
|
||||
return mMediaDevices;
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
NavigatorUserMediaSuccessCallback& aOnSuccess,
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
class Geolocation;
|
||||
class systemMessageCallback;
|
||||
class MediaDevices;
|
||||
struct MediaStreamConstraints;
|
||||
class WakeLock;
|
||||
class ArrayBufferViewOrBlobOrStringOrFormData;
|
||||
|
@ -226,6 +227,7 @@ public:
|
|||
TVManager* GetTv();
|
||||
network::Connection* GetConnection(ErrorResult& aRv);
|
||||
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
|
||||
MediaDevices* GetMediaDevices(ErrorResult& aRv);
|
||||
void MozSetMessageHandler(const nsAString& aType,
|
||||
systemMessageCallback* aCallback,
|
||||
ErrorResult& aRv);
|
||||
|
@ -349,6 +351,7 @@ private:
|
|||
nsRefPtr<system::AudioChannelManager> mAudioChannelManager;
|
||||
#endif
|
||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||
nsRefPtr<MediaDevices> mMediaDevices;
|
||||
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
|
||||
nsRefPtr<time::TimeManager> mTimeManager;
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "mozilla/dom/quota/FileStreams.h"
|
||||
#include "mozilla/dom/quota/OriginOrPatternString.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
#include "mozilla/dom/quota/UsageInfo.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
|
@ -3885,7 +3884,6 @@ protected:
|
|||
nsCString mOrigin;
|
||||
nsCString mDatabaseId;
|
||||
State mState;
|
||||
StoragePrivilege mStoragePrivilege;
|
||||
bool mEnforcingQuota;
|
||||
const bool mDeleting;
|
||||
bool mBlockedQuotaManager;
|
||||
|
@ -8590,14 +8588,14 @@ Cursor::RecvContinue(const CursorRequestParams& aParams)
|
|||
FileManager::FileManager(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
StoragePrivilege aPrivilege,
|
||||
const nsAString& aDatabaseName)
|
||||
const nsAString& aDatabaseName,
|
||||
bool aEnforcingQuota)
|
||||
: mPersistenceType(aPersistenceType)
|
||||
, mGroup(aGroup)
|
||||
, mOrigin(aOrigin)
|
||||
, mPrivilege(aPrivilege)
|
||||
, mDatabaseName(aDatabaseName)
|
||||
, mLastFileId(0)
|
||||
, mEnforcingQuota(aEnforcingQuota)
|
||||
, mInvalidated(false)
|
||||
{ }
|
||||
|
||||
|
@ -10436,7 +10434,6 @@ FactoryOp::FactoryOp(Factory* aFactory,
|
|||
, mContentParent(Move(aContentParent))
|
||||
, mCommonParams(aCommonParams)
|
||||
, mState(State_Initial)
|
||||
, mStoragePrivilege(mozilla::dom::quota::Content)
|
||||
, mEnforcingQuota(true)
|
||||
, mDeleting(aDeleting)
|
||||
, mBlockedQuotaManager(false)
|
||||
|
@ -10735,9 +10732,7 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
|||
}
|
||||
|
||||
if (State_Initial == mState) {
|
||||
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, &mStoragePrivilege,
|
||||
nullptr);
|
||||
MOZ_ASSERT(mStoragePrivilege == mozilla::dom::quota::Chrome);
|
||||
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, nullptr, nullptr);
|
||||
mEnforcingQuota = false;
|
||||
}
|
||||
|
||||
|
@ -10789,12 +10784,10 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
|
|||
if (permission != PermissionRequestBase::kPermissionDenied &&
|
||||
State_Initial == mState) {
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
|
||||
&mStoragePrivilege, nullptr);
|
||||
nullptr, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mStoragePrivilege != mozilla::dom::quota::Chrome);
|
||||
}
|
||||
|
||||
if (permission == PermissionRequestBase::kPermissionAllowed &&
|
||||
|
@ -11326,8 +11319,8 @@ OpenDatabaseOp::DoDatabaseWork()
|
|||
fileManager = new FileManager(persistenceType,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mStoragePrivilege,
|
||||
databaseName);
|
||||
databaseName,
|
||||
mEnforcingQuota);
|
||||
|
||||
rv = fileManager->Init(fmDirectory, connection);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -12704,7 +12697,7 @@ VersionChangeOp::RunOnIOThread()
|
|||
if (exists) {
|
||||
int64_t fileSize;
|
||||
|
||||
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) {
|
||||
if (mDeleteDatabaseOp->mEnforcingQuota) {
|
||||
rv = dbFile->GetFileSize(&fileSize);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -12716,7 +12709,7 @@ VersionChangeOp::RunOnIOThread()
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) {
|
||||
if (mDeleteDatabaseOp->mEnforcingQuota) {
|
||||
quotaManager->DecreaseUsageForOrigin(persistenceType,
|
||||
mDeleteDatabaseOp->mGroup,
|
||||
mDeleteDatabaseOp->mOrigin,
|
||||
|
@ -12781,7 +12774,7 @@ VersionChangeOp::RunOnIOThread()
|
|||
|
||||
uint64_t usage = 0;
|
||||
|
||||
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) {
|
||||
if (mDeleteDatabaseOp->mEnforcingQuota) {
|
||||
rv = FileManager::GetUsage(fmDirectory, &usage);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -12793,7 +12786,7 @@ VersionChangeOp::RunOnIOThread()
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) {
|
||||
if (mDeleteDatabaseOp->mEnforcingQuota) {
|
||||
quotaManager->DecreaseUsageForOrigin(persistenceType,
|
||||
mDeleteDatabaseOp->mGroup,
|
||||
mDeleteDatabaseOp->mOrigin,
|
||||
|
@ -14425,12 +14418,14 @@ ObjectStoreAddOrPutRequestOp::CopyFileData(nsIInputStream* aInputStream,
|
|||
}
|
||||
} while (true);
|
||||
|
||||
nsresult rv2 = aOutputStream->Flush();
|
||||
if (NS_WARN_IF(NS_FAILED(rv2))) {
|
||||
return NS_SUCCEEDED(rv) ? rv2 : rv;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aOutputStream->Flush();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
rv2 = aOutputStream->Close();
|
||||
nsresult rv2 = aOutputStream->Close();
|
||||
if (NS_WARN_IF(NS_FAILED(rv2))) {
|
||||
return NS_SUCCEEDED(rv) ? rv2 : rv;
|
||||
}
|
||||
|
@ -14804,9 +14799,31 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(TransactionBase* aTransaction)
|
|||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// Try to remove the file if the copy failed.
|
||||
if (NS_FAILED(diskFile->Remove(false))) {
|
||||
NS_WARNING("Failed to remove file after copying failed!");
|
||||
nsresult rv2;
|
||||
int64_t fileSize;
|
||||
|
||||
if (mFileManager->EnforcingQuota()) {
|
||||
rv2 = diskFile->GetFileSize(&fileSize);
|
||||
if (NS_WARN_IF(NS_FAILED(rv2))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
rv2 = diskFile->Remove(false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv2))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mFileManager->EnforcingQuota()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager);
|
||||
|
||||
quotaManager->DecreaseUsageForOrigin(mFileManager->Type(),
|
||||
mFileManager->Group(),
|
||||
mFileManager->Origin(),
|
||||
fileSize);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
@ -29,12 +28,10 @@ class FileManager MOZ_FINAL
|
|||
friend class FileInfo;
|
||||
|
||||
typedef mozilla::dom::quota::PersistenceType PersistenceType;
|
||||
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
|
||||
|
||||
PersistenceType mPersistenceType;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
StoragePrivilege mPrivilege;
|
||||
nsString mDatabaseName;
|
||||
|
||||
nsString mDirectoryPath;
|
||||
|
@ -45,6 +42,7 @@ class FileManager MOZ_FINAL
|
|||
// Protected by IndexedDatabaseManager::FileMutex()
|
||||
nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;
|
||||
|
||||
const bool mEnforcingQuota;
|
||||
bool mInvalidated;
|
||||
|
||||
public:
|
||||
|
@ -64,8 +62,8 @@ public:
|
|||
FileManager(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
StoragePrivilege aPrivilege,
|
||||
const nsAString& aDatabaseName);
|
||||
const nsAString& aDatabaseName,
|
||||
bool aEnforcingQuota);
|
||||
|
||||
PersistenceType
|
||||
Type() const
|
||||
|
@ -85,18 +83,18 @@ public:
|
|||
return mOrigin;
|
||||
}
|
||||
|
||||
const StoragePrivilege&
|
||||
Privilege() const
|
||||
{
|
||||
return mPrivilege;
|
||||
}
|
||||
|
||||
const nsAString&
|
||||
DatabaseName() const
|
||||
{
|
||||
return mDatabaseName;
|
||||
}
|
||||
|
||||
bool
|
||||
EnforcingQuota() const
|
||||
{
|
||||
return mEnforcingQuota;
|
||||
}
|
||||
|
||||
bool
|
||||
Invalidated() const
|
||||
{
|
||||
|
|
|
@ -848,7 +848,7 @@ AsyncDeleteFileRunnable::Run()
|
|||
nsresult rv;
|
||||
int64_t fileSize;
|
||||
|
||||
if (mFileManager->Privilege() != Chrome) {
|
||||
if (mFileManager->EnforcingQuota()) {
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
@ -856,7 +856,7 @@ AsyncDeleteFileRunnable::Run()
|
|||
rv = file->Remove(false);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
if (mFileManager->Privilege() != Chrome) {
|
||||
if (mFileManager->EnforcingQuota()) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
NS_ASSERTION(quotaManager, "Shouldn't be null!");
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "mozilla/dom/indexedDB/IDBCursor.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "mozilla/dom/quota/PersistenceType.h"
|
||||
#include "mozilla/dom/quota/StoragePrivilege.h"
|
||||
|
||||
namespace IPC {
|
||||
|
||||
|
@ -24,13 +23,6 @@ struct ParamTraits<mozilla::dom::quota::PersistenceType> :
|
|||
mozilla::dom::quota::PERSISTENCE_TYPE_INVALID>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::quota::StoragePrivilege> :
|
||||
public ContiguousEnumSerializer<mozilla::dom::quota::StoragePrivilege,
|
||||
mozilla::dom::quota::Chrome,
|
||||
mozilla::dom::quota::Invalid>
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::dom::indexedDB::Key>
|
||||
{
|
||||
|
|
|
@ -33,7 +33,12 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMMediaStream)
|
|||
NS_INTERFACE_MAP_ENTRY(DOMMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(DOMLocalMediaStream, DOMMediaStream)
|
||||
NS_IMPL_ADDREF_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMLocalMediaStream, DOMMediaStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_ENTRY(DOMLocalMediaStream)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream,
|
||||
mStreamNode)
|
||||
|
|
|
@ -20,15 +20,10 @@ namespace mozilla {
|
|||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaDecoderLog;
|
||||
#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
|
||||
#ifdef SEEK_LOGGING
|
||||
#define SEEK_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
|
||||
#define DECODER_LOG(x, ...) \
|
||||
PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, ("Decoder=%p " x, mDecoder, ##__VA_ARGS__))
|
||||
#else
|
||||
#define SEEK_LOG(type, msg)
|
||||
#endif
|
||||
#else
|
||||
#define DECODER_LOG(type, msg)
|
||||
#define SEEK_LOG(type, msg)
|
||||
#define DECODER_LOG(x, ...)
|
||||
#endif
|
||||
|
||||
class VideoQueueMemoryFunctor : public nsDequeFunctor {
|
||||
|
@ -139,6 +134,20 @@ MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
int64_t
|
||||
MediaDecoderReader::ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio)
|
||||
{
|
||||
int64_t startTime = std::min<int64_t>(aAudio ? aAudio->mTime : INT64_MAX,
|
||||
aVideo ? aVideo->mTime : INT64_MAX);
|
||||
if (startTime == INT64_MAX) {
|
||||
startTime = 0;
|
||||
}
|
||||
DECODER_LOG("ComputeStartTime first video frame start %lld", aVideo ? aVideo->mTime : -1);
|
||||
DECODER_LOG("ComputeStartTime first audio frame start %lld", aAudio ? aAudio->mTime : -1);
|
||||
MOZ_ASSERT(startTime >= 0);
|
||||
return startTime;
|
||||
}
|
||||
|
||||
class RequestVideoWithSkipTask : public nsRunnable {
|
||||
public:
|
||||
RequestVideoWithSkipTask(MediaDecoderReader* aReader,
|
||||
|
|
|
@ -148,6 +148,8 @@ public:
|
|||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
||||
int64_t aStartTime);
|
||||
|
||||
virtual int64_t ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio);
|
||||
|
||||
// Returns the number of bytes of memory allocated by structures/frames in
|
||||
// the video queue.
|
||||
size_t SizeOfVideoQueueInBytes() const;
|
||||
|
|
|
@ -2016,18 +2016,9 @@ MediaDecoderStateMachine::FinishDecodeMetadata()
|
|||
}
|
||||
|
||||
if (!mScheduler->IsRealTime() && !mDecodingFrozenAtStateMetadata) {
|
||||
|
||||
const VideoData* v = VideoQueue().PeekFront();
|
||||
const AudioData* a = AudioQueue().PeekFront();
|
||||
|
||||
int64_t startTime = std::min<int64_t>(a ? a->mTime : INT64_MAX,
|
||||
v ? v->mTime : INT64_MAX);
|
||||
if (startTime == INT64_MAX) {
|
||||
startTime = 0;
|
||||
}
|
||||
DECODER_LOG("DecodeMetadata first video frame start %lld", v ? v->mTime : -1);
|
||||
DECODER_LOG("DecodeMetadata first audio frame start %lld", a ? a->mTime : -1);
|
||||
SetStartTime(startTime);
|
||||
SetStartTime(mReader->ComputeStartTime(v, a));
|
||||
if (VideoQueue().GetSize()) {
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
RenderVideoFrame(VideoQueue().PeekFront(), TimeStamp::Now());
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* 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/dom/MediaDevices.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaDevicesBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/MediaManager.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaDevices::GumResolver : public nsIDOMGetUserMediaSuccessCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit GumResolver(Promise* aPromise) : mPromise(aPromise) {}
|
||||
|
||||
NS_IMETHOD
|
||||
OnSuccess(nsISupports* aStream) MOZ_OVERRIDE
|
||||
{
|
||||
nsRefPtr<DOMLocalMediaStream> stream = do_QueryObject(aStream);
|
||||
if (!stream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mPromise->MaybeResolve(stream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~GumResolver() {}
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
class MediaDevices::GumRejecter : public nsIDOMGetUserMediaErrorCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit GumRejecter(Promise* aPromise) : mPromise(aPromise) {}
|
||||
|
||||
NS_IMETHOD
|
||||
OnError(nsISupports* aError) MOZ_OVERRIDE
|
||||
{
|
||||
nsRefPtr<MediaStreamError> error = do_QueryObject(aError);
|
||||
if (!error) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mPromise->MaybeReject(error);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~GumRejecter() {}
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MediaDevices::GumResolver, nsIDOMGetUserMediaSuccessCallback)
|
||||
NS_IMPL_ISUPPORTS(MediaDevices::GumRejecter, nsIDOMGetUserMediaErrorCallback)
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MediaDevices::GetUserMedia(const MediaStreamConstraints& aConstraints,
|
||||
ErrorResult &aRv)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
|
||||
nsRefPtr<Promise> p = Promise::Create(go, aRv);
|
||||
NS_ENSURE_TRUE(!rv.Failed(), nullptr);
|
||||
|
||||
nsRefPtr<GumResolver> resolver = new GumResolver(p);
|
||||
nsRefPtr<GumRejecter> rejecter = new GumRejecter(p);
|
||||
|
||||
aRv = MediaManager::Get()->GetUserMedia(window, aConstraints,
|
||||
resolver, rejecter);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaDevices, DOMEventTargetHelper)
|
||||
NS_INTERFACE_MAP_BEGIN(MediaDevices)
|
||||
NS_INTERFACE_MAP_ENTRY(MediaDevices)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
JSObject*
|
||||
MediaDevices::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaDevicesBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,50 @@
|
|||
/* 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 MediaDevices_h__
|
||||
#define MediaDevices_h__
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
struct MediaStreamConstraints;
|
||||
|
||||
#define MOZILLA_DOM_MEDIADEVICES_IMPLEMENTATION_IID \
|
||||
{ 0x2f784d8a, 0x7485, 0x4280, \
|
||||
{ 0x9a, 0x36, 0x74, 0xa4, 0xd6, 0x71, 0xa6, 0xc8 } }
|
||||
|
||||
class MediaDevices MOZ_FINAL : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
MediaDevices(nsPIDOMWindow* aWindow) : DOMEventTargetHelper(aWindow) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIADEVICES_IMPLEMENTATION_IID)
|
||||
|
||||
JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetUserMedia(const MediaStreamConstraints& aConstraints, ErrorResult &aRv);
|
||||
|
||||
private:
|
||||
class GumResolver;
|
||||
class GumRejecter;
|
||||
|
||||
virtual ~MediaDevices() {}
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaDevices,
|
||||
MOZILLA_DOM_MEDIADEVICES_IMPLEMENTATION_IID)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MediaDevices_h__
|
|
@ -102,6 +102,7 @@ GetMediaManagerLog()
|
|||
using dom::MediaStreamConstraints; // Outside API (contains JSObject)
|
||||
using dom::MediaTrackConstraintSet; // Mandatory or optional constraints
|
||||
using dom::MediaTrackConstraints; // Raw mMandatory (as JSObject)
|
||||
using dom::MediaStreamError;
|
||||
using dom::GetUserMediaRequest;
|
||||
using dom::Sequence;
|
||||
using dom::OwningBooleanOrMediaTrackConstraints;
|
||||
|
@ -194,20 +195,21 @@ HostHasPermission(nsIURI &docURI)
|
|||
}
|
||||
|
||||
ErrorCallbackRunnable::ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
const nsAString& aErrorMsg, uint64_t aWindowID)
|
||||
: mErrorMsg(aErrorMsg)
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError,
|
||||
uint64_t aWindowID)
|
||||
: mError(&aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mSuccess.swap(aSuccess);
|
||||
mError.swap(aError);
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
ErrorCallbackRunnable::~ErrorCallbackRunnable()
|
||||
{
|
||||
MOZ_ASSERT(!mSuccess && !mError);
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -216,15 +218,19 @@ ErrorCallbackRunnable::Run()
|
|||
// Only run if the window is still active.
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
|
||||
if (!(mManager->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
error->OnError(mErrorMsg);
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window, *mError);
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -238,15 +244,15 @@ class SuccessCallbackRunnable : public nsRunnable
|
|||
{
|
||||
public:
|
||||
SuccessCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
nsIDOMFile* aFile, uint64_t aWindowID)
|
||||
: mFile(aFile)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mSuccess.swap(aSuccess);
|
||||
mError.swap(aError);
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -255,21 +261,21 @@ public:
|
|||
// Only run if the window is still active.
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
|
||||
if (!(mManager->IsWindowStillActive(mWindowID))) {
|
||||
return NS_OK;
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
success->OnSuccess(mFile);
|
||||
onSuccess->OnSuccess(mFile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsCOMPtr<nsIDOMFile> mFile;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
|
@ -285,15 +291,15 @@ class DeviceSuccessCallbackRunnable: public nsRunnable
|
|||
public:
|
||||
DeviceSuccessCallbackRunnable(
|
||||
uint64_t aWindowID,
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
nsTArray<nsRefPtr<MediaDevice>>* aDevices)
|
||||
: mDevices(aDevices)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mSuccess.swap(aSuccess);
|
||||
mError.swap(aError);
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
|
@ -315,7 +321,12 @@ public:
|
|||
// We should in the future return an empty array, and dynamically add
|
||||
// devices to the dropdowns if things are hotplugged while the
|
||||
// requester is up.
|
||||
mError->OnError(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("NotFoundError"));
|
||||
mOnFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -331,13 +342,13 @@ public:
|
|||
static_cast<const void*>(tmp.Elements())
|
||||
));
|
||||
|
||||
mSuccess->OnSuccess(devices);
|
||||
mOnSuccess->OnSuccess(devices);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
|
@ -723,8 +734,8 @@ class GetUserMediaStreamRunnable : public nsRunnable
|
|||
{
|
||||
public:
|
||||
GetUserMediaStreamRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
uint64_t aWindowID,
|
||||
GetUserMediaCallbackMediaStreamListener* aListener,
|
||||
MediaEngineSource* aAudioSource,
|
||||
|
@ -737,8 +748,8 @@ public:
|
|||
, mPeerIdentity(aPeerIdentity)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
mSuccess.swap(aSuccess);
|
||||
mError.swap(aError);
|
||||
mOnSuccess.swap(aOnSuccess);
|
||||
mOnFailure.swap(aOnFailure);
|
||||
}
|
||||
|
||||
~GetUserMediaStreamRunnable() {}
|
||||
|
@ -750,7 +761,7 @@ public:
|
|||
nsIDOMGetUserMediaSuccessCallback* aSuccess,
|
||||
uint64_t aWindowID,
|
||||
DOMMediaStream* aStream)
|
||||
: mWindowID(aWindowID), mSuccess(aSuccess), mManager(aManager),
|
||||
: mWindowID(aWindowID), mOnSuccess(aSuccess), mManager(aManager),
|
||||
mStream(aStream) {}
|
||||
virtual void NotifyTracksAvailable(DOMMediaStream* aStream) MOZ_OVERRIDE
|
||||
{
|
||||
|
@ -766,10 +777,10 @@ public:
|
|||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
LOG(("Returning success for getUserMedia()"));
|
||||
mSuccess->OnSuccess(aStream);
|
||||
mOnSuccess->OnSuccess(aStream);
|
||||
}
|
||||
uint64_t mWindowID;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
// Keep the DOMMediaStream alive until the NotifyTracksAvailable callback
|
||||
// has fired, otherwise we might immediately destroy the DOMMediaStream and
|
||||
|
@ -830,9 +841,16 @@ public:
|
|||
nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener,
|
||||
mAudioSource, mVideoSource);
|
||||
if (!trackunion) {
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("InternalError"),
|
||||
NS_LITERAL_STRING("No stream."));
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
trackunion->AudioConfig(aec_on, (uint32_t) aec,
|
||||
|
@ -874,7 +892,7 @@ public:
|
|||
|
||||
// Note: includes JS callbacks; must be released on MainThread
|
||||
TracksAvailableCallback* tracksAvailableCallback =
|
||||
new TracksAvailableCallback(mManager, mSuccess, mWindowID, trackunion);
|
||||
new TracksAvailableCallback(mManager, mOnSuccess, mWindowID, trackunion);
|
||||
|
||||
mListener->AudioConfig(aec_on, (uint32_t) aec,
|
||||
agc_on, (uint32_t) agc,
|
||||
|
@ -889,16 +907,16 @@ public:
|
|||
new MediaOperationTask(MEDIA_START, mListener, trackunion,
|
||||
tracksAvailableCallback,
|
||||
mAudioSource, mVideoSource, false, mWindowID,
|
||||
mError.forget()));
|
||||
mOnFailure.forget()));
|
||||
|
||||
// We won't need mError now.
|
||||
mError = nullptr;
|
||||
// We won't need mOnFailure now.
|
||||
mOnFailure = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaEngineSource> mAudioSource;
|
||||
nsRefPtr<MediaEngineSource> mVideoSource;
|
||||
uint64_t mWindowID;
|
||||
|
@ -1056,13 +1074,13 @@ class GetUserMediaTask : public Task
|
|||
public:
|
||||
GetUserMediaTask(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
MediaEnginePrefs &aPrefs)
|
||||
: mConstraints(aConstraints)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mOnSuccess(aOnSuccess)
|
||||
, mOnFailure(aOnFailure)
|
||||
, mWindowID(aWindowID)
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
|
@ -1077,14 +1095,14 @@ public:
|
|||
*/
|
||||
GetUserMediaTask(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
MediaEnginePrefs &aPrefs,
|
||||
MediaEngine* aBackend)
|
||||
: mConstraints(aConstraints)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mOnSuccess(aOnSuccess)
|
||||
, mOnFailure(aOnFailure)
|
||||
, mWindowID(aWindowID)
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
|
@ -1097,12 +1115,14 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
Fail(const nsAString& aMessage) {
|
||||
Fail(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString()) {
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage);
|
||||
nsRefPtr<ErrorCallbackRunnable> runnable =
|
||||
new ErrorCallbackRunnable(mSuccess, mError, aMessage, mWindowID);
|
||||
new ErrorCallbackRunnable(mOnSuccess, mOnFailure, *error, mWindowID);
|
||||
// These should be empty now
|
||||
MOZ_ASSERT(!mSuccess);
|
||||
MOZ_ASSERT(!mError);
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
@ -1111,8 +1131,8 @@ public:
|
|||
Run()
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
MOZ_ASSERT(mSuccess);
|
||||
MOZ_ASSERT(mError);
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
MOZ_ASSERT(mOnFailure);
|
||||
|
||||
MediaEngine* backend = mBackend;
|
||||
// Was a backend provided?
|
||||
|
@ -1136,34 +1156,40 @@ public:
|
|||
}
|
||||
|
||||
nsresult
|
||||
Denied(const nsAString& aErrorMsg)
|
||||
Denied(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString())
|
||||
{
|
||||
MOZ_ASSERT(mSuccess);
|
||||
MOZ_ASSERT(mError);
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
MOZ_ASSERT(mOnFailure);
|
||||
|
||||
// We add a disabled listener to the StreamListeners array until accepted
|
||||
// If this was the only active MediaStream, remove the window from the list.
|
||||
if (NS_IsMainThread()) {
|
||||
// This is safe since we're on main-thread, and the window can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget();
|
||||
error->OnError(aErrorMsg);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
aName, aMessage);
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
// Should happen *after* error runs for consistency, but may not matter
|
||||
nsRefPtr<MediaManager> manager(MediaManager::GetInstance());
|
||||
manager->RemoveFromWindowList(mWindowID, mListener);
|
||||
} else {
|
||||
// This will re-check the window being alive on main-thread
|
||||
// Note: we must remove the listener on MainThread as well
|
||||
Fail(aErrorMsg);
|
||||
Fail(aName, aMessage);
|
||||
|
||||
// MUST happen after ErrorCallbackRunnable Run()s, as it checks the active window list
|
||||
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mSuccess);
|
||||
MOZ_ASSERT(!mError);
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1194,15 +1220,15 @@ public:
|
|||
nsresult
|
||||
SelectDevice(MediaEngine* backend)
|
||||
{
|
||||
MOZ_ASSERT(mSuccess);
|
||||
MOZ_ASSERT(mError);
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
MOZ_ASSERT(mOnFailure);
|
||||
if (IsOn(mConstraints.mVideo)) {
|
||||
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
|
||||
nsTArray<nsRefPtr<VideoDevice>> sources;
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources);
|
||||
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
Fail(NS_LITERAL_STRING("NotFoundError"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
|
@ -1215,7 +1241,7 @@ public:
|
|||
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources);
|
||||
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
Fail(NS_LITERAL_STRING("NotFoundError"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
|
@ -1234,14 +1260,15 @@ public:
|
|||
ProcessGetUserMedia(MediaEngineAudioSource* aAudioSource,
|
||||
MediaEngineVideoSource* aVideoSource)
|
||||
{
|
||||
MOZ_ASSERT(mSuccess);
|
||||
MOZ_ASSERT(mError);
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
MOZ_ASSERT(mOnFailure);
|
||||
nsresult rv;
|
||||
if (aAudioSource) {
|
||||
rv = aAudioSource->Allocate(GetInvariant(mConstraints.mAudio), mPrefs);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Failed to allocate audiosource %d",rv));
|
||||
Fail(NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"));
|
||||
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
|
||||
NS_LITERAL_STRING("Failed to allocate audiosource"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1252,7 +1279,8 @@ public:
|
|||
if (aAudioSource) {
|
||||
aAudioSource->Deallocate();
|
||||
}
|
||||
Fail(NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"));
|
||||
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
|
||||
NS_LITERAL_STRING("Failed to allocate videosource"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1262,12 +1290,12 @@ public:
|
|||
}
|
||||
|
||||
NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
|
||||
mSuccess, mError, mWindowID, mListener, aAudioSource, aVideoSource,
|
||||
mOnSuccess, mOnFailure, mWindowID, mListener, aAudioSource, aVideoSource,
|
||||
peerIdentity
|
||||
));
|
||||
|
||||
MOZ_ASSERT(!mSuccess);
|
||||
MOZ_ASSERT(!mError);
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1275,8 +1303,8 @@ public:
|
|||
private:
|
||||
MediaStreamConstraints mConstraints;
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
|
||||
nsRefPtr<AudioDevice> mAudioDevice;
|
||||
|
@ -1322,13 +1350,13 @@ class GetUserMediaDevicesTask : public Task
|
|||
public:
|
||||
GetUserMediaDevicesTask(
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aOnSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
|
||||
uint64_t aWindowId, nsACString& aAudioLoopbackDev,
|
||||
nsACString& aVideoLoopbackDev)
|
||||
: mConstraints(aConstraints)
|
||||
, mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mOnSuccess(aOnSuccess)
|
||||
, mOnFailure(aOnFailure)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
, mWindowId(aWindowId)
|
||||
, mLoopbackAudioDevice(aAudioLoopbackDev)
|
||||
|
@ -1368,16 +1396,16 @@ public:
|
|||
}
|
||||
|
||||
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
|
||||
mSuccess, mError,
|
||||
mOnSuccess, mOnFailure,
|
||||
final.forget()));
|
||||
// DeviceSuccessCallbackRunnable should have taken these.
|
||||
MOZ_ASSERT(!mSuccess && !mError);
|
||||
MOZ_ASSERT(!mOnSuccess && !mOnFailure);
|
||||
}
|
||||
|
||||
private:
|
||||
MediaStreamConstraints mConstraints;
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
uint64_t mWindowId;
|
||||
const nsString mCallId;
|
||||
|
@ -1544,18 +1572,18 @@ nsresult
|
|||
MediaManager::GetUserMedia(
|
||||
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints,
|
||||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError)
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnError, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnFailure, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
|
||||
|
||||
bool privileged = nsContentUtils::IsChromeDoc(aWindow->GetExtantDoc());
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
|
||||
MediaStreamConstraints c(aConstraints); // copy
|
||||
|
||||
|
@ -1640,11 +1668,11 @@ MediaManager::GetUserMedia(
|
|||
if (c.mFake) {
|
||||
// Fake stream from default backend.
|
||||
task = new GetUserMediaTask(c, onSuccess.forget(),
|
||||
onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
|
||||
onFailure.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
|
||||
} else {
|
||||
// Stream from default device from WebRTC backend.
|
||||
task = new GetUserMediaTask(c, onSuccess.forget(),
|
||||
onError.forget(), windowID, listener, mPrefs);
|
||||
onFailure.forget(), windowID, listener, mPrefs);
|
||||
}
|
||||
|
||||
nsIURI* docURI = aWindow->GetDocumentURI();
|
||||
|
@ -1655,10 +1683,10 @@ MediaManager::GetUserMedia(
|
|||
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
if (tc.mMediaSource == dom::MediaSourceEnum::Browser) {
|
||||
if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
} else if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
/* Deny screensharing if the requesting document is not from a host
|
||||
on the whitelist. */
|
||||
|
@ -1676,7 +1704,7 @@ MediaManager::GetUserMedia(
|
|||
) ||
|
||||
#endif
|
||||
(!privileged && !HostHasPermission(*docURI))) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1730,7 +1758,7 @@ MediaManager::GetUserMedia(
|
|||
|
||||
if ((!IsOn(c.mAudio) || audioPerm == nsIPermissionManager::DENY_ACTION) &&
|
||||
(!IsOn(c.mVideo) || videoPerm == nsIPermissionManager::DENY_ACTION)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
|
||||
// Ask for user permission, and dispatch task (or not) when a response
|
||||
|
@ -1778,16 +1806,16 @@ nsresult
|
|||
MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
||||
const MediaStreamConstraints& aConstraints,
|
||||
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnFailure,
|
||||
uint64_t aInnerWindowID)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
NS_ENSURE_TRUE(aOnError, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnFailure, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
|
||||
|
||||
// Check if the preference for using loopback devices is enabled.
|
||||
nsAdoptingCString loopbackAudioDevice =
|
||||
|
@ -1797,7 +1825,7 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
|
|||
|
||||
MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
|
||||
new GetUserMediaDevicesTask(
|
||||
aConstraints, onSuccess.forget(), onError.forget(),
|
||||
aConstraints, onSuccess.forget(), onFailure.forget(),
|
||||
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
|
||||
loopbackAudioDevice, loopbackVideoDevice));
|
||||
|
||||
|
@ -2020,7 +2048,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
MOZ_ASSERT(len);
|
||||
if (!len) {
|
||||
// neither audio nor video were selected
|
||||
task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
return NS_OK;
|
||||
}
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
|
@ -2047,14 +2075,14 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
|
||||
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
|
||||
nsString errorMessage(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
nsString errorMessage(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
|
||||
if (aSubject) {
|
||||
nsCOMPtr<nsISupportsString> msg(do_QueryInterface(aSubject));
|
||||
MOZ_ASSERT(msg);
|
||||
msg->GetData(errorMessage);
|
||||
if (errorMessage.IsEmpty())
|
||||
errorMessage.AssignLiteral(MOZ_UTF16("UNKNOWN_ERROR"));
|
||||
errorMessage.AssignLiteral(MOZ_UTF16("InternalError"));
|
||||
}
|
||||
|
||||
nsString key(aData);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "prlog.h"
|
||||
#include "DOMMediaStream.h"
|
||||
|
||||
|
@ -268,7 +269,7 @@ class GetUserMediaNotificationEvent: public nsRunnable
|
|||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
|
||||
: mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
|
||||
mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID),
|
||||
mError(aError) {}
|
||||
mOnFailure(aError) {}
|
||||
virtual ~GetUserMediaNotificationEvent()
|
||||
{
|
||||
|
||||
|
@ -284,7 +285,7 @@ class GetUserMediaNotificationEvent: public nsRunnable
|
|||
bool mIsAudio;
|
||||
bool mIsVideo;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsRefPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -298,24 +299,24 @@ class MediaManager;
|
|||
class GetUserMediaTask;
|
||||
|
||||
/**
|
||||
* Send an error back to content. The error is the form a string.
|
||||
* Do this only on the main thread. The success callback is also passed here
|
||||
* Send an error back to content.
|
||||
* Do this only on the main thread. The onSuccess callback is also passed here
|
||||
* so it can be released correctly.
|
||||
*/
|
||||
class ErrorCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
const nsAString& aErrorMsg, uint64_t aWindowID);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError, uint64_t aWindowID);
|
||||
NS_IMETHOD Run();
|
||||
private:
|
||||
~ErrorCallbackRunnable();
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
const nsString mErrorMsg;
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
nsRefPtr<MediaMgrError> mError;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
|
@ -357,7 +358,7 @@ public:
|
|||
, mListener(aListener)
|
||||
, mBool(aBool)
|
||||
, mWindowID(aWindowID)
|
||||
, mError(aError)
|
||||
, mOnFailure(aError)
|
||||
{}
|
||||
|
||||
~MediaOperationTask()
|
||||
|
@ -373,10 +374,12 @@ public:
|
|||
mOnTracksAvailableCallback.forget()));
|
||||
nsString log;
|
||||
|
||||
log.AssignASCII(errorLog, strlen(errorLog));
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success;
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(success, mError,
|
||||
log, mWindowID));
|
||||
log.AssignASCII(errorLog);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(
|
||||
NS_LITERAL_STRING("InternalError"), log);
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(onSuccess, mOnFailure,
|
||||
*error, mWindowID));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -428,7 +431,7 @@ public:
|
|||
mOnTracksAvailableCallback.forget(),
|
||||
mAudioSource != nullptr,
|
||||
mVideoSource != nullptr,
|
||||
mWindowID, mError.forget());
|
||||
mWindowID, mOnFailure.forget());
|
||||
// event must always be released on mainthread due to the JS callbacks
|
||||
// in the TracksAvailableCallback
|
||||
NS_DispatchToMainThread(event);
|
||||
|
@ -490,7 +493,7 @@ private:
|
|||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
|
||||
bool mBool;
|
||||
uint64_t mWindowID;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
};
|
||||
|
||||
typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "GetUserMediaRequest.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
|
@ -224,7 +225,7 @@ MediaPermissionRequest::Cancel()
|
|||
{
|
||||
nsString callID;
|
||||
mRequest->GetCallID(callID);
|
||||
NotifyPermissionDeny(callID, NS_LITERAL_STRING("Permission Denied"));
|
||||
NotifyPermissionDeny(callID, NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -393,9 +394,17 @@ NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
|
|||
|
||||
// nsIDOMGetUserMediaErrorCallback method
|
||||
NS_IMETHODIMP
|
||||
MediaDeviceErrorCallback::OnError(const nsAString &aError)
|
||||
MediaDeviceErrorCallback::OnError(nsISupports* aError)
|
||||
{
|
||||
return NotifyPermissionDeny(mCallID, aError);
|
||||
MediaStreamError *error = nullptr;
|
||||
nsresult rv = CallQueryInterface(aError, &error);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsString name;
|
||||
error->GetName(name);
|
||||
return NotifyPermissionDeny(mCallID, name);
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "MediaStreamError.h"
|
||||
#include "mozilla/dom/MediaStreamErrorBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
BaseMediaMgrError::BaseMediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName)
|
||||
: mName(aName)
|
||||
, mMessage(aMessage)
|
||||
, mConstraintName(aConstraintName)
|
||||
{
|
||||
if (mMessage.IsEmpty()) {
|
||||
if (mName.EqualsLiteral("NotFoundError")) {
|
||||
mMessage.AssignLiteral("The object can not be found here.");
|
||||
} else if (mName.EqualsLiteral("PermissionDeniedError")) {
|
||||
mMessage.AssignLiteral("The user did not grant permission for the operation.");
|
||||
} else if (mName.EqualsLiteral("SourceUnavailableError")) {
|
||||
mMessage.AssignLiteral("The source of the MediaStream could not be "
|
||||
"accessed due to a hardware error (e.g. lock from another process).");
|
||||
} else if (mName.EqualsLiteral("InternalError")) {
|
||||
mMessage.AssignLiteral("Internal error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS0(MediaMgrError)
|
||||
|
||||
namespace dom {
|
||||
|
||||
MediaStreamError::MediaStreamError(
|
||||
nsPIDOMWindow* aParent,
|
||||
const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName)
|
||||
: BaseMediaMgrError(aName, aMessage, aConstraintName)
|
||||
, mParent(aParent) {}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaStreamError, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaStreamError)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaStreamError)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamError)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(MediaStreamError)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject*
|
||||
MediaStreamError::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return MediaStreamErrorBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamError::GetName(nsAString& aName) const
|
||||
{
|
||||
aName = mName;
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamError::GetMessage(nsAString& aMessage) const
|
||||
{
|
||||
aMessage = mMessage;
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamError::GetConstraintName(nsAString& aConstraintName) const
|
||||
{
|
||||
aConstraintName = mConstraintName;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,99 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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_MediaStreamError_h
|
||||
#define mozilla_dom_MediaStreamError_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsRefPtr.h"
|
||||
|
||||
#if defined(XP_WIN) && defined(GetMessage)
|
||||
#undef GetMessage
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#define MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID \
|
||||
{ 0x95fa29aa, 0x0cc2, 0x4698, \
|
||||
{ 0x9d, 0xa9, 0xf2, 0xeb, 0x03, 0x91, 0x0b, 0xd1 } }
|
||||
|
||||
class MediaStreamError;
|
||||
}
|
||||
|
||||
class BaseMediaMgrError
|
||||
{
|
||||
friend class dom::MediaStreamError;
|
||||
protected:
|
||||
BaseMediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName);
|
||||
const nsString mName;
|
||||
nsString mMessage;
|
||||
const nsString mConstraintName;
|
||||
};
|
||||
|
||||
class MediaMgrError MOZ_FINAL : public nsISupports,
|
||||
public BaseMediaMgrError
|
||||
{
|
||||
public:
|
||||
MediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString(),
|
||||
const nsAString& aConstraintName = EmptyString())
|
||||
: BaseMediaMgrError(aName, aMessage, aConstraintName) {}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
~MediaMgrError() {}
|
||||
};
|
||||
|
||||
namespace dom {
|
||||
class MediaStreamError MOZ_FINAL : public nsISupports,
|
||||
public BaseMediaMgrError,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
MediaStreamError(nsPIDOMWindow* aParent,
|
||||
const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString(),
|
||||
const nsAString& aConstraintName = EmptyString());
|
||||
|
||||
MediaStreamError(nsPIDOMWindow* aParent,
|
||||
const BaseMediaMgrError& aOther)
|
||||
: BaseMediaMgrError(aOther.mName, aOther.mMessage, aOther.mConstraintName)
|
||||
, mParent(aParent) {}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaStreamError)
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
void GetName(nsAString& aName) const;
|
||||
void GetMessage(nsAString& aMessage) const;
|
||||
void GetConstraintName(nsAString& aConstraintName) const;
|
||||
|
||||
private:
|
||||
virtual ~MediaStreamError() {}
|
||||
|
||||
nsRefPtr<nsPIDOMWindow> mParent;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaStreamError,
|
||||
MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID)
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -70,6 +70,11 @@ public:
|
|||
return mInfo.HasAudio();
|
||||
}
|
||||
|
||||
// We can't compute a proper start time since we won't necessarily
|
||||
// have the first frame of the resource available. This does the same
|
||||
// as chrome/blink and assumes that we always start at t=0.
|
||||
virtual int64_t ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio) MOZ_OVERRIDE { return 0; }
|
||||
|
||||
bool IsMediaSeekable() { return true; }
|
||||
|
||||
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
|
||||
|
|
|
@ -143,6 +143,8 @@ EXPORTS.mozilla.dom += [
|
|||
'AudioTrack.h',
|
||||
'AudioTrackList.h',
|
||||
'GetUserMediaRequest.h',
|
||||
'MediaDevices.h',
|
||||
'MediaStreamError.h',
|
||||
'MediaStreamTrack.h',
|
||||
'TextTrack.h',
|
||||
'TextTrackCue.h',
|
||||
|
@ -177,10 +179,12 @@ UNIFIED_SOURCES += [
|
|||
'MediaDecoderReader.cpp',
|
||||
'MediaDecoderStateMachine.cpp',
|
||||
'MediaDecoderStateMachineScheduler.cpp',
|
||||
'MediaDevices.cpp',
|
||||
'MediaManager.cpp',
|
||||
'MediaRecorder.cpp',
|
||||
'MediaResource.cpp',
|
||||
'MediaShutdownManager.cpp',
|
||||
'MediaStreamError.cpp',
|
||||
'MediaStreamGraph.cpp',
|
||||
'MediaStreamTrack.cpp',
|
||||
'MediaTaskQueue.cpp',
|
||||
|
|
|
@ -34,5 +34,5 @@ interface nsIDOMGetUserMediaSuccessCallback : nsISupports
|
|||
[scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)]
|
||||
interface nsIDOMGetUserMediaErrorCallback : nsISupports
|
||||
{
|
||||
void onError(in DOMString error);
|
||||
void onError(in nsISupports error);
|
||||
};
|
||||
|
|
|
@ -14,19 +14,19 @@ var common_tests = [
|
|||
{ message: "unknown required constraint on video fails",
|
||||
constraints: { video: { somethingUnknown:0, require:["somethingUnknown"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "unknown required constraint on audio fails",
|
||||
constraints: { audio: { somethingUnknown:0, require:["somethingUnknown"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "video overconstrained by facingMode fails",
|
||||
constraints: { video: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "audio overconstrained by facingMode fails",
|
||||
constraints: { audio: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
|
||||
constraints: { fake: true,
|
||||
audio: { facingMode:'left',
|
||||
|
@ -48,29 +48,27 @@ var common_tests = [
|
|||
|
||||
/**
|
||||
* Starts the test run by running through each constraint
|
||||
* test by verifying that the right callback and error message is fired.
|
||||
* test by verifying that the right resolution and rejection is fired.
|
||||
*/
|
||||
|
||||
function testConstraints(tests) {
|
||||
var i = 0;
|
||||
next();
|
||||
function testgum(p, test) {
|
||||
return p.then(function() {
|
||||
return navigator.mediaDevices.getUserMedia(test.constraints);
|
||||
})
|
||||
.then(function() {
|
||||
is(null, test.error, test.message);
|
||||
}, function(reason) {
|
||||
is(reason.name, test.error, test.message + ": " + reason.message);
|
||||
});
|
||||
}
|
||||
|
||||
function Success() {
|
||||
ok(!tests[i].error, tests[i].message);
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function Failure(err) {
|
||||
ok(tests[i].error? (err === tests[i].error) : false,
|
||||
tests[i].message + " (err=" + err + ")");
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
function next() {
|
||||
if (i < tests.length) {
|
||||
navigator.mozGetUserMedia(tests[i].constraints, Success, Failure);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
var p = new Promise(function(resolve) { resolve(); });
|
||||
tests.forEach(function(test) {
|
||||
p = testgum(p, test);
|
||||
});
|
||||
p.catch(function(reason) {
|
||||
ok(false, "Unexpected failure: " + reason.message);
|
||||
})
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882145
|
|||
var mobile_tests = [
|
||||
{ message: "legacy facingMode overconstrains video (mobile)",
|
||||
constraints: { video: { mandatory: { facingMode:'left' } }, fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
];
|
||||
|
||||
runTest(function () {
|
||||
|
|
|
@ -26,7 +26,7 @@ function theTest() {
|
|||
config.peerIdentity = 'user@example.com';
|
||||
}
|
||||
info('getting media with constraints: ' + JSON.stringify(config));
|
||||
navigator.mozGetUserMedia(config, function(stream) {
|
||||
navigator.mediaDevices.getUserMedia(config).then(function(stream) {
|
||||
var oneDone = false;
|
||||
function checkDone() {
|
||||
if (oneDone) {
|
||||
|
@ -38,7 +38,8 @@ function theTest() {
|
|||
var cancelVideoCheck = videoIsBlack(withConstraint, stream, checkDone);
|
||||
setTimeout(cancelAudioCheck, 3*60*1000);
|
||||
setTimeout(cancelVideoCheck, 3*60*1000);
|
||||
}, function(e) {
|
||||
})
|
||||
.catch(function(e) {
|
||||
ok(false, 'gUM error: ' + e);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -37,23 +37,23 @@
|
|||
var track = stream.getVideoTracks()[0];
|
||||
var sender = test.pcLocal._pc.getSenders().find(isSenderOfTrack, track);
|
||||
ok(sender, "track has a sender");
|
||||
navigator.mozGetUserMedia({video:true, fake: true}, function(newStream) {
|
||||
navigator.mediaDevices.getUserMedia({video:true, fake: true})
|
||||
.then(function(newStream) {
|
||||
var newtrack = newStream.getVideoTracks()[0];
|
||||
sender.replaceTrack(newtrack,
|
||||
function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
sender.replaceTrack(newtrack, function() {
|
||||
resolve(newtrack);
|
||||
}, reject);
|
||||
});
|
||||
})
|
||||
.then(function(newtrack) {
|
||||
ok(true, "replaceTrack success callback is called");
|
||||
is(sender.track, newtrack, "sender.track has been replaced");
|
||||
test.next();
|
||||
},
|
||||
function(err) {
|
||||
ok(false, "replaceTrack failed with error = " + err);
|
||||
test.next();
|
||||
});
|
||||
},
|
||||
function(err) {
|
||||
ok(false, "mozGetUserMedia failed. error = " + err);
|
||||
test.next();
|
||||
});
|
||||
})
|
||||
.catch(function(reason) {
|
||||
ok(false, "unexpected error = " + reason.message);
|
||||
})
|
||||
.then(test.next.bind(test));
|
||||
}
|
||||
]]);
|
||||
test.chain.append(flowtest);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "mozilla/dom/SpeechRecognitionBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "mozilla/MediaManager.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
|
@ -23,6 +24,11 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
// Undo the windows.h damage
|
||||
#if defined(XP_WIN) && defined(GetMessage)
|
||||
#undef GetMessage
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -945,19 +951,26 @@ SpeechRecognition::GetUserMediaSuccessCallback::OnSuccess(nsISupports* aStream)
|
|||
NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMediaErrorCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechRecognition::GetUserMediaErrorCallback::OnError(const nsAString& aError)
|
||||
SpeechRecognition::GetUserMediaErrorCallback::OnError(nsISupports* aError)
|
||||
{
|
||||
nsRefPtr<MediaStreamError> error = do_QueryObject(aError);
|
||||
if (!error) {
|
||||
return NS_OK;
|
||||
}
|
||||
SpeechRecognitionErrorCode errorCode;
|
||||
|
||||
if (aError.EqualsLiteral("PERMISSION_DENIED")) {
|
||||
nsString name;
|
||||
error->GetName(name);
|
||||
if (name.EqualsLiteral("PERMISSION_DENIED")) {
|
||||
errorCode = SpeechRecognitionErrorCode::Not_allowed;
|
||||
} else {
|
||||
errorCode = SpeechRecognitionErrorCode::Audio_capture;
|
||||
}
|
||||
|
||||
nsString message;
|
||||
error->GetMessage(message);
|
||||
mRecognition->DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR, errorCode,
|
||||
aError);
|
||||
|
||||
message);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/dom/OwningNonNull.h"
|
||||
#include "mozilla/dom/PromiseBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "PromiseCallback.h"
|
||||
|
@ -354,6 +355,11 @@ Promise::MaybeReject(JSContext* aCx,
|
|||
MaybeRejectInternal(aCx, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
Promise::MaybeReject(const nsRefPtr<MediaStreamError>& aArg) {
|
||||
MaybeSomething(aArg, &Promise::MaybeReject);
|
||||
}
|
||||
|
||||
void
|
||||
Promise::PerformMicroTaskCheckpoint()
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace dom {
|
|||
|
||||
class AnyCallback;
|
||||
class DOMError;
|
||||
class MediaStreamError;
|
||||
class PromiseCallback;
|
||||
class PromiseInit;
|
||||
class PromiseNativeHandler;
|
||||
|
@ -99,6 +100,9 @@ public:
|
|||
MOZ_ASSERT(NS_FAILED(aArg));
|
||||
MaybeSomething(aArg, &Promise::MaybeReject);
|
||||
}
|
||||
|
||||
void MaybeReject(const nsRefPtr<MediaStreamError>& aArg);
|
||||
|
||||
// DO NOT USE MaybeRejectBrokenly with in new code. Promises should be
|
||||
// rejected with Error instances.
|
||||
// Note: MaybeRejectBrokenly is a template so we can use it with DOMError
|
||||
|
|
|
@ -1101,7 +1101,7 @@ QuotaManager::DecreaseUsageForOrigin(PersistenceType aPersistenceType,
|
|||
const nsACString& aOrigin,
|
||||
int64_t aSize)
|
||||
{
|
||||
AssertIsOnIOThread();
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
|
|
|
@ -81,6 +81,34 @@ SVGCircleElement::GetLengthInfo()
|
|||
//----------------------------------------------------------------------
|
||||
// nsSVGPathGeometryElement methods
|
||||
|
||||
bool
|
||||
SVGCircleElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
|
||||
const Matrix& aTransform)
|
||||
{
|
||||
float x, y, r;
|
||||
GetAnimatedLengthValues(&x, &y, &r, nullptr);
|
||||
|
||||
if (r <= 0.f) {
|
||||
// Rendering of the element is disabled
|
||||
aBounds->MoveTo(x, y);
|
||||
aBounds->SetEmpty();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aTransform.IsRectilinear()) {
|
||||
// Optimize the case where we can treat the circle as a rectangle and
|
||||
// still get tight bounds.
|
||||
if (aStrokeWidth > 0.f) {
|
||||
r += aStrokeWidth / 2.f;
|
||||
}
|
||||
Rect rect(x - r, y - r, 2 * r, 2 * r);
|
||||
*aBounds = aTransform.TransformBounds(rect);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TemporaryRef<Path>
|
||||
SVGCircleElement::BuildPath(PathBuilder* aBuilder)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
virtual bool HasValidDimensions() const MOZ_OVERRIDE;
|
||||
|
||||
// nsSVGPathGeometryElement methods:
|
||||
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
|
||||
const Matrix& aTransform) MOZ_OVERRIDE;
|
||||
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
|
|
@ -92,6 +92,35 @@ SVGEllipseElement::GetLengthInfo()
|
|||
//----------------------------------------------------------------------
|
||||
// nsSVGPathGeometryElement methods
|
||||
|
||||
bool
|
||||
SVGEllipseElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
|
||||
const Matrix& aTransform)
|
||||
{
|
||||
float x, y, rx, ry;
|
||||
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
|
||||
|
||||
if (rx <= 0.f || ry <= 0.f) {
|
||||
// Rendering of the element is disabled
|
||||
aBounds->MoveTo(x, y);
|
||||
aBounds->SetEmpty();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aTransform.IsRectilinear()) {
|
||||
// Optimize the case where we can treat the ellipse as a rectangle and
|
||||
// still get tight bounds.
|
||||
if (aStrokeWidth > 0.f) {
|
||||
rx += aStrokeWidth / 2.f;
|
||||
ry += aStrokeWidth / 2.f;
|
||||
}
|
||||
Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
|
||||
*aBounds = aTransform.TransformBounds(rect);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TemporaryRef<Path>
|
||||
SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
virtual bool HasValidDimensions() const MOZ_OVERRIDE;
|
||||
|
||||
// nsSVGPathGeometryElement methods:
|
||||
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
|
||||
const Matrix& aTransform) MOZ_OVERRIDE;
|
||||
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
|
|
@ -70,6 +70,12 @@ public:
|
|||
virtual bool IsMarkable();
|
||||
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
|
||||
|
||||
/**
|
||||
* A method that can be faster than using a Moz2D Path and calling GetBounds/
|
||||
* GetStrokedBounds on it. It also helps us avoid rounding error for simple
|
||||
* shapes and simple transforms where the Moz2D Path backends can fail to
|
||||
* produce the clean integer bounds that content authors expect in some cases.
|
||||
*/
|
||||
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
|
||||
const Matrix& aTransform) {
|
||||
return false;
|
||||
|
|
|
@ -635,6 +635,8 @@ var interfaceNamesInGlobalScope =
|
|||
"LocalMediaStream",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Location",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaDevices",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaElementAudioSourceNode",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[Func="Navigator::HasUserMediaSupport"]
|
||||
interface MediaDevices : EventTarget {
|
||||
// attribute EventHandler ondevicechange;
|
||||
//
|
||||
// void enumerateDevices (MediaDeviceInfoCallback resultCallback);
|
||||
//
|
||||
// static Dictionary getSupportedConstraints (DOMString kind);
|
||||
|
||||
[Throws, Func="Navigator::HasUserMediaSupport"]
|
||||
Promise<MediaStream> getUserMedia(optional MediaStreamConstraints constraints);
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://w3c.github.io/mediacapture-main/getusermedia.html#idl-def-MediaStreamError
|
||||
*/
|
||||
|
||||
// The future of MediaStreamError is uncertain.
|
||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=26776
|
||||
|
||||
// TODO: This is an 'exception', not an interface, by virtue of needing to be
|
||||
// passed as a promise rejection-reason. Revisit if DOMException grows a customArg
|
||||
|
||||
[ExceptionClass, NoInterfaceObject]
|
||||
interface MediaStreamError {
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString? message;
|
||||
readonly attribute DOMString? constraintName;
|
||||
};
|
|
@ -354,9 +354,13 @@ partial interface Navigator {
|
|||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
callback NavigatorUserMediaSuccessCallback = void (MediaStream stream);
|
||||
callback NavigatorUserMediaErrorCallback = void (DOMString error);
|
||||
callback NavigatorUserMediaErrorCallback = void (MediaStreamError error);
|
||||
|
||||
partial interface Navigator {
|
||||
[Throws, Func="Navigator::HasUserMediaSupport"]
|
||||
readonly attribute MediaDevices mediaDevices;
|
||||
|
||||
// Deprecated. Use mediaDevices.getUserMedia instead.
|
||||
[Throws, Func="Navigator::HasUserMediaSupport"]
|
||||
void mozGetUserMedia(MediaStreamConstraints constraints,
|
||||
NavigatorUserMediaSuccessCallback successCallback,
|
||||
|
|
|
@ -255,6 +255,7 @@ WEBIDL_FILES = [
|
|||
'ListBoxObject.webidl',
|
||||
'LocalMediaStream.webidl',
|
||||
'Location.webidl',
|
||||
'MediaDevices.webidl',
|
||||
'MediaElementAudioSourceNode.webidl',
|
||||
'MediaError.webidl',
|
||||
'MediaList.webidl',
|
||||
|
@ -264,6 +265,7 @@ WEBIDL_FILES = [
|
|||
'MediaStream.webidl',
|
||||
'MediaStreamAudioDestinationNode.webidl',
|
||||
'MediaStreamAudioSourceNode.webidl',
|
||||
'MediaStreamError.webidl',
|
||||
'MediaStreamTrack.webidl',
|
||||
'MediaTrackConstraintSet.webidl',
|
||||
'MenuBoxObject.webidl',
|
||||
|
|
|
@ -45,6 +45,52 @@ class AutoRestoreTransform
|
|||
Matrix mOldTransform;
|
||||
};
|
||||
|
||||
class AutoPopClips
|
||||
{
|
||||
public:
|
||||
explicit AutoPopClips(DrawTarget *aTarget)
|
||||
: mDrawTarget(aTarget)
|
||||
, mPushCount(0)
|
||||
{
|
||||
MOZ_ASSERT(mDrawTarget);
|
||||
}
|
||||
|
||||
~AutoPopClips()
|
||||
{
|
||||
PopAll();
|
||||
}
|
||||
|
||||
void PushClip(const Path *aPath)
|
||||
{
|
||||
mDrawTarget->PushClip(aPath);
|
||||
++mPushCount;
|
||||
}
|
||||
|
||||
void PushClipRect(const Rect &aRect)
|
||||
{
|
||||
mDrawTarget->PushClipRect(aRect);
|
||||
++mPushCount;
|
||||
}
|
||||
|
||||
void PopClip()
|
||||
{
|
||||
MOZ_ASSERT(mPushCount > 0);
|
||||
mDrawTarget->PopClip();
|
||||
--mPushCount;
|
||||
}
|
||||
|
||||
void PopAll()
|
||||
{
|
||||
while (mPushCount-- > 0) {
|
||||
mDrawTarget->PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<DrawTarget> mDrawTarget;
|
||||
int32_t mPushCount;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <math.h>
|
||||
#include "DrawTargetCG.h"
|
||||
#include "Logging.h"
|
||||
#include "PathHelpers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -68,6 +69,10 @@ void
|
|||
PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
||||
Float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
// Disabled for now due to a CG bug when using CGPathAddArc with stroke
|
||||
// dashing and rotation transforms that are multiples of 90 degrees. See:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=949661#c8
|
||||
#if 0
|
||||
// Core Graphic's initial coordinate system is y-axis up, whereas Moz2D's is
|
||||
// y-axis down. Core Graphics therefore considers "clockwise" to mean "sweep
|
||||
// in the direction of decreasing angle" whereas Moz2D considers it to mean
|
||||
|
@ -82,6 +87,9 @@ PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
|||
aStartAngle,
|
||||
aEndAngle,
|
||||
aAntiClockwise);
|
||||
#endif
|
||||
ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
|
||||
aAntiClockwise);
|
||||
}
|
||||
|
||||
Point
|
||||
|
|
|
@ -14,7 +14,6 @@ TransGaming Inc.
|
|||
Adobe Systems Inc.
|
||||
Autodesk, Inc.
|
||||
BlackBerry Limited
|
||||
Borbitsoft
|
||||
Cable Television Laboratories, Inc.
|
||||
Cloud Party, Inc.
|
||||
Intel Corporation
|
||||
|
@ -22,10 +21,12 @@ Mozilla Corporation
|
|||
Turbulenz
|
||||
Klarälvdalens Datakonsult AB
|
||||
Microsoft Open Technologies, Inc.
|
||||
NVIDIA Corporation
|
||||
|
||||
Jacek Caban
|
||||
Mark Callow
|
||||
Ginn Chen
|
||||
Tibor den Ouden
|
||||
James Hauxwell
|
||||
Sam Hocevar
|
||||
Pierre Leveille
|
||||
|
|
|
@ -49,9 +49,6 @@ Adobe Systems Inc.
|
|||
Autodesk, Inc.
|
||||
Ranger Harke
|
||||
|
||||
Borbitsoft
|
||||
Tibor den Ouden
|
||||
|
||||
Cloud Party, Inc.
|
||||
Conor Dickinson
|
||||
|
||||
|
@ -82,7 +79,11 @@ Ulrik Persson (ddefrostt)
|
|||
Mark Banner (standard8mbp)
|
||||
David Kilzer
|
||||
Jacek Caban
|
||||
Tibor den Ouden
|
||||
|
||||
Microsoft Open Technologies, Inc.
|
||||
Cooper Partin
|
||||
Austin Kinross
|
||||
|
||||
NVIDIA Corporation
|
||||
Olli Etuaho
|
||||
|
|
|
@ -246,6 +246,12 @@ typedef struct
|
|||
int EXT_frag_depth;
|
||||
int EXT_shader_texture_lod;
|
||||
|
||||
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
|
||||
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
|
||||
// EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
|
||||
// function. This applies to Tegra K1 devices.
|
||||
int NV_draw_buffers;
|
||||
|
||||
// Set to 1 if highp precision is supported in the fragment language.
|
||||
// Default is 0.
|
||||
int FragmentPrecisionHigh;
|
||||
|
|
|
@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable
|
|||
unsigned int elementCount() const { return std::max(1u, arraySize); }
|
||||
bool isStruct() const { return !fields.empty(); }
|
||||
|
||||
// All of the shader's variables are described using nested data
|
||||
// structures. This is needed in order to disambiguate similar looking
|
||||
// types, such as two structs containing the same fields, but in
|
||||
// different orders. "findInfoByMappedName" provides an easy query for
|
||||
// users to dive into the data structure and fetch the unique variable
|
||||
// instance corresponding to a dereferencing chain of the top-level
|
||||
// variable.
|
||||
// Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
|
||||
// that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
|
||||
// in |originalName|, based on the assumption that |this| defines 'a'.
|
||||
// If no match is found, return false.
|
||||
bool findInfoByMappedName(const std::string &mappedFullName,
|
||||
const ShaderVariable **leafVar,
|
||||
std::string* originalFullName) const;
|
||||
|
||||
GLenum type;
|
||||
GLenum precision;
|
||||
std::string name;
|
||||
|
@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable
|
|||
bool staticUse;
|
||||
std::vector<ShaderVariable> fields;
|
||||
std::string structName;
|
||||
|
||||
protected:
|
||||
bool isSameVariableAtLinkTime(const ShaderVariable &other,
|
||||
bool matchPrecision) const;
|
||||
|
||||
bool operator==(const ShaderVariable &other) const;
|
||||
bool operator!=(const ShaderVariable &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
struct COMPILER_EXPORT Uniform : public ShaderVariable
|
||||
|
@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
|
|||
~Uniform();
|
||||
Uniform(const Uniform &other);
|
||||
Uniform &operator=(const Uniform &other);
|
||||
bool operator==(const Uniform &other) const;
|
||||
bool operator!=(const Uniform &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// Decide whether two uniforms are the same at shader link time,
|
||||
// assuming one from vertex shader and the other from fragment shader.
|
||||
// See GLSL ES Spec 3.00.3, sec 4.3.5.
|
||||
bool isSameUniformAtLinkTime(const Uniform &other) const;
|
||||
};
|
||||
|
||||
struct COMPILER_EXPORT Attribute : public ShaderVariable
|
||||
|
@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable
|
|||
~Attribute();
|
||||
Attribute(const Attribute &other);
|
||||
Attribute &operator=(const Attribute &other);
|
||||
bool operator==(const Attribute &other) const;
|
||||
bool operator!=(const Attribute &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
int location;
|
||||
};
|
||||
|
@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
|
|||
~InterfaceBlockField();
|
||||
InterfaceBlockField(const InterfaceBlockField &other);
|
||||
InterfaceBlockField &operator=(const InterfaceBlockField &other);
|
||||
bool operator==(const InterfaceBlockField &other) const;
|
||||
bool operator!=(const InterfaceBlockField &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// Decide whether two InterfaceBlock fields are the same at shader
|
||||
// link time, assuming one from vertex shader and the other from
|
||||
// fragment shader.
|
||||
// See GLSL ES Spec 3.00.3, sec 4.3.7.
|
||||
bool isSameInterfaceBlockFieldAtLinkTime(
|
||||
const InterfaceBlockField &other) const;
|
||||
|
||||
bool isRowMajorLayout;
|
||||
};
|
||||
|
@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
|
|||
{
|
||||
Varying();
|
||||
~Varying();
|
||||
Varying(const Varying &other);
|
||||
Varying(const Varying &otherg);
|
||||
Varying &operator=(const Varying &other);
|
||||
bool operator==(const Varying &other) const;
|
||||
bool operator!=(const Varying &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// Decide whether two varyings are the same at shader link time,
|
||||
// assuming one from vertex shader and the other from fragment shader.
|
||||
// See GLSL ES Spec 3.00.3, sec 4.3.9.
|
||||
bool isSameVaryingAtLinkTime(const Varying &other) const;
|
||||
|
||||
InterpolationType interpolation;
|
||||
bool isInvariant;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define ANGLE_COMMIT_HASH "7a2ba5a15abc"
|
||||
#define ANGLE_COMMIT_HASH "f0cacb827771"
|
||||
#define ANGLE_COMMIT_HASH_SIZE 12
|
||||
#define ANGLE_COMMIT_DATE "2014-10-25 15:19:56 -0400"
|
||||
#define ANGLE_COMMIT_DATE "2014-10-28 23:00:12 -0400"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "common/angleutils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
std::string FormatString(const char *fmt, va_list vararg)
|
||||
|
|
|
@ -360,7 +360,8 @@ void TCompiler::setResourceString()
|
|||
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
|
||||
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
|
||||
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
|
||||
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset;
|
||||
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
|
||||
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
|
||||
|
||||
builtInResourcesString = strstream.str();
|
||||
}
|
||||
|
|
|
@ -201,6 +201,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
|
|||
resources->EXT_frag_depth = 0;
|
||||
resources->EXT_shader_texture_lod = 0;
|
||||
|
||||
resources->NV_draw_buffers = 0;
|
||||
|
||||
// Disable highp precision in fragment shader by default.
|
||||
resources->FragmentPrecisionHigh = 0;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <GLSLANG/ShaderLang.h>
|
||||
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
|
||||
namespace sh
|
||||
{
|
||||
|
||||
|
@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool ShaderVariable::operator==(const ShaderVariable &other) const
|
||||
{
|
||||
if (type != other.type ||
|
||||
precision != other.precision ||
|
||||
name != other.name ||
|
||||
mappedName != other.mappedName ||
|
||||
arraySize != other.arraySize ||
|
||||
staticUse != other.staticUse ||
|
||||
fields.size() != other.fields.size() ||
|
||||
structName != other.structName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t ii = 0; ii < fields.size(); ++ii)
|
||||
{
|
||||
if (fields[ii] != other.fields[ii])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderVariable::findInfoByMappedName(
|
||||
const std::string &mappedFullName,
|
||||
const ShaderVariable **leafVar, std::string *originalFullName) const
|
||||
{
|
||||
ASSERT(leafVar && originalFullName);
|
||||
// There are three cases:
|
||||
// 1) the top variable is of struct type;
|
||||
// 2) the top variable is an array;
|
||||
// 3) otherwise.
|
||||
size_t pos = mappedFullName.find_first_of(".[");
|
||||
std::string topName;
|
||||
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
// Case 3.
|
||||
if (mappedFullName != this->mappedName)
|
||||
return false;
|
||||
*originalFullName = this->name;
|
||||
*leafVar = this;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string topName = mappedFullName.substr(0, pos);
|
||||
if (topName != this->mappedName)
|
||||
return false;
|
||||
std::string originalName = this->name;
|
||||
std::string remaining;
|
||||
if (mappedFullName[pos] == '[')
|
||||
{
|
||||
// Case 2.
|
||||
size_t closePos = mappedFullName.find_first_of(']');
|
||||
if (closePos < pos || closePos == std::string::npos)
|
||||
return false;
|
||||
// Append '[index]'.
|
||||
originalName += mappedFullName.substr(pos, closePos - pos + 1);
|
||||
if (closePos + 1 == mappedFullName.size())
|
||||
{
|
||||
*originalFullName = originalName;
|
||||
*leafVar = this;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In the form of 'a[0].b', so after ']', '.' is expected.
|
||||
if (mappedFullName[closePos + 1] != '.')
|
||||
return false;
|
||||
remaining = mappedFullName.substr(closePos + 2); // Skip "]."
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 1.
|
||||
remaining = mappedFullName.substr(pos + 1); // Skip "."
|
||||
}
|
||||
for (size_t ii = 0; ii < this->fields.size(); ++ii)
|
||||
{
|
||||
const ShaderVariable *fieldVar = NULL;
|
||||
std::string originalFieldName;
|
||||
bool found = fields[ii].findInfoByMappedName(
|
||||
remaining, &fieldVar, &originalFieldName);
|
||||
if (found)
|
||||
{
|
||||
*originalFullName = originalName + "." + originalFieldName;
|
||||
*leafVar = fieldVar;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderVariable::isSameVariableAtLinkTime(
|
||||
const ShaderVariable &other, bool matchPrecision) const
|
||||
{
|
||||
if (type != other.type)
|
||||
return false;
|
||||
if (matchPrecision && precision != other.precision)
|
||||
return false;
|
||||
if (name != other.name)
|
||||
return false;
|
||||
ASSERT(mappedName == other.mappedName);
|
||||
if (arraySize != other.arraySize)
|
||||
return false;
|
||||
if (fields.size() != other.fields.size())
|
||||
return false;
|
||||
for (size_t ii = 0; ii < fields.size(); ++ii)
|
||||
{
|
||||
if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
|
||||
matchPrecision))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (structName != other.structName)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Uniform::Uniform()
|
||||
{}
|
||||
|
||||
|
@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool Uniform::operator==(const Uniform &other) const
|
||||
{
|
||||
return ShaderVariable::operator==(other);
|
||||
}
|
||||
|
||||
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
|
||||
{
|
||||
return ShaderVariable::isSameVariableAtLinkTime(other, true);
|
||||
}
|
||||
|
||||
Attribute::Attribute()
|
||||
: location(-1)
|
||||
{}
|
||||
|
@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool Attribute::operator==(const Attribute &other) const
|
||||
{
|
||||
return (ShaderVariable::operator==(other) &&
|
||||
location == other.location);
|
||||
}
|
||||
|
||||
InterfaceBlockField::InterfaceBlockField()
|
||||
: isRowMajorLayout(false)
|
||||
{}
|
||||
|
@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
|
||||
{
|
||||
return (ShaderVariable::operator==(other) &&
|
||||
isRowMajorLayout == other.isRowMajorLayout);
|
||||
}
|
||||
|
||||
bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
|
||||
const InterfaceBlockField &other) const
|
||||
{
|
||||
return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
|
||||
isRowMajorLayout == other.isRowMajorLayout);
|
||||
}
|
||||
|
||||
Varying::Varying()
|
||||
: interpolation(INTERPOLATION_SMOOTH),
|
||||
isInvariant(false)
|
||||
|
@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool Varying::operator==(const Varying &other) const
|
||||
{
|
||||
return (ShaderVariable::operator==(other) &&
|
||||
interpolation == other.interpolation &&
|
||||
isInvariant == other.isInvariant);
|
||||
}
|
||||
|
||||
bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
|
||||
{
|
||||
return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
|
||||
interpolation == other.interpolation &&
|
||||
isInvariant == other.isInvariant);
|
||||
}
|
||||
|
||||
InterfaceBlock::InterfaceBlock()
|
||||
: arraySize(0),
|
||||
layout(BLOCKLAYOUT_PACKED),
|
||||
|
|
|
@ -37,8 +37,13 @@ void TranslatorESSL::writeExtensionBehavior() {
|
|||
for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
|
||||
iter != extensionBehavior.end(); ++iter) {
|
||||
if (iter->second != EBhUndefined) {
|
||||
if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
|
||||
sink << "#extension GL_NV_draw_buffers : "
|
||||
<< getBehaviorString(iter->second) << "\n";
|
||||
} else {
|
||||
sink << "#extension " << iter->first << " : "
|
||||
<< getBehaviorString(iter->second) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,13 +91,13 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
|
|||
bindRenderbuffer(0);
|
||||
|
||||
bindGenericUniformBuffer(0);
|
||||
for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
|
||||
for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++)
|
||||
{
|
||||
bindIndexedUniformBuffer(0, i, 0, -1);
|
||||
}
|
||||
|
||||
bindGenericTransformFeedbackBuffer(0);
|
||||
for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
|
||||
for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++)
|
||||
{
|
||||
bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
|
||||
}
|
||||
|
@ -119,8 +119,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
|
|||
mResetStatus = GL_NO_ERROR;
|
||||
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
|
||||
mRobustAccess = robustAccess;
|
||||
|
||||
mState.setContext(this);
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
|
@ -640,33 +638,44 @@ void Context::useProgram(GLuint program)
|
|||
}
|
||||
}
|
||||
|
||||
void Context::linkProgram(GLuint program)
|
||||
Error Context::linkProgram(GLuint program)
|
||||
{
|
||||
Program *programObject = mResourceManager->getProgram(program);
|
||||
|
||||
bool linked = programObject->link(getCaps());
|
||||
Error error = programObject->link(getCaps());
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// if the current program was relinked successfully we
|
||||
// need to install the new executables
|
||||
if (linked && program == mState.getCurrentProgramId())
|
||||
if (programObject->isLinked() && program == mState.getCurrentProgramId())
|
||||
{
|
||||
mState.setCurrentProgramBinary(programObject->getProgramBinary());
|
||||
}
|
||||
|
||||
return Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
|
||||
Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
|
||||
{
|
||||
Program *programObject = mResourceManager->getProgram(program);
|
||||
|
||||
bool loaded = programObject->setProgramBinary(binaryFormat, binary, length);
|
||||
Error error = programObject->setProgramBinary(binaryFormat, binary, length);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// if the current program was reloaded successfully we
|
||||
// need to install the new executables
|
||||
if (loaded && program == mState.getCurrentProgramId())
|
||||
if (programObject->isLinked() && program == mState.getCurrentProgramId())
|
||||
{
|
||||
mState.setCurrentProgramBinary(programObject->getProgramBinary());
|
||||
}
|
||||
|
||||
return Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void Context::bindTransformFeedback(GLuint transformFeedback)
|
||||
|
@ -1398,10 +1407,8 @@ Error Context::applyState(GLenum drawMode)
|
|||
// Applies the shaders and shader constants to the Direct3D 9 device
|
||||
Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
|
||||
{
|
||||
const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes();
|
||||
|
||||
VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
|
||||
VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues());
|
||||
VertexFormat::GetInputLayout(inputLayout, programBinary, mState);
|
||||
|
||||
const Framebuffer *fbo = mState.getDrawFramebuffer();
|
||||
|
||||
|
@ -1584,14 +1591,7 @@ bool Context::applyTransformFeedbackBuffers()
|
|||
TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback();
|
||||
if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
|
||||
{
|
||||
Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
|
||||
GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
|
||||
for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
|
||||
{
|
||||
transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i);
|
||||
transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i);
|
||||
}
|
||||
mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets);
|
||||
mRenderer->applyTransformFeedbackBuffers(mState);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -1602,7 +1602,7 @@ bool Context::applyTransformFeedbackBuffers()
|
|||
|
||||
void Context::markTransformFeedbackUsage()
|
||||
{
|
||||
for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
|
||||
for (size_t i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++)
|
||||
{
|
||||
Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i);
|
||||
if (buffer)
|
||||
|
@ -1771,7 +1771,7 @@ Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei insta
|
|||
return error;
|
||||
}
|
||||
|
||||
error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances);
|
||||
error = mRenderer->applyVertexBuffer(mState, first, count, instances);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
|
@ -1856,9 +1856,7 @@ Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
|
|||
}
|
||||
|
||||
GLsizei vertexCount = indexInfo.indexRange.length() + 1;
|
||||
error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(),
|
||||
mState.getVertexAttribCurrentValues(),
|
||||
indexInfo.indexRange.start, vertexCount, instances);
|
||||
error = mRenderer->applyVertexBuffer(mState, indexInfo.indexRange.start, vertexCount, instances);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
|
|
|
@ -130,8 +130,8 @@ class Context
|
|||
void bindPixelPackBuffer(GLuint buffer);
|
||||
void bindPixelUnpackBuffer(GLuint buffer);
|
||||
void useProgram(GLuint program);
|
||||
void linkProgram(GLuint program);
|
||||
void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
|
||||
Error linkProgram(GLuint program);
|
||||
Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
|
||||
void bindTransformFeedback(GLuint transformFeedback);
|
||||
|
||||
Error beginQuery(GLenum target, GLuint query);
|
||||
|
|
|
@ -48,6 +48,11 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
|
|||
return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
|
||||
}
|
||||
|
||||
ImageIndex ImageIndex::MakeInvalid()
|
||||
{
|
||||
return ImageIndex(GL_NONE, -1, -1);
|
||||
}
|
||||
|
||||
ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
|
||||
: type(typeIn),
|
||||
mipIndex(mipIndexIn),
|
||||
|
|
|
@ -31,6 +31,7 @@ struct ImageIndex
|
|||
static ImageIndex MakeCube(GLenum target, GLint mipIndex);
|
||||
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
|
||||
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
|
||||
static ImageIndex MakeInvalid();
|
||||
|
||||
static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
|
||||
};
|
||||
|
|
|
@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name)
|
|||
// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
|
||||
// compiling them into binaries, determining the attribute mappings, and collecting
|
||||
// a list of uniforms
|
||||
bool Program::link(const Caps &caps)
|
||||
Error Program::link(const Caps &caps)
|
||||
{
|
||||
unlink(false);
|
||||
|
||||
|
@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
|
|||
resetUniformBlockBindings();
|
||||
|
||||
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
|
||||
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
|
||||
LinkResult result = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
|
||||
mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
|
||||
if (result.error.isError())
|
||||
{
|
||||
return result.error;
|
||||
}
|
||||
|
||||
return mLinked;
|
||||
mLinked = result.linkSuccess;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
int AttributeBindings::getAttributeBinding(const std::string &name) const
|
||||
|
@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
|
|||
return mProgramBinary.get();
|
||||
}
|
||||
|
||||
bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
|
||||
Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
|
||||
{
|
||||
unlink(false);
|
||||
|
||||
mInfoLog.reset();
|
||||
|
||||
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
|
||||
mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
|
||||
|
||||
if (!mLinked)
|
||||
LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
|
||||
if (result.error.isError())
|
||||
{
|
||||
mProgramBinary.set(NULL);
|
||||
return result.error;
|
||||
}
|
||||
|
||||
return mLinked;
|
||||
mLinked = result.linkSuccess;
|
||||
return Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void Program::release()
|
||||
|
|
|
@ -77,9 +77,9 @@ class Program
|
|||
|
||||
void bindAttributeLocation(GLuint index, const char *name);
|
||||
|
||||
bool link(const Caps &caps);
|
||||
Error link(const Caps &caps);
|
||||
bool isLinked();
|
||||
bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
ProgramBinary *getProgramBinary() const;
|
||||
|
||||
int getInfoLogLength() const;
|
||||
|
|
|
@ -107,6 +107,12 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size,
|
|||
{
|
||||
}
|
||||
|
||||
LinkResult::LinkResult(bool linkSuccess, const Error &error)
|
||||
: linkSuccess(linkSuccess),
|
||||
error(error)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int ProgramBinary::mCurrentSerial = 1;
|
||||
|
||||
ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
|
||||
|
@ -854,10 +860,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
|
||||
LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
|
||||
{
|
||||
#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
#else
|
||||
ASSERT(binaryFormat == mProgram->getBinaryFormat());
|
||||
|
||||
|
@ -869,7 +875,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (format != mProgram->getBinaryFormat())
|
||||
{
|
||||
infoLog.append("Invalid program binary format.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
int majorVersion = stream.readInt<int>();
|
||||
|
@ -877,7 +883,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
|
||||
{
|
||||
infoLog.append("Invalid program binary version.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
|
||||
|
@ -885,14 +891,14 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
|
||||
{
|
||||
infoLog.append("Invalid program binary version.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
int compileFlags = stream.readInt<int>();
|
||||
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
|
||||
{
|
||||
infoLog.append("Mismatched compilation flags.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
|
||||
|
@ -932,7 +938,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (stream.error())
|
||||
{
|
||||
infoLog.append("Invalid program binary.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
mUniforms.resize(uniformCount);
|
||||
|
@ -965,7 +971,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (stream.error())
|
||||
{
|
||||
infoLog.append("Invalid program binary.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
mUniformBlocks.resize(uniformBlockCount);
|
||||
|
@ -994,7 +1000,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
if (stream.error())
|
||||
{
|
||||
infoLog.append("Invalid program binary.");
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
mUniformIndex.resize(uniformIndexCount);
|
||||
|
@ -1005,18 +1011,19 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
|
|||
stream.readInt(&mUniformIndex[uniformIndexIndex].index);
|
||||
}
|
||||
|
||||
if (!mProgram->load(infoLog, &stream))
|
||||
LinkResult result = mProgram->load(infoLog, &stream);
|
||||
if (result.error.isError() || !result.linkSuccess)
|
||||
{
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
mProgram->initializeUniformStorage(mUniforms);
|
||||
|
||||
return true;
|
||||
return LinkResult(true, Error(GL_NO_ERROR));
|
||||
#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
|
||||
}
|
||||
|
||||
bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
|
||||
Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
|
||||
{
|
||||
if (binaryFormat)
|
||||
{
|
||||
|
@ -1108,15 +1115,7 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
|
|||
stream.writeInt(mUniformIndex[i].index);
|
||||
}
|
||||
|
||||
if (!mProgram->save(&stream))
|
||||
{
|
||||
if (length)
|
||||
{
|
||||
*length = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
mProgram->save(&stream);
|
||||
|
||||
GLsizei streamLength = stream.length();
|
||||
const void *streamData = stream.data();
|
||||
|
@ -1128,7 +1127,10 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
|
|||
*length = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
// TODO: This should be moved to the validation layer but computing the size of the binary before saving
|
||||
// it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate
|
||||
// sizes and then copy it.
|
||||
return Error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
if (binary)
|
||||
|
@ -1146,34 +1148,33 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
|
|||
*length = streamLength;
|
||||
}
|
||||
|
||||
return true;
|
||||
return Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
GLint ProgramBinary::getLength()
|
||||
{
|
||||
GLint length;
|
||||
if (save(NULL, NULL, INT_MAX, &length))
|
||||
{
|
||||
return length;
|
||||
}
|
||||
else
|
||||
Error error = save(NULL, NULL, INT_MAX, &length);
|
||||
if (error.isError())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
|
||||
LinkResult ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
|
||||
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
|
||||
{
|
||||
if (!fragmentShader || !fragmentShader->isCompiled())
|
||||
{
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
|
||||
|
||||
if (!vertexShader || !vertexShader->isCompiled())
|
||||
{
|
||||
return false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
|
||||
|
||||
|
@ -1187,22 +1188,21 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
|
|||
|
||||
int registers;
|
||||
std::vector<LinkedVarying> linkedVaryings;
|
||||
if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
|
||||
®isters, &linkedVaryings, &mOutputVariables, caps))
|
||||
LinkResult result = mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
|
||||
®isters, &linkedVaryings, &mOutputVariables, caps);
|
||||
if (result.error.isError() || !result.linkSuccess)
|
||||
{
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (!linkAttributes(infoLog, attributeBindings, vertexShader))
|
||||
{
|
||||
success = false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
|
||||
{
|
||||
success = false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
// special case for gl_DepthRange, the only built-in uniform (also a struct)
|
||||
|
@ -1217,28 +1217,26 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
|
|||
|
||||
if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
|
||||
{
|
||||
success = false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
|
||||
transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), caps))
|
||||
{
|
||||
success = false;
|
||||
return LinkResult(false, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
|
||||
// however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
|
||||
if (!mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers))
|
||||
result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
|
||||
if (result.error.isError() || !result.linkSuccess)
|
||||
{
|
||||
infoLog.append("Failed to create D3D shaders.");
|
||||
success = false;
|
||||
reset();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return success;
|
||||
return LinkResult(true, Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
|
||||
|
|
|
@ -86,6 +86,14 @@ struct LinkedVarying
|
|||
unsigned int semanticIndexCount;
|
||||
};
|
||||
|
||||
struct LinkResult
|
||||
{
|
||||
bool linkSuccess;
|
||||
Error error;
|
||||
|
||||
LinkResult(bool linkSuccess, const Error &error);
|
||||
};
|
||||
|
||||
// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
|
||||
class ProgramBinary : public RefCountObject
|
||||
{
|
||||
|
@ -138,12 +146,13 @@ class ProgramBinary : public RefCountObject
|
|||
Error applyUniforms();
|
||||
Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
|
||||
|
||||
bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
|
||||
LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
|
||||
GLint getLength();
|
||||
|
||||
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
|
||||
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
|
||||
LinkResult link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
|
||||
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
|
||||
const Caps &caps);
|
||||
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
|
||||
|
||||
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace gl
|
|||
|
||||
State::State()
|
||||
{
|
||||
mMaxDrawBuffers = 0;
|
||||
mMaxCombinedTextureImageUnits = 0;
|
||||
}
|
||||
|
||||
State::~State()
|
||||
|
@ -31,7 +33,8 @@ State::~State()
|
|||
|
||||
void State::initialize(const Caps& caps, GLuint clientVersion)
|
||||
{
|
||||
mContext = NULL;
|
||||
mMaxDrawBuffers = caps.maxDrawBuffers;
|
||||
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
|
||||
|
||||
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
|
@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
|
|||
mActiveSampler = 0;
|
||||
|
||||
const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
|
||||
mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
|
||||
for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex)
|
||||
{
|
||||
mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
|
||||
}
|
||||
|
||||
mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
|
||||
mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
|
||||
|
||||
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
|
||||
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
|
||||
if (clientVersion >= 3)
|
||||
|
@ -153,12 +160,6 @@ void State::reset()
|
|||
mSamplers[samplerIdx].set(NULL);
|
||||
}
|
||||
|
||||
const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
|
||||
{
|
||||
mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
|
||||
}
|
||||
|
||||
mArrayBuffer.set(NULL);
|
||||
mRenderbuffer.set(NULL);
|
||||
|
||||
|
@ -170,15 +171,15 @@ void State::reset()
|
|||
}
|
||||
|
||||
mGenericUniformBuffer.set(NULL);
|
||||
for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
|
||||
mGenericTransformFeedbackBuffer.set(NULL);
|
||||
for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
|
||||
{
|
||||
mUniformBuffers[i].set(NULL);
|
||||
bufItr->set(NULL);
|
||||
}
|
||||
|
||||
mGenericTransformFeedbackBuffer.set(NULL);
|
||||
for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
|
||||
for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
|
||||
{
|
||||
mTransformFeedbackBuffers[i].set(NULL);
|
||||
bufItr->set(NULL);
|
||||
}
|
||||
|
||||
mCopyReadBuffer.set(NULL);
|
||||
|
@ -947,14 +948,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt
|
|||
|
||||
GLuint State::getIndexedUniformBufferId(GLuint index) const
|
||||
{
|
||||
ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
|
||||
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
|
||||
|
||||
return mUniformBuffers[index].id();
|
||||
}
|
||||
|
||||
Buffer *State::getIndexedUniformBuffer(GLuint index) const
|
||||
{
|
||||
ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
|
||||
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
|
||||
|
||||
return mUniformBuffers[index].get();
|
||||
}
|
||||
|
@ -971,25 +972,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe
|
|||
|
||||
GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const
|
||||
{
|
||||
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
|
||||
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
|
||||
|
||||
return mTransformFeedbackBuffers[index].id();
|
||||
}
|
||||
|
||||
Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const
|
||||
{
|
||||
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
|
||||
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
|
||||
|
||||
return mTransformFeedbackBuffers[index].get();
|
||||
}
|
||||
|
||||
GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const
|
||||
{
|
||||
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
|
||||
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
|
||||
|
||||
return mTransformFeedbackBuffers[index].getOffset();
|
||||
}
|
||||
|
||||
size_t State::getTransformFeedbackBufferIndexRange() const
|
||||
{
|
||||
return mTransformFeedbackBuffers.size();
|
||||
}
|
||||
|
||||
void State::setCopyReadBufferBinding(Buffer *buffer)
|
||||
{
|
||||
mCopyReadBuffer.set(buffer);
|
||||
|
@ -1033,19 +1039,19 @@ void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
|
|||
|
||||
void State::setVertexAttribf(GLuint index, const GLfloat values[4])
|
||||
{
|
||||
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
|
||||
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
|
||||
mVertexAttribCurrentValues[index].setFloatValues(values);
|
||||
}
|
||||
|
||||
void State::setVertexAttribu(GLuint index, const GLuint values[4])
|
||||
{
|
||||
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
|
||||
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
|
||||
mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
|
||||
}
|
||||
|
||||
void State::setVertexAttribi(GLuint index, const GLint values[4])
|
||||
{
|
||||
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
|
||||
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
|
||||
mVertexAttribCurrentValues[index].setIntValues(values);
|
||||
}
|
||||
|
||||
|
@ -1062,15 +1068,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
|
|||
|
||||
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
|
||||
{
|
||||
ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
|
||||
ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
|
||||
return mVertexAttribCurrentValues[attribNum];
|
||||
}
|
||||
|
||||
const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const
|
||||
{
|
||||
return mVertexAttribCurrentValues;
|
||||
}
|
||||
|
||||
const void *State::getVertexAttribPointer(unsigned int attribNum) const
|
||||
{
|
||||
return getVertexArray()->getVertexAttribute(attribNum).pointer;
|
||||
|
@ -1185,7 +1186,7 @@ void State::getIntegerv(GLenum pname, GLint *params)
|
|||
if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
|
||||
{
|
||||
unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
|
||||
ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers);
|
||||
ASSERT(colorAttachment < mMaxDrawBuffers);
|
||||
Framebuffer *framebuffer = mDrawFramebuffer;
|
||||
*params = framebuffer->getDrawBufferState(colorAttachment);
|
||||
return;
|
||||
|
@ -1332,19 +1333,19 @@ void State::getIntegerv(GLenum pname, GLint *params)
|
|||
}
|
||||
break;
|
||||
case GL_TEXTURE_BINDING_2D:
|
||||
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
|
||||
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
|
||||
*params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
|
||||
break;
|
||||
case GL_TEXTURE_BINDING_CUBE_MAP:
|
||||
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
|
||||
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
|
||||
*params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
|
||||
break;
|
||||
case GL_TEXTURE_BINDING_3D:
|
||||
ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits);
|
||||
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
|
||||
*params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
|
||||
break;
|
||||
case GL_TEXTURE_BINDING_2D_ARRAY:
|
||||
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
|
||||
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
|
||||
*params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
|
||||
break;
|
||||
case GL_UNIFORM_BUFFER_BINDING:
|
||||
|
@ -1376,13 +1377,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
|
|||
switch (target)
|
||||
{
|
||||
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
||||
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
|
||||
{
|
||||
*data = mTransformFeedbackBuffers[index].id();
|
||||
}
|
||||
break;
|
||||
case GL_UNIFORM_BUFFER_BINDING:
|
||||
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mUniformBuffers.size())
|
||||
{
|
||||
*data = mUniformBuffers[index].id();
|
||||
}
|
||||
|
@ -1399,25 +1400,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
|
|||
switch (target)
|
||||
{
|
||||
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
|
||||
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
|
||||
{
|
||||
*data = mTransformFeedbackBuffers[index].getOffset();
|
||||
}
|
||||
break;
|
||||
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
|
||||
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
|
||||
{
|
||||
*data = mTransformFeedbackBuffers[index].getSize();
|
||||
}
|
||||
break;
|
||||
case GL_UNIFORM_BUFFER_START:
|
||||
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mUniformBuffers.size())
|
||||
{
|
||||
*data = mUniformBuffers[index].getOffset();
|
||||
}
|
||||
break;
|
||||
case GL_UNIFORM_BUFFER_SIZE:
|
||||
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
|
||||
if (static_cast<size_t>(index) < mUniformBuffers.size())
|
||||
{
|
||||
*data = mUniformBuffers[index].getSize();
|
||||
}
|
||||
|
@ -1433,9 +1434,9 @@ bool State::hasMappedBuffer(GLenum target) const
|
|||
{
|
||||
if (target == GL_ARRAY_BUFFER)
|
||||
{
|
||||
for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++)
|
||||
for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++)
|
||||
{
|
||||
const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex);
|
||||
const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex));
|
||||
gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
|
||||
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
|
||||
{
|
||||
|
|
|
@ -35,8 +35,6 @@ class State
|
|||
void initialize(const Caps& caps, GLuint clientVersion);
|
||||
void reset();
|
||||
|
||||
void setContext(Context *context) { mContext = context; }
|
||||
|
||||
// State chunk getters
|
||||
const RasterizerState &getRasterizerState() const;
|
||||
const BlendState &getBlendState() const;
|
||||
|
@ -199,6 +197,7 @@ class State
|
|||
GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
|
||||
Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
|
||||
GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const;
|
||||
size_t getTransformFeedbackBufferIndexRange() const;
|
||||
|
||||
// GL_COPY_[READ/WRITE]_BUFFER
|
||||
void setCopyReadBufferBinding(Buffer *buffer);
|
||||
|
@ -220,7 +219,6 @@ class State
|
|||
bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
|
||||
const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
|
||||
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
|
||||
const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const;
|
||||
const void *getVertexAttribPointer(unsigned int attribNum) const;
|
||||
|
||||
// Pixel pack state manipulation
|
||||
|
@ -247,7 +245,9 @@ class State
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(State);
|
||||
|
||||
Context *mContext;
|
||||
// Cached values from Context's caps
|
||||
GLuint mMaxDrawBuffers;
|
||||
GLuint mMaxCombinedTextureImageUnits;
|
||||
|
||||
ColorF mColorClearValue;
|
||||
GLclampf mDepthClearValue;
|
||||
|
@ -283,7 +283,8 @@ class State
|
|||
GLuint mCurrentProgramId;
|
||||
BindingPointer<ProgramBinary> mCurrentProgramBinary;
|
||||
|
||||
VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
|
||||
typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
|
||||
VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
|
||||
VertexArray *mVertexArray;
|
||||
|
||||
// Texture and sampler bindings
|
||||
|
@ -300,11 +301,12 @@ class State
|
|||
ActiveQueryMap mActiveQueries;
|
||||
|
||||
BindingPointer<Buffer> mGenericUniformBuffer;
|
||||
OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
|
||||
typedef std::vector< OffsetBindingPointer<Buffer> > BufferVector;
|
||||
BufferVector mUniformBuffers;
|
||||
|
||||
BindingPointer<TransformFeedback> mTransformFeedback;
|
||||
BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
|
||||
OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
|
||||
BufferVector mTransformFeedbackBuffers;
|
||||
|
||||
BindingPointer<Buffer> mCopyReadBuffer;
|
||||
BindingPointer<Buffer> mCopyWriteBuffer;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "libGLESv2/angletypes.h"
|
||||
#include "libGLESv2/ProgramBinary.h"
|
||||
#include "libGLESv2/VertexAttribute.h"
|
||||
#include "libGLESv2/State.h"
|
||||
#include "libGLESv2/VertexArray.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
@ -148,16 +150,16 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp
|
|||
|
||||
void VertexFormat::GetInputLayout(VertexFormat *inputLayout,
|
||||
ProgramBinary *programBinary,
|
||||
const VertexAttribute *attributes,
|
||||
const gl::VertexAttribCurrentValueData *currentValues)
|
||||
const State &state)
|
||||
{
|
||||
const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes();
|
||||
for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
|
||||
{
|
||||
int semanticIndex = programBinary->getSemanticIndex(attributeIndex);
|
||||
|
||||
if (semanticIndex != -1)
|
||||
{
|
||||
inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type);
|
||||
inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
namespace gl
|
||||
{
|
||||
class Buffer;
|
||||
class State;
|
||||
class ProgramBinary;
|
||||
struct VertexAttribute;
|
||||
struct VertexAttribCurrentValueData;
|
||||
|
@ -229,8 +230,7 @@ struct VertexFormat
|
|||
|
||||
static void GetInputLayout(VertexFormat *inputLayout,
|
||||
ProgramBinary *programBinary,
|
||||
const VertexAttribute *attributes,
|
||||
const gl::VertexAttribCurrentValueData *currentValues);
|
||||
const State& currentValues);
|
||||
|
||||
bool operator==(const VertexFormat &other) const;
|
||||
bool operator!=(const VertexFormat &other) const;
|
||||
|
|
|
@ -3654,7 +3654,12 @@ void __stdcall glLinkProgram(GLuint program)
|
|||
}
|
||||
}
|
||||
|
||||
context->linkProgram(program);
|
||||
gl::Error error = context->linkProgram(program);
|
||||
if (error.isError())
|
||||
{
|
||||
context->recordError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8402,9 +8407,10 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l
|
|||
return;
|
||||
}
|
||||
|
||||
if (!programBinary->save(binaryFormat, binary, bufSize, length))
|
||||
gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length);
|
||||
if (error.isError())
|
||||
{
|
||||
context->recordError(gl::Error(GL_INVALID_OPERATION));
|
||||
context->recordError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -8433,7 +8439,12 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
|
|||
return;
|
||||
}
|
||||
|
||||
context->setProgramBinary(program, binaryFormat, binary, length);
|
||||
gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length);
|
||||
if (error.isError())
|
||||
{
|
||||
context->recordError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// surfaces or resources.
|
||||
|
||||
#include "libGLESv2/renderer/Image.h"
|
||||
#include "libGLESv2/Framebuffer.h"
|
||||
#include "libGLESv2/main.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
@ -25,4 +27,18 @@ Image::Image()
|
|||
mDirty = false;
|
||||
}
|
||||
|
||||
void Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source)
|
||||
{
|
||||
gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
|
||||
|
||||
if (!colorbuffer)
|
||||
{
|
||||
return gl::error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
RenderTarget *renderTarget = GetAttachmentRenderTarget(colorbuffer);
|
||||
ASSERT(renderTarget);
|
||||
copy(xoffset, yoffset, zoffset, area, renderTarget);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
namespace gl
|
||||
{
|
||||
class Framebuffer;
|
||||
struct Rectangle;
|
||||
struct ImageIndex;
|
||||
}
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class Renderer;
|
||||
class RenderTarget;
|
||||
class TextureStorage;
|
||||
|
||||
class Image
|
||||
{
|
||||
|
@ -51,7 +54,10 @@ class Image
|
|||
virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||
const void *input) = 0;
|
||||
|
||||
virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
|
||||
void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source);
|
||||
virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0;
|
||||
virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
|
||||
const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0;
|
||||
|
||||
protected:
|
||||
GLsizei mWidth;
|
||||
|
|
|
@ -32,13 +32,13 @@ public:
|
|||
virtual sh::Attribute *getShaderAttributes() = 0;
|
||||
|
||||
virtual GLenum getBinaryFormat() = 0;
|
||||
virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
|
||||
virtual bool save(gl::BinaryOutputStream *stream) = 0;
|
||||
virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
|
||||
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
|
||||
|
||||
virtual bool compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
int registers) = 0;
|
||||
|
||||
virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
virtual gl::LinkResult link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
|
||||
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
|
||||
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0;
|
||||
|
|
|
@ -132,10 +132,9 @@ class Renderer
|
|||
bool rasterizerDiscard, bool transformFeedbackActive) = 0;
|
||||
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
|
||||
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
|
||||
virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
|
||||
GLint first, GLsizei count, GLsizei instances) = 0;
|
||||
virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0;
|
||||
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
|
||||
virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0;
|
||||
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
|
||||
|
||||
virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
|
||||
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
|
||||
|
@ -197,12 +196,13 @@ class Renderer
|
|||
|
||||
// Shader operations
|
||||
virtual void releaseShaderCompiler() = 0;
|
||||
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
|
||||
virtual gl::Error loadExecutable(const void *function, size_t length, rx::ShaderType type,
|
||||
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
|
||||
bool separatedOutputBuffers) = 0;
|
||||
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
|
||||
bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
|
||||
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
|
||||
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
|
||||
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
|
||||
bool separatedOutputBuffers, D3DWorkaroundType workaround,
|
||||
ShaderExecutable **outExectuable) = 0;
|
||||
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
|
||||
|
||||
// Image operations
|
||||
|
|
|
@ -26,10 +26,12 @@ enum D3DWorkaroundType
|
|||
struct Workarounds
|
||||
{
|
||||
Workarounds()
|
||||
: mrtPerfWorkaround(false)
|
||||
: mrtPerfWorkaround(false),
|
||||
setDataFasterThanImageUpload(false)
|
||||
{}
|
||||
|
||||
bool mrtPerfWorkaround;
|
||||
bool setDataFasterThanImageUpload;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ void HLSLCompiler::release()
|
|||
}
|
||||
}
|
||||
|
||||
ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
|
||||
const std::vector<CompileConfig> &configs) const
|
||||
gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
|
||||
const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const
|
||||
{
|
||||
ASSERT(mD3DCompilerModule && mD3DCompileFunc);
|
||||
|
||||
|
@ -115,13 +115,15 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
|
|||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
return binary;
|
||||
*outCompiledBlob = binary;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == E_OUTOFMEMORY)
|
||||
{
|
||||
return gl::error<ID3DBlob*>(GL_OUT_OF_MEMORY, NULL);
|
||||
*outCompiledBlob = NULL;
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
|
||||
}
|
||||
|
||||
infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
|
||||
|
@ -133,7 +135,9 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
|
|||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
// None of the configurations succeeded in compiling this shader but the compiler is still intact
|
||||
*outCompiledBlob = NULL;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
|
||||
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
|
||||
|
||||
#include "libGLESv2/Error.h"
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "common/platform.h"
|
||||
|
||||
|
@ -33,8 +35,10 @@ class HLSLCompiler
|
|||
bool initialize();
|
||||
void release();
|
||||
|
||||
ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
|
||||
const std::vector<CompileConfig> &configs) const;
|
||||
// Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
|
||||
// even if no GL errors are returned.
|
||||
gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
|
||||
const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
namespace gl
|
||||
{
|
||||
class Framebuffer;
|
||||
struct ImageIndex;
|
||||
struct Box;
|
||||
}
|
||||
|
||||
namespace rx
|
||||
|
@ -37,10 +39,10 @@ class ImageD3D : public Image
|
|||
virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {};
|
||||
virtual void setManagedSurface3D(TextureStorage *storage, int level) {};
|
||||
virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {};
|
||||
virtual gl::Error copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
|
||||
virtual gl::Error copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
|
||||
virtual gl::Error copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0;
|
||||
virtual gl::Error copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0;
|
||||
virtual gl::Error copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0;
|
||||
virtual gl::Error copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0;
|
||||
virtual gl::Error copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0;
|
||||
virtual gl::Error copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ImageD3D);
|
||||
|
|
|
@ -147,7 +147,7 @@ bool ProgramD3D::usesGeometryShader() const
|
|||
return usesPointSpriteEmulation();
|
||||
}
|
||||
|
||||
bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
||||
gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
||||
{
|
||||
stream->readInt(&mShaderVersion);
|
||||
|
||||
|
@ -201,14 +201,22 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
|||
|
||||
unsigned int vertexShaderSize = stream->readInt<unsigned int>();
|
||||
const unsigned char *vertexShaderFunction = binary + stream->offset();
|
||||
ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
|
||||
|
||||
ShaderExecutable *shaderExecutable = NULL;
|
||||
gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
|
||||
SHADER_VERTEX,
|
||||
mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
&shaderExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
|
||||
if (!shaderExecutable)
|
||||
{
|
||||
infoLog.append("Could not create vertex shader.");
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
// generated converted input layout
|
||||
|
@ -233,15 +241,20 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
|||
|
||||
const size_t pixelShaderSize = stream->readInt<unsigned int>();
|
||||
const unsigned char *pixelShaderFunction = binary + stream->offset();
|
||||
ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
|
||||
SHADER_PIXEL,
|
||||
ShaderExecutable *shaderExecutable = NULL;
|
||||
gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
|
||||
mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
&shaderExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
|
||||
if (!shaderExecutable)
|
||||
{
|
||||
infoLog.append("Could not create pixel shader.");
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
// add new binary
|
||||
|
@ -255,15 +268,19 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
|||
if (geometryShaderSize > 0)
|
||||
{
|
||||
const unsigned char *geometryShaderFunction = binary + stream->offset();
|
||||
mGeometryExecutable = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
|
||||
SHADER_GEOMETRY,
|
||||
gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
|
||||
mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
&mGeometryExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
|
||||
if (!mGeometryExecutable)
|
||||
{
|
||||
infoLog.append("Could not create geometry shader.");
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
stream->skip(geometryShaderSize);
|
||||
}
|
||||
|
@ -275,13 +292,13 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
|
|||
if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
|
||||
{
|
||||
infoLog.append("Invalid program binary.");
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
return true;
|
||||
return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
bool ProgramD3D::save(gl::BinaryOutputStream *stream)
|
||||
gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
|
||||
{
|
||||
stream->writeInt(mShaderVersion);
|
||||
|
||||
|
@ -369,10 +386,10 @@ bool ProgramD3D::save(gl::BinaryOutputStream *stream)
|
|||
GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
|
||||
stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
|
||||
|
||||
return true;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
ShaderExecutable *ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo)
|
||||
gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable)
|
||||
{
|
||||
std::vector<GLenum> outputs;
|
||||
|
||||
|
@ -392,16 +409,17 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebu
|
|||
}
|
||||
}
|
||||
|
||||
return getPixelExecutableForOutputLayout(outputs);
|
||||
return getPixelExecutableForOutputLayout(outputs, outExecutable);
|
||||
}
|
||||
|
||||
ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
|
||||
gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable)
|
||||
{
|
||||
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
|
||||
{
|
||||
if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
|
||||
{
|
||||
return mPixelExecutables[executableIndex]->shaderExecutable();
|
||||
*outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,10 +428,15 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(const std::vecto
|
|||
|
||||
// Generate new pixel executable
|
||||
gl::InfoLog tempInfoLog;
|
||||
ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
|
||||
ShaderExecutable *pixelExecutable = NULL;
|
||||
gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
|
||||
mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
mPixelWorkarounds);
|
||||
mPixelWorkarounds, &pixelExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!pixelExecutable)
|
||||
{
|
||||
|
@ -426,10 +449,11 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(const std::vecto
|
|||
mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
|
||||
}
|
||||
|
||||
return pixelExecutable;
|
||||
*outExectuable = pixelExecutable;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
|
||||
gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable)
|
||||
{
|
||||
GLenum signature[gl::MAX_VERTEX_ATTRIBS];
|
||||
getInputLayoutSignature(inputLayout, signature);
|
||||
|
@ -438,7 +462,8 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::Vertex
|
|||
{
|
||||
if (mVertexExecutables[executableIndex]->matchesSignature(signature))
|
||||
{
|
||||
return mVertexExecutables[executableIndex]->shaderExecutable();
|
||||
*outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,11 +472,16 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::Vertex
|
|||
|
||||
// Generate new vertex executable
|
||||
gl::InfoLog tempInfoLog;
|
||||
ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL,
|
||||
SHADER_VERTEX,
|
||||
ShaderExecutable *vertexExecutable = NULL;
|
||||
gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
|
||||
mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
mVertexWorkarounds);
|
||||
mVertexWorkarounds, &vertexExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!vertexExecutable)
|
||||
{
|
||||
std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
|
||||
|
@ -463,10 +493,11 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::Vertex
|
|||
mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
|
||||
}
|
||||
|
||||
return vertexExecutable;
|
||||
*outExectuable = vertexExecutable;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
bool ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
int registers)
|
||||
{
|
||||
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
|
||||
|
@ -474,25 +505,40 @@ bool ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fra
|
|||
|
||||
gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
|
||||
GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
|
||||
ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
|
||||
ShaderExecutable *defaultVertexExecutable = NULL;
|
||||
gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
|
||||
std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
|
||||
ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
|
||||
ShaderExecutable *defaultPixelExecutable = NULL;
|
||||
error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
|
||||
if (usesGeometryShader())
|
||||
{
|
||||
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
|
||||
|
||||
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL,
|
||||
SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
|
||||
|
||||
error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
|
||||
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
|
||||
ANGLE_D3D_WORKAROUND_NONE);
|
||||
ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
|
||||
if (error.isError())
|
||||
{
|
||||
return gl::LinkResult(false, error);
|
||||
}
|
||||
}
|
||||
|
||||
return (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
|
||||
bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
|
||||
return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
gl::LinkResult ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
|
||||
const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
|
||||
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
|
||||
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps)
|
||||
|
@ -515,24 +561,24 @@ bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shad
|
|||
|
||||
if (*registers < 0)
|
||||
{
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
|
||||
{
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
|
||||
fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
|
||||
linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
|
||||
{
|
||||
return false;
|
||||
return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
mUsesPointSize = vertexShaderD3D->usesPointSize();
|
||||
|
||||
return true;
|
||||
return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
|
||||
}
|
||||
|
||||
void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче