Merge mozilla-central to b2g-inbound on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2014-10-29 13:42:47 +01:00
Родитель 3033fd14c8 281b258180
Коммит 348b931e1c
178 изменённых файлов: 3392 добавлений и 1634 удалений

Просмотреть файл

@ -22,7 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please # changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more. # don't change CLOBBER for WebIDL changes any more.
Updating CLOBBER for Bug 1084342 Backing out bug 1087560 needs a CLOBBER
There are some refactored files in in dom/bluetooth. Updating CLOBBER to not
leave artifacts from older builds.

Просмотреть файл

@ -43,7 +43,7 @@ function runNext() {
ok(false, 'unexpected success, permission request should be denied'); ok(false, 'unexpected success, permission request should be denied');
runNext(); runNext();
}, function failure(err) { }, function failure(err) {
is(err.toLowerCase(), 'permission denied', 'expected permission denied'); is(err.name, 'PermissionDeniedError', 'expected permission denied');
runNext(); runNext();
}); });
} else { } else {

Просмотреть файл

@ -524,6 +524,20 @@ Sanitizer.prototype = {
let features = "chrome,all,dialog=no," + this.privateStateForNewWindow; let features = "chrome,all,dialog=no," + this.privateStateForNewWindow;
let newWindow = existingWindow.openDialog("chrome://browser/content/", "_blank", let newWindow = existingWindow.openDialog("chrome://browser/content/", "_blank",
features, defaultArgs); 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 // Window creation and destruction is asynchronous. We need to wait
// until all existing windows are fully closed, and the new window is // until all existing windows are fully closed, and the new window is
@ -537,6 +551,9 @@ Sanitizer.prototype = {
return; return;
Services.obs.removeObserver(onWindowOpened, "browser-delayed-startup-finished"); Services.obs.removeObserver(onWindowOpened, "browser-delayed-startup-finished");
#ifdef XP_MACOSX
newWindow.removeEventListener("fullscreen", onFullScreen);
#endif
newWindowOpened = true; newWindowOpened = true;
// If we're the last thing to happen, invoke callback. // If we're the last thing to happen, invoke callback.
if (numWindowsClosing == 0) if (numWindowsClosing == 0)

Просмотреть файл

@ -223,6 +223,8 @@ function checkNotSharing() {
assertWebRTCIndicatorStatus(null); assertWebRTCIndicatorStatus(null);
} }
const permissionError = "error: PermissionDeniedError: The user did not grant permission for the operation.";
let gTests = [ let gTests = [
{ {
@ -381,7 +383,7 @@ let gTests = [
enableDevice("Camera", false); enableDevice("Camera", false);
enableDevice("Microphone", false); enableDevice("Microphone", false);
yield promiseMessage("error: PERMISSION_DENIED", () => { yield promiseMessage(permissionError, () => {
PopupNotifications.panel.firstChild.button.click(); PopupNotifications.panel.firstChild.button.click();
}); });
@ -405,7 +407,7 @@ let gTests = [
expectObserverCalled("getUserMedia:request"); expectObserverCalled("getUserMedia:request");
checkDeviceSelectors(true, true); checkDeviceSelectors(true, true);
yield promiseMessage("error: PERMISSION_DENIED", () => { yield promiseMessage(permissionError, () => {
activateSecondaryAction(kActionDeny); activateSecondaryAction(kActionDeny);
}); });
@ -482,7 +484,7 @@ let gTests = [
enableDevice("Camera", aAllowVideo || aNever); enableDevice("Camera", aAllowVideo || aNever);
let expectedMessage = let expectedMessage =
(aAllowVideo || aAllowAudio) ? "ok" : "error: PERMISSION_DENIED"; (aAllowVideo || aAllowAudio) ? "ok" : permissionError;
yield promiseMessage(expectedMessage, () => { yield promiseMessage(expectedMessage, () => {
activateSecondaryAction(aNever ? kActionNever : kActionAlways); activateSecondaryAction(aNever ? kActionNever : kActionAlways);
}); });
@ -587,14 +589,14 @@ let gTests = [
expectObserverCalled("getUserMedia:request"); expectObserverCalled("getUserMedia:request");
// Deny the request to cleanup... // Deny the request to cleanup...
yield promiseMessage("error: PERMISSION_DENIED", () => { yield promiseMessage(permissionError, () => {
activateSecondaryAction(kActionDeny); activateSecondaryAction(kActionDeny);
}); });
expectObserverCalled("getUserMedia:response:deny"); expectObserverCalled("getUserMedia:response:deny");
expectObserverCalled("recording-window-ended"); expectObserverCalled("recording-window-ended");
} }
else { else {
let expectedMessage = aExpectStream ? "ok" : "error: PERMISSION_DENIED"; let expectedMessage = aExpectStream ? "ok" : permissionError;
yield promiseMessage(expectedMessage, gum); yield promiseMessage(expectedMessage, gum);
if (expectedMessage == "ok") { if (expectedMessage == "ok") {

Просмотреть файл

@ -1,5 +1,5 @@
[DEFAULT] [DEFAULT]
skip-if = buildapp == "mulet" || e10s skip-if = buildapp == "mulet"
support-files = support-files =
head.js head.js
support/test_967000_charEncoding_page.html support/test_967000_charEncoding_page.html
@ -34,6 +34,7 @@ skip-if = os == "mac"
skip-if = os == "linux" skip-if = os == "linux"
[browser_901207_searchbar_in_panel.js] [browser_901207_searchbar_in_panel.js]
skip-if = e10s # bug 1090656
[browser_913972_currentset_overflow.js] [browser_913972_currentset_overflow.js]
skip-if = os == "linux" skip-if = os == "linux"
@ -54,7 +55,6 @@ skip-if = os == "mac"
skip-if = os == "linux" skip-if = os == "linux"
[browser_934951_zoom_in_toolbar.js] [browser_934951_zoom_in_toolbar.js]
skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
[browser_938980_navbar_collapsed.js] [browser_938980_navbar_collapsed.js]
[browser_938995_indefaultstate_nonremovable.js] [browser_938995_indefaultstate_nonremovable.js]
[browser_940013_registerToolbarNode_calls_registerArea.js] [browser_940013_registerToolbarNode_calls_registerArea.js]
@ -83,7 +83,7 @@ skip-if = os == "linux" # Intermittent failures
[browser_947914_button_paste.js] [browser_947914_button_paste.js]
skip-if = os == "linux" # Intermittent failures skip-if = os == "linux" # Intermittent failures
[browser_947914_button_print.js] [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] [browser_947914_button_savePage.js]
skip-if = os == "linux" # Intermittent failures skip-if = os == "linux" # Intermittent failures
[browser_947914_button_zoomIn.js] [browser_947914_button_zoomIn.js]
@ -100,11 +100,9 @@ skip-if = os == "linux" # Intermittent failures
[browser_962884_opt_in_disable_hyphens.js] [browser_962884_opt_in_disable_hyphens.js]
[browser_963639_customizing_attribute_non_customizable_toolbar.js] [browser_963639_customizing_attribute_non_customizable_toolbar.js]
[browser_967000_button_charEncoding.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] [browser_967000_button_feeds.js]
skip-if = buildapp == 'mulet' || e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
[browser_967000_button_sync.js] [browser_967000_button_sync.js]
skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
[browser_967000_button_tabView.js] [browser_967000_button_tabView.js]
[browser_968447_bookmarks_toolbar_items_in_panel.js] [browser_968447_bookmarks_toolbar_items_in_panel.js]
skip-if = os == "linux" # Intemittent failures - bug 979207 skip-if = os == "linux" # Intemittent failures - bug 979207
@ -129,6 +127,7 @@ skip-if = os == "linux"
skip-if = os == "linux" skip-if = os == "linux"
[browser_985815_propagate_setToolbarVisibility.js] [browser_985815_propagate_setToolbarVisibility.js]
skip-if = e10s # bug 1090635
[browser_981305_separator_insertion.js] [browser_981305_separator_insertion.js]
[browser_988072_sidebar_events.js] [browser_988072_sidebar_events.js]
[browser_989338_saved_placements_not_resaved.js] [browser_989338_saved_placements_not_resaved.js]
@ -138,6 +137,7 @@ skip-if = os == "linux"
[browser_987185_syncButton.js] [browser_987185_syncButton.js]
[browser_987492_window_api.js] [browser_987492_window_api.js]
[browser_987640_charEncoding.js] [browser_987640_charEncoding.js]
skip-if = e10s # Bug 1088710
[browser_992747_toggle_noncustomizable_toolbar.js] [browser_992747_toggle_noncustomizable_toolbar.js]
[browser_993322_widget_notoolbar.js] [browser_993322_widget_notoolbar.js]
[browser_995164_registerArea_during_customize_mode.js] [browser_995164_registerArea_during_customize_mode.js]

Просмотреть файл

@ -26,6 +26,37 @@ loop.shared.mixins = (function() {
rootObject = obj; 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. * Dropdown menu mixin.
* @type {Object} * @type {Object}
@ -151,6 +182,8 @@ loop.shared.mixins = (function() {
AudioMixin: AudioMixin, AudioMixin: AudioMixin,
setRootObject: setRootObject, setRootObject: setRootObject,
DropdownMenuMixin: DropdownMenuMixin, DropdownMenuMixin: DropdownMenuMixin,
DocumentVisibilityMixin: DocumentVisibilityMixin DocumentVisibilityMixin: DocumentVisibilityMixin,
DocumentLocationMixin: DocumentLocationMixin,
UrlHashChangeMixin: UrlHashChangeMixin
}; };
})(); })();

Просмотреть файл

@ -859,6 +859,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
* of the webapp page. * of the webapp page.
*/ */
var WebappRootView = React.createClass({displayName: 'WebappRootView', var WebappRootView = React.createClass({displayName: 'WebappRootView',
mixins: [sharedMixins.UrlHashChangeMixin,
sharedMixins.DocumentLocationMixin],
propTypes: { propTypes: {
client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired, client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
conversation: React.PropTypes.oneOfType([ conversation: React.PropTypes.oneOfType([
@ -879,6 +883,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
}; };
}, },
onUrlHashChange: function() {
this.locationReload();
},
render: function() { render: function() {
if (this.state.unsupportedDevice) { if (this.state.unsupportedDevice) {
return UnsupportedDeviceView(null); return UnsupportedDeviceView(null);

Просмотреть файл

@ -859,6 +859,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
* of the webapp page. * of the webapp page.
*/ */
var WebappRootView = React.createClass({ var WebappRootView = React.createClass({
mixins: [sharedMixins.UrlHashChangeMixin,
sharedMixins.DocumentLocationMixin],
propTypes: { propTypes: {
client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired, client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
conversation: React.PropTypes.oneOfType([ conversation: React.PropTypes.oneOfType([
@ -879,6 +883,10 @@ loop.webapp = (function($, _, OT, mozL10n) {
}; };
}, },
onUrlHashChange: function() {
this.locationReload();
},
render: function() { render: function() {
if (this.state.unsupportedDevice) { if (this.state.unsupportedDevice) {
return <UnsupportedDeviceView />; return <UnsupportedDeviceView />;

Просмотреть файл

@ -21,6 +21,75 @@ describe("loop.shared.mixins", function() {
sandbox.restore(); 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() { describe("loop.panel.DocumentVisibilityMixin", function() {
var comp, TestComp, onDocumentVisibleStub, onDocumentHiddenStub; var comp, TestComp, onDocumentVisibleStub, onDocumentHiddenStub;

Просмотреть файл

@ -514,7 +514,8 @@ describe("loop.webapp", function() {
notifications: notifications, notifications: notifications,
sdk: sdk, sdk: sdk,
conversation: conversationModel, conversation: conversationModel,
feedbackApiClient: feedbackApiClient feedbackApiClient: feedbackApiClient,
onUrlHashChange: sandbox.stub()
})); }));
} }

Просмотреть файл

@ -64,7 +64,7 @@ function handleRequest(aSubject, aTopic, aData) {
constraints, devices, secure); constraints, devices, secure);
}, },
function (error) { 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. // and allow the user to plug in a device, instead of immediately failing.
denyRequest({callID: aSubject.callID}, error); denyRequest({callID: aSubject.callID}, error);
}, },
@ -108,7 +108,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec
requestTypes.push("Microphone"); requestTypes.push("Microphone");
if (!requestTypes.length) { if (!requestTypes.length) {
denyRequest({callID: aCallID}, "NO_DEVICES_FOUND"); denyRequest({callID: aCallID}, "NotFoundError");
return; return;
} }

Просмотреть файл

@ -838,7 +838,17 @@ this.UITour = {
highlighter.parentElement.setAttribute("targetName", aTarget.targetName); highlighter.parentElement.setAttribute("targetName", aTarget.targetName);
highlighter.parentElement.hidden = false; 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 highlightHeight = targetRect.height;
let highlightWidth = targetRect.width; let highlightWidth = targetRect.width;
let minDimension = Math.min(highlightHeight, highlightWidth); let minDimension = Math.min(highlightHeight, highlightWidth);
@ -874,7 +884,7 @@ this.UITour = {
let offsetY = paddingLeftPx let offsetY = paddingLeftPx
- (Math.max(0, highlightHeightWithMin - targetRect.height) / 2); - (Math.max(0, highlightHeightWithMin - targetRect.height) / 2);
this._addAnnotationPanelMutationObserver(highlighter.parentElement); 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. // Prevent showing a panel at an undefined position.

Просмотреть файл

@ -18,6 +18,23 @@
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
%define conditionalForwardWithUrlbarWidth 30 %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 { #menubar-items {
-moz-box-orient: vertical; /* for flex hack */ -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]):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-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-icon { :-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-icon {
background-color: hsla(0,0%,100%,.3); background: var(--toolbarbutton-hover-background);
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.2)); border-width: 1px;
border: 1px solid rgb(154,154,154); border-style: solid;
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset, border-color: var(--toolbarbutton-hover-bordercolor);
0 0 0 1px hsla(0,0%,100%,.2) inset, box-shadow: var(--toolbarbutton-hover-boxshadow);
0 1px 0 hsla(0,0%,0%,.03);
} }
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon, :-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[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-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .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: var(--toolbarbutton-active-background);
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4)); box-shadow: var(--toolbarbutton-active-boxshadow);
border: 1px solid rgb(154,154,154); border-width: 1px;
box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, border-style: solid;
0 0 1px hsla(0,0%,0%,.3) inset; border-color: var(--toolbarbutton-active-bordercolor);
transition-duration: 10ms; transition-duration: 10ms;
} }
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[checked]:not(:active):hover > .toolbarbutton-icon { :-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; transition: background-color 150ms;
} }
@ -633,12 +649,12 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
width: 1px; width: 1px;
height: 18px; height: 18px;
-moz-margin-end: -1px; -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-clip: padding-box;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 1px 18px; 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 { :-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) { #identity-box.verifiedIdentity:not(:-moz-lwtheme) {
background-color: #fff; background-color: var(--verified-identity-box-backgroundcolor);
} }
#identity-box:-moz-focusring { #identity-box:-moz-focusring {

Просмотреть файл

@ -17,6 +17,28 @@
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper %define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-wrapper
%define conditionalForwardWithUrlbarWidth 30 %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 { #menubar-items {
-moz-box-orient: vertical; /* for flex hack */ -moz-box-orient: vertical; /* for flex hack */
} }
@ -663,6 +685,27 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
(-moz-os-version: windows-win7) { (-moz-os-version: windows-win7) {
%endif %endif
/* < Win8 */ /* < 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-icon,
#nav-bar .toolbarbutton-1 > .toolbarbutton-text, #nav-bar .toolbarbutton-1 > .toolbarbutton-text,
#nav-bar .toolbarbutton-1 > .toolbarbutton-badge-container, #nav-bar .toolbarbutton-1 > .toolbarbutton-badge-container,
@ -732,7 +775,8 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
width: 1px; width: 1px;
height: 16px; height: 16px;
-moz-margin-end: -1px; -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-clip: padding-box;
background-position: center; background-position: center;
background-repeat: no-repeat; 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, #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, @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 { #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); background: var(--toolbarbutton-hover-background);
border-color: hsla(210,4%,10%,.1); border-color: var(--toolbarbutton-hover-bordercolor);
box-shadow: var(--toolbarbutton-hover-boxshadow);
} }
%ifdef WINDOWS_AERO %ifdef WINDOWS_AERO
@ -762,17 +807,8 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
/* < Win8 */ /* < Win8 */
#nav-bar .toolbarbutton-1:not(:hover):not(:active):not([open]) > .toolbarbutton-menubutton-dropmarker::before, #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 { #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; 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; 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), #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; 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 > .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, #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 { @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-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-text,
#nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container { #nav-bar .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container {
background-color: hsla(210,4%,10%,.12); background: var(--toolbarbutton-active-background);
border-top-color: hsla(210,4%,10%,.2); border-color: var(--toolbarbutton-active-bordercolor);
box-shadow: 0 1px 0 0 hsla(210,4%,10%,.1) inset; box-shadow: var(--toolbarbutton-active-boxshadow);
transition-duration: 10ms; 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-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-text,
#nav-bar .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container { #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; text-shadow: none;
transition: 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 { #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; transition: background-color .4s;
} }
%ifdef WINDOWS_AERO %ifdef WINDOWS_AERO
@ -1317,7 +1330,7 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
} }
#identity-box.verifiedIdentity:not(:-moz-lwtheme) { #identity-box.verifiedIdentity:not(:-moz-lwtheme) {
background-color: #fff; background-color: var(--verified-identity-box-backgroundcolor);
} }
#identity-box:-moz-focusring { #identity-box:-moz-focusring {
@ -1338,19 +1351,19 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
background-color: transparent; background-color: transparent;
border: none; border: none;
width: auto; width: auto;
list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker.png"); list-style-image: var(--urlbar-dropmarker-url);
-moz-image-region: rect(0px, 11px, 14px, 0px); -moz-image-region: var(--urlbar-dropmarker-region);
} }
.urlbar-history-dropmarker:hover { .urlbar-history-dropmarker:hover {
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent); 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:hover:active,
.urlbar-history-dropmarker[open="true"] { .urlbar-history-dropmarker[open="true"] {
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), transparent); 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 */ /* page proxy icon */

Просмотреть файл

@ -30,8 +30,8 @@
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox { #BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
/* emulating chrome://browser/content/places/menu.xml#places-popup-arrow but without the arrow */ /* 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); box-shadow: 0 0 4px rgba(0,0,0,0.2);
background: #FFF; background: var(--panel-arrowcontent-background);
border: 1px solid rgba(0,0,0,0.25); border: var(--panel-arrowcontent-border);
border-radius: 3.5px; border-radius: 3.5px;
margin-top: -4px; margin-top: -4px;
} }

Просмотреть файл

@ -2,6 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * 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 { .autocomplete-textbox-container {
-moz-box-align: stretch; -moz-box-align: stretch;
} }
@ -38,7 +42,7 @@
} }
.searchbar-dropmarker-image { .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); -moz-image-region: rect(0, 13px, 11px, 0);
} }

Просмотреть файл

@ -240,7 +240,6 @@ if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
fi fi
else else
STLPORT_CPPFLAGS="-isystem $_topsrcdir/build/stlport/stlport -isystem $_topsrcdir/build/stlport/overrides -isystem $android_ndk/sources/cxx-stl/system/include" 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
fi fi
CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS" CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"

Просмотреть файл

@ -4,7 +4,13 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # 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 FORCE_STATIC_LIB = True

Просмотреть файл

@ -5,19 +5,31 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
@template @template
def StdCppCompat(): def Binary():
'''Template for libstdc++ compatibility for target binaries.''' '''Generic template for target binaries. Meant to be used by other
templates.'''
if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']: if CONFIG['MOZ_LIBSTDCXX_TARGET_VERSION']:
USE_LIBS += ['stdc++compat'] 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 @template
def Program(name): def Program(name):
'''Template for program executables.''' '''Template for program executables.'''
PROGRAM = name PROGRAM = name
StdCppCompat() Binary()
@template @template
@ -29,7 +41,7 @@ def SimplePrograms(names, ext='.cpp'):
SIMPLE_PROGRAMS += names SIMPLE_PROGRAMS += names
SOURCES += ['%s%s' % (name, ext) for name in names] SOURCES += ['%s%s' % (name, ext) for name in names]
StdCppCompat() Binary()
@template @template
@ -41,7 +53,7 @@ def CppUnitTests(names, ext='.cpp'):
CPP_UNIT_TESTS += names CPP_UNIT_TESTS += names
SOURCES += ['%s%s' % (name, ext) for name in names] SOURCES += ['%s%s' % (name, ext) for name in names]
StdCppCompat() Binary()
@template @template
@ -57,7 +69,7 @@ def SharedLibrary(name):
FORCE_SHARED_LIB = True FORCE_SHARED_LIB = True
StdCppCompat() Binary()
@template @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 JSContextPtr(JSContext);
[ptr] native JSObjectPtr(JSObject); [ptr] native JSObjectPtr(JSObject);
[scriptable, uuid(3b021962-975e-43b5-8a93-9fc2d20346e9)] [scriptable, uuid(f649959d-dae3-4027-83fd-5b7f8c8a8815)]
interface nsIScriptSecurityManager : nsISupports interface nsIScriptSecurityManager : nsISupports
{ {
/** /**
@ -178,13 +178,6 @@ interface nsIScriptSecurityManager : nsISupports
*/ */
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri); [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" * Returns OK if aSourceURI and target have the same "origin"
* (scheme, host, and port). * (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)) { if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -441,39 +441,6 @@ nsScriptSecurityManager::JSPrincipalsSubsume(JSPrincipals *first,
return nsJSPrincipals::get(first)->Subsumes(nsJSPrincipals::get(second)); 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 NS_IMETHODIMP
nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI, nsScriptSecurityManager::CheckSameOriginURI(nsIURI* aSourceURI,
nsIURI* aTargetURI, 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 ldap/target: config/external/nss/target mozglue/build/target
toolkit/library/target: ldap/target toolkit/library/target: ldap/target
endif 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) 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
endif endif

Просмотреть файл

@ -696,7 +696,7 @@ ifdef MOZ_PROFILE_GENERATE
touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
endif endif
else # !WINNT || GNU_CC 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,$@) $(call CHECK_BINARY,$@)
endif # WINNT && !GNU_CC endif # WINNT && !GNU_CC
@ -752,7 +752,7 @@ ifdef MSMANIFEST_TOOL
fi fi
endif # MSVC with manifest tool endif # MSVC with manifest tool
else 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,$@) $(call CHECK_BINARY,$@)
endif # WINNT && !GNU_CC endif # WINNT && !GNU_CC
@ -834,10 +834,10 @@ ifdef DTRACE_LIB_DEPENDENT
ifndef XP_MACOSX ifndef XP_MACOSX
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS)) dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
endif 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) @$(RM) $(DTRACE_PROBE_OBJ)
else # ! DTRACE_LIB_DEPENDENT 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 endif # DTRACE_LIB_DEPENDENT
$(call CHECK_BINARY,$@) $(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]) AC_MSG_ERROR([Couldn't find path to stlport sources in the gonk tree])
fi fi
STLPORT_CPPFLAGS="-I$_topsrcdir/build/stlport/stlport -I$gonkdir/ndk/sources/cxx-stl/system/include" 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 case "$target_cpu" in
arm) arm)
@ -9060,8 +9059,6 @@ HAVE_SYS_VFS_H
HAVE_SYS_MOUNT_H HAVE_SYS_MOUNT_H
" "
AC_SUBST(STLPORT_LIBS)
dnl ======================================================== dnl ========================================================
dnl ICU Support dnl ICU Support
dnl ======================================================== dnl ========================================================

Просмотреть файл

@ -53,8 +53,9 @@
var s2 = snapshotWindow($("f2").contentWindow); var s2 = snapshotWindow($("f2").contentWindow);
var s3 = snapshotWindow($("f3").contentWindow); var s3 = snapshotWindow($("f3").contentWindow);
ok(!compareSnapshots(s2, s3, true)[0], // This test is broken - see bug 1090274
"Should look different due to different sizing"); //ok(!compareSnapshots(s2, s3, true)[0],
// "Should look different due to different sizing");
function getDOM(id) { function getDOM(id) {
return $(id).contentDocument.documentElement.innerHTML; return $(id).contentDocument.documentElement.innerHTML;

Просмотреть файл

@ -70,6 +70,7 @@
#include "mozIThirdPartyUtil.h" #include "mozIThirdPartyUtil.h"
#ifdef MOZ_MEDIA_NAVIGATOR #ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/dom/MediaDevices.h"
#include "MediaManager.h" #include "MediaManager.h"
#endif #endif
#ifdef MOZ_B2G_BT #ifdef MOZ_B2G_BT
@ -1219,6 +1220,21 @@ Navigator::SendBeacon(const nsAString& aUrl,
} }
#ifdef MOZ_MEDIA_NAVIGATOR #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 void
Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints, Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
NavigatorUserMediaSuccessCallback& aOnSuccess, NavigatorUserMediaSuccessCallback& aOnSuccess,

Просмотреть файл

@ -32,6 +32,7 @@ namespace mozilla {
namespace dom { namespace dom {
class Geolocation; class Geolocation;
class systemMessageCallback; class systemMessageCallback;
class MediaDevices;
struct MediaStreamConstraints; struct MediaStreamConstraints;
class WakeLock; class WakeLock;
class ArrayBufferViewOrBlobOrStringOrFormData; class ArrayBufferViewOrBlobOrStringOrFormData;
@ -226,6 +227,7 @@ public:
TVManager* GetTv(); TVManager* GetTv();
network::Connection* GetConnection(ErrorResult& aRv); network::Connection* GetConnection(ErrorResult& aRv);
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv); nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
MediaDevices* GetMediaDevices(ErrorResult& aRv);
void MozSetMessageHandler(const nsAString& aType, void MozSetMessageHandler(const nsAString& aType,
systemMessageCallback* aCallback, systemMessageCallback* aCallback,
ErrorResult& aRv); ErrorResult& aRv);
@ -349,6 +351,7 @@ private:
nsRefPtr<system::AudioChannelManager> mAudioChannelManager; nsRefPtr<system::AudioChannelManager> mAudioChannelManager;
#endif #endif
nsRefPtr<nsDOMCameraManager> mCameraManager; nsRefPtr<nsDOMCameraManager> mCameraManager;
nsRefPtr<MediaDevices> mMediaDevices;
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager; nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores; nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
nsRefPtr<time::TimeManager> mTimeManager; nsRefPtr<time::TimeManager> mTimeManager;

Просмотреть файл

@ -46,7 +46,6 @@
#include "mozilla/dom/quota/FileStreams.h" #include "mozilla/dom/quota/FileStreams.h"
#include "mozilla/dom/quota/OriginOrPatternString.h" #include "mozilla/dom/quota/OriginOrPatternString.h"
#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
#include "mozilla/dom/quota/UsageInfo.h" #include "mozilla/dom/quota/UsageInfo.h"
#include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/BackgroundUtils.h"
@ -3885,7 +3884,6 @@ protected:
nsCString mOrigin; nsCString mOrigin;
nsCString mDatabaseId; nsCString mDatabaseId;
State mState; State mState;
StoragePrivilege mStoragePrivilege;
bool mEnforcingQuota; bool mEnforcingQuota;
const bool mDeleting; const bool mDeleting;
bool mBlockedQuotaManager; bool mBlockedQuotaManager;
@ -8590,14 +8588,14 @@ Cursor::RecvContinue(const CursorRequestParams& aParams)
FileManager::FileManager(PersistenceType aPersistenceType, FileManager::FileManager(PersistenceType aPersistenceType,
const nsACString& aGroup, const nsACString& aGroup,
const nsACString& aOrigin, const nsACString& aOrigin,
StoragePrivilege aPrivilege, const nsAString& aDatabaseName,
const nsAString& aDatabaseName) bool aEnforcingQuota)
: mPersistenceType(aPersistenceType) : mPersistenceType(aPersistenceType)
, mGroup(aGroup) , mGroup(aGroup)
, mOrigin(aOrigin) , mOrigin(aOrigin)
, mPrivilege(aPrivilege)
, mDatabaseName(aDatabaseName) , mDatabaseName(aDatabaseName)
, mLastFileId(0) , mLastFileId(0)
, mEnforcingQuota(aEnforcingQuota)
, mInvalidated(false) , mInvalidated(false)
{ } { }
@ -10436,7 +10434,6 @@ FactoryOp::FactoryOp(Factory* aFactory,
, mContentParent(Move(aContentParent)) , mContentParent(Move(aContentParent))
, mCommonParams(aCommonParams) , mCommonParams(aCommonParams)
, mState(State_Initial) , mState(State_Initial)
, mStoragePrivilege(mozilla::dom::quota::Content)
, mEnforcingQuota(true) , mEnforcingQuota(true)
, mDeleting(aDeleting) , mDeleting(aDeleting)
, mBlockedQuotaManager(false) , mBlockedQuotaManager(false)
@ -10735,9 +10732,7 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
} }
if (State_Initial == mState) { if (State_Initial == mState) {
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, &mStoragePrivilege, QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, nullptr, nullptr);
nullptr);
MOZ_ASSERT(mStoragePrivilege == mozilla::dom::quota::Chrome);
mEnforcingQuota = false; mEnforcingQuota = false;
} }
@ -10789,12 +10784,10 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
if (permission != PermissionRequestBase::kPermissionDenied && if (permission != PermissionRequestBase::kPermissionDenied &&
State_Initial == mState) { State_Initial == mState) {
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin, rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
&mStoragePrivilege, nullptr); nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
MOZ_ASSERT(mStoragePrivilege != mozilla::dom::quota::Chrome);
} }
if (permission == PermissionRequestBase::kPermissionAllowed && if (permission == PermissionRequestBase::kPermissionAllowed &&
@ -11326,8 +11319,8 @@ OpenDatabaseOp::DoDatabaseWork()
fileManager = new FileManager(persistenceType, fileManager = new FileManager(persistenceType,
mGroup, mGroup,
mOrigin, mOrigin,
mStoragePrivilege, databaseName,
databaseName); mEnforcingQuota);
rv = fileManager->Init(fmDirectory, connection); rv = fileManager->Init(fmDirectory, connection);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
@ -12704,7 +12697,7 @@ VersionChangeOp::RunOnIOThread()
if (exists) { if (exists) {
int64_t fileSize; int64_t fileSize;
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) { if (mDeleteDatabaseOp->mEnforcingQuota) {
rv = dbFile->GetFileSize(&fileSize); rv = dbFile->GetFileSize(&fileSize);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
@ -12716,7 +12709,7 @@ VersionChangeOp::RunOnIOThread()
return rv; return rv;
} }
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) { if (mDeleteDatabaseOp->mEnforcingQuota) {
quotaManager->DecreaseUsageForOrigin(persistenceType, quotaManager->DecreaseUsageForOrigin(persistenceType,
mDeleteDatabaseOp->mGroup, mDeleteDatabaseOp->mGroup,
mDeleteDatabaseOp->mOrigin, mDeleteDatabaseOp->mOrigin,
@ -12781,7 +12774,7 @@ VersionChangeOp::RunOnIOThread()
uint64_t usage = 0; uint64_t usage = 0;
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) { if (mDeleteDatabaseOp->mEnforcingQuota) {
rv = FileManager::GetUsage(fmDirectory, &usage); rv = FileManager::GetUsage(fmDirectory, &usage);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
@ -12793,7 +12786,7 @@ VersionChangeOp::RunOnIOThread()
return rv; return rv;
} }
if (mDeleteDatabaseOp->mStoragePrivilege != Chrome) { if (mDeleteDatabaseOp->mEnforcingQuota) {
quotaManager->DecreaseUsageForOrigin(persistenceType, quotaManager->DecreaseUsageForOrigin(persistenceType,
mDeleteDatabaseOp->mGroup, mDeleteDatabaseOp->mGroup,
mDeleteDatabaseOp->mOrigin, mDeleteDatabaseOp->mOrigin,
@ -14425,12 +14418,14 @@ ObjectStoreAddOrPutRequestOp::CopyFileData(nsIInputStream* aInputStream,
} }
} while (true); } while (true);
nsresult rv2 = aOutputStream->Flush(); if (NS_SUCCEEDED(rv)) {
if (NS_WARN_IF(NS_FAILED(rv2))) { rv = aOutputStream->Flush();
return NS_SUCCEEDED(rv) ? rv2 : rv; if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} }
rv2 = aOutputStream->Close(); nsresult rv2 = aOutputStream->Close();
if (NS_WARN_IF(NS_FAILED(rv2))) { if (NS_WARN_IF(NS_FAILED(rv2))) {
return NS_SUCCEEDED(rv) ? rv2 : rv; return NS_SUCCEEDED(rv) ? rv2 : rv;
} }
@ -14804,9 +14799,31 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(TransactionBase* aTransaction)
} }
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
// Try to remove the file if the copy failed. // Try to remove the file if the copy failed.
if (NS_FAILED(diskFile->Remove(false))) { nsresult rv2;
NS_WARNING("Failed to remove file after copying failed!"); 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; return rv;
} }

Просмотреть файл

@ -9,7 +9,6 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/dom/quota/PersistenceType.h" #include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
@ -29,12 +28,10 @@ class FileManager MOZ_FINAL
friend class FileInfo; friend class FileInfo;
typedef mozilla::dom::quota::PersistenceType PersistenceType; typedef mozilla::dom::quota::PersistenceType PersistenceType;
typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege;
PersistenceType mPersistenceType; PersistenceType mPersistenceType;
nsCString mGroup; nsCString mGroup;
nsCString mOrigin; nsCString mOrigin;
StoragePrivilege mPrivilege;
nsString mDatabaseName; nsString mDatabaseName;
nsString mDirectoryPath; nsString mDirectoryPath;
@ -45,6 +42,7 @@ class FileManager MOZ_FINAL
// Protected by IndexedDatabaseManager::FileMutex() // Protected by IndexedDatabaseManager::FileMutex()
nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos; nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;
const bool mEnforcingQuota;
bool mInvalidated; bool mInvalidated;
public: public:
@ -64,8 +62,8 @@ public:
FileManager(PersistenceType aPersistenceType, FileManager(PersistenceType aPersistenceType,
const nsACString& aGroup, const nsACString& aGroup,
const nsACString& aOrigin, const nsACString& aOrigin,
StoragePrivilege aPrivilege, const nsAString& aDatabaseName,
const nsAString& aDatabaseName); bool aEnforcingQuota);
PersistenceType PersistenceType
Type() const Type() const
@ -85,18 +83,18 @@ public:
return mOrigin; return mOrigin;
} }
const StoragePrivilege&
Privilege() const
{
return mPrivilege;
}
const nsAString& const nsAString&
DatabaseName() const DatabaseName() const
{ {
return mDatabaseName; return mDatabaseName;
} }
bool
EnforcingQuota() const
{
return mEnforcingQuota;
}
bool bool
Invalidated() const Invalidated() const
{ {

Просмотреть файл

@ -848,7 +848,7 @@ AsyncDeleteFileRunnable::Run()
nsresult rv; nsresult rv;
int64_t fileSize; int64_t fileSize;
if (mFileManager->Privilege() != Chrome) { if (mFileManager->EnforcingQuota()) {
rv = file->GetFileSize(&fileSize); rv = file->GetFileSize(&fileSize);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
} }
@ -856,7 +856,7 @@ AsyncDeleteFileRunnable::Run()
rv = file->Remove(false); rv = file->Remove(false);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
if (mFileManager->Privilege() != Chrome) { if (mFileManager->EnforcingQuota()) {
QuotaManager* quotaManager = QuotaManager::Get(); QuotaManager* quotaManager = QuotaManager::Get();
NS_ASSERTION(quotaManager, "Shouldn't be null!"); NS_ASSERTION(quotaManager, "Shouldn't be null!");

Просмотреть файл

@ -12,7 +12,6 @@
#include "mozilla/dom/indexedDB/IDBCursor.h" #include "mozilla/dom/indexedDB/IDBCursor.h"
#include "mozilla/dom/indexedDB/IDBTransaction.h" #include "mozilla/dom/indexedDB/IDBTransaction.h"
#include "mozilla/dom/quota/PersistenceType.h" #include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/StoragePrivilege.h"
namespace IPC { namespace IPC {
@ -24,13 +23,6 @@ struct ParamTraits<mozilla::dom::quota::PersistenceType> :
mozilla::dom::quota::PERSISTENCE_TYPE_INVALID> 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 <> template <>
struct ParamTraits<mozilla::dom::indexedDB::Key> 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_ENTRY(DOMMediaStream)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) 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, NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream,
mStreamNode) mStreamNode)

Просмотреть файл

@ -20,15 +20,10 @@ namespace mozilla {
#ifdef PR_LOGGING #ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaDecoderLog; extern PRLogModuleInfo* gMediaDecoderLog;
#define DECODER_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg) #define DECODER_LOG(x, ...) \
#ifdef SEEK_LOGGING PR_LOG(gMediaDecoderLog, PR_LOG_DEBUG, ("Decoder=%p " x, mDecoder, ##__VA_ARGS__))
#define SEEK_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
#else #else
#define SEEK_LOG(type, msg) #define DECODER_LOG(x, ...)
#endif
#else
#define DECODER_LOG(type, msg)
#define SEEK_LOG(type, msg)
#endif #endif
class VideoQueueMemoryFunctor : public nsDequeFunctor { class VideoQueueMemoryFunctor : public nsDequeFunctor {
@ -139,6 +134,20 @@ MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
return NS_OK; 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 { class RequestVideoWithSkipTask : public nsRunnable {
public: public:
RequestVideoWithSkipTask(MediaDecoderReader* aReader, RequestVideoWithSkipTask(MediaDecoderReader* aReader,

Просмотреть файл

@ -148,6 +148,8 @@ public:
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
int64_t aStartTime); 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 // Returns the number of bytes of memory allocated by structures/frames in
// the video queue. // the video queue.
size_t SizeOfVideoQueueInBytes() const; size_t SizeOfVideoQueueInBytes() const;

Просмотреть файл

@ -2016,18 +2016,9 @@ MediaDecoderStateMachine::FinishDecodeMetadata()
} }
if (!mScheduler->IsRealTime() && !mDecodingFrozenAtStateMetadata) { if (!mScheduler->IsRealTime() && !mDecodingFrozenAtStateMetadata) {
const VideoData* v = VideoQueue().PeekFront(); const VideoData* v = VideoQueue().PeekFront();
const AudioData* a = AudioQueue().PeekFront(); const AudioData* a = AudioQueue().PeekFront();
SetStartTime(mReader->ComputeStartTime(v, a));
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);
if (VideoQueue().GetSize()) { if (VideoQueue().GetSize()) {
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
RenderVideoFrame(VideoQueue().PeekFront(), TimeStamp::Now()); 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

50
dom/media/MediaDevices.h Normal file
Просмотреть файл

@ -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::MediaStreamConstraints; // Outside API (contains JSObject)
using dom::MediaTrackConstraintSet; // Mandatory or optional constraints using dom::MediaTrackConstraintSet; // Mandatory or optional constraints
using dom::MediaTrackConstraints; // Raw mMandatory (as JSObject) using dom::MediaTrackConstraints; // Raw mMandatory (as JSObject)
using dom::MediaStreamError;
using dom::GetUserMediaRequest; using dom::GetUserMediaRequest;
using dom::Sequence; using dom::Sequence;
using dom::OwningBooleanOrMediaTrackConstraints; using dom::OwningBooleanOrMediaTrackConstraints;
@ -194,20 +195,21 @@ HostHasPermission(nsIURI &docURI)
} }
ErrorCallbackRunnable::ErrorCallbackRunnable( ErrorCallbackRunnable::ErrorCallbackRunnable(
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess, nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
const nsAString& aErrorMsg, uint64_t aWindowID) MediaMgrError& aError,
: mErrorMsg(aErrorMsg) uint64_t aWindowID)
: mError(&aError)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mManager(MediaManager::GetInstance()) , mManager(MediaManager::GetInstance())
{ {
mSuccess.swap(aSuccess); mOnSuccess.swap(aOnSuccess);
mError.swap(aError); mOnFailure.swap(aOnFailure);
} }
ErrorCallbackRunnable::~ErrorCallbackRunnable() ErrorCallbackRunnable::~ErrorCallbackRunnable()
{ {
MOZ_ASSERT(!mSuccess && !mError); MOZ_ASSERT(!mOnSuccess && !mOnFailure);
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -216,15 +218,19 @@ ErrorCallbackRunnable::Run()
// Only run if the window is still active. // Only run if the window is still active.
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget(); nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget(); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
if (!(mManager->IsWindowStillActive(mWindowID))) { if (!(mManager->IsWindowStillActive(mWindowID))) {
return NS_OK; return NS_OK;
} }
// This is safe since we're on main-thread, and the windowlist can only // This is safe since we're on main-thread, and the windowlist can only
// be invalidated from the main-thread (see OnNavigation) // 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; return NS_OK;
} }
@ -238,15 +244,15 @@ class SuccessCallbackRunnable : public nsRunnable
{ {
public: public:
SuccessCallbackRunnable( SuccessCallbackRunnable(
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess, nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
nsIDOMFile* aFile, uint64_t aWindowID) nsIDOMFile* aFile, uint64_t aWindowID)
: mFile(aFile) : mFile(aFile)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mManager(MediaManager::GetInstance()) , mManager(MediaManager::GetInstance())
{ {
mSuccess.swap(aSuccess); mOnSuccess.swap(aOnSuccess);
mError.swap(aError); mOnFailure.swap(aOnFailure);
} }
NS_IMETHOD NS_IMETHOD
@ -255,21 +261,21 @@ public:
// Only run if the window is still active. // Only run if the window is still active.
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget(); nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget(); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
if (!(mManager->IsWindowStillActive(mWindowID))) { if (!(mManager->IsWindowStillActive(mWindowID))) {
return NS_OK; return NS_OK;
} }
// This is safe since we're on main-thread, and the windowlist can only // This is safe since we're on main-thread, and the windowlist can only
// be invalidated from the main-thread (see OnNavigation) // be invalidated from the main-thread (see OnNavigation)
success->OnSuccess(mFile); onSuccess->OnSuccess(mFile);
return NS_OK; return NS_OK;
} }
private: private:
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsCOMPtr<nsIDOMFile> mFile; nsCOMPtr<nsIDOMFile> mFile;
uint64_t mWindowID; uint64_t mWindowID;
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
@ -285,15 +291,15 @@ class DeviceSuccessCallbackRunnable: public nsRunnable
public: public:
DeviceSuccessCallbackRunnable( DeviceSuccessCallbackRunnable(
uint64_t aWindowID, uint64_t aWindowID,
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aSuccess, nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback>& aOnSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
nsTArray<nsRefPtr<MediaDevice>>* aDevices) nsTArray<nsRefPtr<MediaDevice>>* aDevices)
: mDevices(aDevices) : mDevices(aDevices)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mManager(MediaManager::GetInstance()) , mManager(MediaManager::GetInstance())
{ {
mSuccess.swap(aSuccess); mOnSuccess.swap(aOnSuccess);
mError.swap(aError); mOnFailure.swap(aOnFailure);
} }
NS_IMETHOD NS_IMETHOD
@ -315,7 +321,12 @@ public:
// We should in the future return an empty array, and dynamically add // We should in the future return an empty array, and dynamically add
// devices to the dropdowns if things are hotplugged while the // devices to the dropdowns if things are hotplugged while the
// requester is up. // 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; return NS_OK;
} }
@ -331,13 +342,13 @@ public:
static_cast<const void*>(tmp.Elements()) static_cast<const void*>(tmp.Elements())
)); ));
mSuccess->OnSuccess(devices); mOnSuccess->OnSuccess(devices);
return NS_OK; return NS_OK;
} }
private: private:
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess; nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices; nsAutoPtr<nsTArray<nsRefPtr<MediaDevice>>> mDevices;
uint64_t mWindowID; uint64_t mWindowID;
nsRefPtr<MediaManager> mManager; nsRefPtr<MediaManager> mManager;
@ -723,8 +734,8 @@ class GetUserMediaStreamRunnable : public nsRunnable
{ {
public: public:
GetUserMediaStreamRunnable( GetUserMediaStreamRunnable(
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess, nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
uint64_t aWindowID, uint64_t aWindowID,
GetUserMediaCallbackMediaStreamListener* aListener, GetUserMediaCallbackMediaStreamListener* aListener,
MediaEngineSource* aAudioSource, MediaEngineSource* aAudioSource,
@ -737,8 +748,8 @@ public:
, mPeerIdentity(aPeerIdentity) , mPeerIdentity(aPeerIdentity)
, mManager(MediaManager::GetInstance()) , mManager(MediaManager::GetInstance())
{ {
mSuccess.swap(aSuccess); mOnSuccess.swap(aOnSuccess);
mError.swap(aError); mOnFailure.swap(aOnFailure);
} }
~GetUserMediaStreamRunnable() {} ~GetUserMediaStreamRunnable() {}
@ -750,7 +761,7 @@ public:
nsIDOMGetUserMediaSuccessCallback* aSuccess, nsIDOMGetUserMediaSuccessCallback* aSuccess,
uint64_t aWindowID, uint64_t aWindowID,
DOMMediaStream* aStream) DOMMediaStream* aStream)
: mWindowID(aWindowID), mSuccess(aSuccess), mManager(aManager), : mWindowID(aWindowID), mOnSuccess(aSuccess), mManager(aManager),
mStream(aStream) {} mStream(aStream) {}
virtual void NotifyTracksAvailable(DOMMediaStream* aStream) MOZ_OVERRIDE 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 // This is safe since we're on main-thread, and the windowlist can only
// be invalidated from the main-thread (see OnNavigation) // be invalidated from the main-thread (see OnNavigation)
LOG(("Returning success for getUserMedia()")); LOG(("Returning success for getUserMedia()"));
mSuccess->OnSuccess(aStream); mOnSuccess->OnSuccess(aStream);
} }
uint64_t mWindowID; uint64_t mWindowID;
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsRefPtr<MediaManager> mManager; nsRefPtr<MediaManager> mManager;
// Keep the DOMMediaStream alive until the NotifyTracksAvailable callback // Keep the DOMMediaStream alive until the NotifyTracksAvailable callback
// has fired, otherwise we might immediately destroy the DOMMediaStream and // has fired, otherwise we might immediately destroy the DOMMediaStream and
@ -830,9 +841,16 @@ public:
nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener, nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener,
mAudioSource, mVideoSource); mAudioSource, mVideoSource);
if (!trackunion) { if (!trackunion) {
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget(); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
LOG(("Returning error for getUserMedia() - no stream")); 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; return NS_OK;
} }
trackunion->AudioConfig(aec_on, (uint32_t) aec, trackunion->AudioConfig(aec_on, (uint32_t) aec,
@ -874,7 +892,7 @@ public:
// Note: includes JS callbacks; must be released on MainThread // Note: includes JS callbacks; must be released on MainThread
TracksAvailableCallback* tracksAvailableCallback = TracksAvailableCallback* tracksAvailableCallback =
new TracksAvailableCallback(mManager, mSuccess, mWindowID, trackunion); new TracksAvailableCallback(mManager, mOnSuccess, mWindowID, trackunion);
mListener->AudioConfig(aec_on, (uint32_t) aec, mListener->AudioConfig(aec_on, (uint32_t) aec,
agc_on, (uint32_t) agc, agc_on, (uint32_t) agc,
@ -889,16 +907,16 @@ public:
new MediaOperationTask(MEDIA_START, mListener, trackunion, new MediaOperationTask(MEDIA_START, mListener, trackunion,
tracksAvailableCallback, tracksAvailableCallback,
mAudioSource, mVideoSource, false, mWindowID, mAudioSource, mVideoSource, false, mWindowID,
mError.forget())); mOnFailure.forget()));
// We won't need mError now. // We won't need mOnFailure now.
mError = nullptr; mOnFailure = nullptr;
return NS_OK; return NS_OK;
} }
private: private:
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsRefPtr<MediaEngineSource> mAudioSource; nsRefPtr<MediaEngineSource> mAudioSource;
nsRefPtr<MediaEngineSource> mVideoSource; nsRefPtr<MediaEngineSource> mVideoSource;
uint64_t mWindowID; uint64_t mWindowID;
@ -1056,13 +1074,13 @@ class GetUserMediaTask : public Task
public: public:
GetUserMediaTask( GetUserMediaTask(
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess, already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError, already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener, uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
MediaEnginePrefs &aPrefs) MediaEnginePrefs &aPrefs)
: mConstraints(aConstraints) : mConstraints(aConstraints)
, mSuccess(aSuccess) , mOnSuccess(aOnSuccess)
, mError(aError) , mOnFailure(aOnFailure)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mListener(aListener) , mListener(aListener)
, mPrefs(aPrefs) , mPrefs(aPrefs)
@ -1077,14 +1095,14 @@ public:
*/ */
GetUserMediaTask( GetUserMediaTask(
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess, already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError, already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener, uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
MediaEnginePrefs &aPrefs, MediaEnginePrefs &aPrefs,
MediaEngine* aBackend) MediaEngine* aBackend)
: mConstraints(aConstraints) : mConstraints(aConstraints)
, mSuccess(aSuccess) , mOnSuccess(aOnSuccess)
, mError(aError) , mOnFailure(aOnFailure)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mListener(aListener) , mListener(aListener)
, mPrefs(aPrefs) , mPrefs(aPrefs)
@ -1097,12 +1115,14 @@ public:
} }
void void
Fail(const nsAString& aMessage) { Fail(const nsAString& aName,
const nsAString& aMessage = EmptyString()) {
nsRefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage);
nsRefPtr<ErrorCallbackRunnable> runnable = nsRefPtr<ErrorCallbackRunnable> runnable =
new ErrorCallbackRunnable(mSuccess, mError, aMessage, mWindowID); new ErrorCallbackRunnable(mOnSuccess, mOnFailure, *error, mWindowID);
// These should be empty now // These should be empty now
MOZ_ASSERT(!mSuccess); MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mError); MOZ_ASSERT(!mOnFailure);
NS_DispatchToMainThread(runnable); NS_DispatchToMainThread(runnable);
} }
@ -1111,8 +1131,8 @@ public:
Run() Run()
{ {
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
MOZ_ASSERT(mSuccess); MOZ_ASSERT(mOnSuccess);
MOZ_ASSERT(mError); MOZ_ASSERT(mOnFailure);
MediaEngine* backend = mBackend; MediaEngine* backend = mBackend;
// Was a backend provided? // Was a backend provided?
@ -1136,34 +1156,40 @@ public:
} }
nsresult nsresult
Denied(const nsAString& aErrorMsg) Denied(const nsAString& aName,
const nsAString& aMessage = EmptyString())
{ {
MOZ_ASSERT(mSuccess); MOZ_ASSERT(mOnSuccess);
MOZ_ASSERT(mError); MOZ_ASSERT(mOnFailure);
// We add a disabled listener to the StreamListeners array until accepted // 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 this was the only active MediaStream, remove the window from the list.
if (NS_IsMainThread()) { if (NS_IsMainThread()) {
// This is safe since we're on main-thread, and the window can only // This is safe since we're on main-thread, and the window can only
// be invalidated from the main-thread (see OnNavigation) // be invalidated from the main-thread (see OnNavigation)
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success = mSuccess.forget(); nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mError.forget(); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
error->OnError(aErrorMsg);
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 // Should happen *after* error runs for consistency, but may not matter
nsRefPtr<MediaManager> manager(MediaManager::GetInstance()); nsRefPtr<MediaManager> manager(MediaManager::GetInstance());
manager->RemoveFromWindowList(mWindowID, mListener); manager->RemoveFromWindowList(mWindowID, mListener);
} else { } else {
// This will re-check the window being alive on main-thread // This will re-check the window being alive on main-thread
// Note: we must remove the listener on MainThread as well // 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 // MUST happen after ErrorCallbackRunnable Run()s, as it checks the active window list
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener)); NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener));
} }
MOZ_ASSERT(!mSuccess); MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mError); MOZ_ASSERT(!mOnFailure);
return NS_OK; return NS_OK;
} }
@ -1194,15 +1220,15 @@ public:
nsresult nsresult
SelectDevice(MediaEngine* backend) SelectDevice(MediaEngine* backend)
{ {
MOZ_ASSERT(mSuccess); MOZ_ASSERT(mOnSuccess);
MOZ_ASSERT(mError); MOZ_ASSERT(mOnFailure);
if (IsOn(mConstraints.mVideo)) { if (IsOn(mConstraints.mVideo)) {
VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo)); VideoTrackConstraintsN constraints(GetInvariant(mConstraints.mVideo));
nsTArray<nsRefPtr<VideoDevice>> sources; nsTArray<nsRefPtr<VideoDevice>> sources;
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources); GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources);
if (!sources.Length()) { if (!sources.Length()) {
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND")); Fail(NS_LITERAL_STRING("NotFoundError"));
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Pick the first available device. // Pick the first available device.
@ -1215,7 +1241,7 @@ public:
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources); GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources);
if (!sources.Length()) { if (!sources.Length()) {
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND")); Fail(NS_LITERAL_STRING("NotFoundError"));
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
// Pick the first available device. // Pick the first available device.
@ -1234,14 +1260,15 @@ public:
ProcessGetUserMedia(MediaEngineAudioSource* aAudioSource, ProcessGetUserMedia(MediaEngineAudioSource* aAudioSource,
MediaEngineVideoSource* aVideoSource) MediaEngineVideoSource* aVideoSource)
{ {
MOZ_ASSERT(mSuccess); MOZ_ASSERT(mOnSuccess);
MOZ_ASSERT(mError); MOZ_ASSERT(mOnFailure);
nsresult rv; nsresult rv;
if (aAudioSource) { if (aAudioSource) {
rv = aAudioSource->Allocate(GetInvariant(mConstraints.mAudio), mPrefs); rv = aAudioSource->Allocate(GetInvariant(mConstraints.mAudio), mPrefs);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
LOG(("Failed to allocate audiosource %d",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; return;
} }
} }
@ -1252,7 +1279,8 @@ public:
if (aAudioSource) { if (aAudioSource) {
aAudioSource->Deallocate(); aAudioSource->Deallocate();
} }
Fail(NS_LITERAL_STRING("HARDWARE_UNAVAILABLE")); Fail(NS_LITERAL_STRING("SourceUnavailableError"),
NS_LITERAL_STRING("Failed to allocate videosource"));
return; return;
} }
} }
@ -1262,12 +1290,12 @@ public:
} }
NS_DispatchToMainThread(new GetUserMediaStreamRunnable( NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
mSuccess, mError, mWindowID, mListener, aAudioSource, aVideoSource, mOnSuccess, mOnFailure, mWindowID, mListener, aAudioSource, aVideoSource,
peerIdentity peerIdentity
)); ));
MOZ_ASSERT(!mSuccess); MOZ_ASSERT(!mOnSuccess);
MOZ_ASSERT(!mError); MOZ_ASSERT(!mOnFailure);
return; return;
} }
@ -1275,8 +1303,8 @@ public:
private: private:
MediaStreamConstraints mConstraints; MediaStreamConstraints mConstraints;
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
uint64_t mWindowID; uint64_t mWindowID;
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
nsRefPtr<AudioDevice> mAudioDevice; nsRefPtr<AudioDevice> mAudioDevice;
@ -1322,13 +1350,13 @@ class GetUserMediaDevicesTask : public Task
public: public:
GetUserMediaDevicesTask( GetUserMediaDevicesTask(
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess, already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aOnSuccess,
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError, already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
uint64_t aWindowId, nsACString& aAudioLoopbackDev, uint64_t aWindowId, nsACString& aAudioLoopbackDev,
nsACString& aVideoLoopbackDev) nsACString& aVideoLoopbackDev)
: mConstraints(aConstraints) : mConstraints(aConstraints)
, mSuccess(aSuccess) , mOnSuccess(aOnSuccess)
, mError(aError) , mOnFailure(aOnFailure)
, mManager(MediaManager::GetInstance()) , mManager(MediaManager::GetInstance())
, mWindowId(aWindowId) , mWindowId(aWindowId)
, mLoopbackAudioDevice(aAudioLoopbackDev) , mLoopbackAudioDevice(aAudioLoopbackDev)
@ -1368,16 +1396,16 @@ public:
} }
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId, NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
mSuccess, mError, mOnSuccess, mOnFailure,
final.forget())); final.forget()));
// DeviceSuccessCallbackRunnable should have taken these. // DeviceSuccessCallbackRunnable should have taken these.
MOZ_ASSERT(!mSuccess && !mError); MOZ_ASSERT(!mOnSuccess && !mOnFailure);
} }
private: private:
MediaStreamConstraints mConstraints; MediaStreamConstraints mConstraints;
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mSuccess; nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
nsRefPtr<MediaManager> mManager; nsRefPtr<MediaManager> mManager;
uint64_t mWindowId; uint64_t mWindowId;
const nsString mCallId; const nsString mCallId;
@ -1544,18 +1572,18 @@ nsresult
MediaManager::GetUserMedia( MediaManager::GetUserMedia(
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints, nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints,
nsIDOMGetUserMediaSuccessCallback* aOnSuccess, nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
nsIDOMGetUserMediaErrorCallback* aOnError) nsIDOMGetUserMediaErrorCallback* aOnFailure)
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER); 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); NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
bool privileged = nsContentUtils::IsChromeDoc(aWindow->GetExtantDoc()); bool privileged = nsContentUtils::IsChromeDoc(aWindow->GetExtantDoc());
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess(aOnSuccess); nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
MediaStreamConstraints c(aConstraints); // copy MediaStreamConstraints c(aConstraints); // copy
@ -1640,11 +1668,11 @@ MediaManager::GetUserMedia(
if (c.mFake) { if (c.mFake) {
// Fake stream from default backend. // Fake stream from default backend.
task = new GetUserMediaTask(c, onSuccess.forget(), task = new GetUserMediaTask(c, onSuccess.forget(),
onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault()); onFailure.forget(), windowID, listener, mPrefs, new MediaEngineDefault());
} else { } else {
// Stream from default device from WebRTC backend. // Stream from default device from WebRTC backend.
task = new GetUserMediaTask(c, onSuccess.forget(), task = new GetUserMediaTask(c, onSuccess.forget(),
onError.forget(), windowID, listener, mPrefs); onFailure.forget(), windowID, listener, mPrefs);
} }
nsIURI* docURI = aWindow->GetDocumentURI(); nsIURI* docURI = aWindow->GetDocumentURI();
@ -1655,10 +1683,10 @@ MediaManager::GetUserMedia(
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) { if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
if (tc.mMediaSource == dom::MediaSourceEnum::Browser) { if (tc.mMediaSource == dom::MediaSourceEnum::Browser) {
if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) { 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)) { } 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 /* Deny screensharing if the requesting document is not from a host
on the whitelist. */ on the whitelist. */
@ -1676,7 +1704,7 @@ MediaManager::GetUserMedia(
) || ) ||
#endif #endif
(!privileged && !HostHasPermission(*docURI))) { (!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) && if ((!IsOn(c.mAudio) || audioPerm == nsIPermissionManager::DENY_ACTION) &&
(!IsOn(c.mVideo) || videoPerm == 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 // Ask for user permission, and dispatch task (or not) when a response
@ -1778,16 +1806,16 @@ nsresult
MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow, MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
const MediaStreamConstraints& aConstraints, const MediaStreamConstraints& aConstraints,
nsIGetUserMediaDevicesSuccessCallback* aOnSuccess, nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
nsIDOMGetUserMediaErrorCallback* aOnError, nsIDOMGetUserMediaErrorCallback* aOnFailure,
uint64_t aInnerWindowID) uint64_t aInnerWindowID)
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); 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); NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess); nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError); nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
// Check if the preference for using loopback devices is enabled. // Check if the preference for using loopback devices is enabled.
nsAdoptingCString loopbackAudioDevice = nsAdoptingCString loopbackAudioDevice =
@ -1797,7 +1825,7 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
MediaManager::GetMessageLoop()->PostTask(FROM_HERE, MediaManager::GetMessageLoop()->PostTask(FROM_HERE,
new GetUserMediaDevicesTask( new GetUserMediaDevicesTask(
aConstraints, onSuccess.forget(), onError.forget(), aConstraints, onSuccess.forget(), onFailure.forget(),
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()), (aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
loopbackAudioDevice, loopbackVideoDevice)); loopbackAudioDevice, loopbackVideoDevice));
@ -2020,7 +2048,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
MOZ_ASSERT(len); MOZ_ASSERT(len);
if (!len) { if (!len) {
// neither audio nor video were selected // neither audio nor video were selected
task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
return NS_OK; return NS_OK;
} }
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
@ -2047,14 +2075,14 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK; return NS_OK;
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) { } else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
nsString errorMessage(NS_LITERAL_STRING("PERMISSION_DENIED")); nsString errorMessage(NS_LITERAL_STRING("PermissionDeniedError"));
if (aSubject) { if (aSubject) {
nsCOMPtr<nsISupportsString> msg(do_QueryInterface(aSubject)); nsCOMPtr<nsISupportsString> msg(do_QueryInterface(aSubject));
MOZ_ASSERT(msg); MOZ_ASSERT(msg);
msg->GetData(errorMessage); msg->GetData(errorMessage);
if (errorMessage.IsEmpty()) if (errorMessage.IsEmpty())
errorMessage.AssignLiteral(MOZ_UTF16("UNKNOWN_ERROR")); errorMessage.AssignLiteral(MOZ_UTF16("InternalError"));
} }
nsString key(aData); nsString key(aData);

Просмотреть файл

@ -26,6 +26,7 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/dom/MediaStreamBinding.h" #include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
#include "prlog.h" #include "prlog.h"
#include "DOMMediaStream.h" #include "DOMMediaStream.h"
@ -268,7 +269,7 @@ class GetUserMediaNotificationEvent: public nsRunnable
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError) already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
: mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback), : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID), mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID),
mError(aError) {} mOnFailure(aError) {}
virtual ~GetUserMediaNotificationEvent() virtual ~GetUserMediaNotificationEvent()
{ {
@ -284,7 +285,7 @@ class GetUserMediaNotificationEvent: public nsRunnable
bool mIsAudio; bool mIsAudio;
bool mIsVideo; bool mIsVideo;
uint64_t mWindowID; uint64_t mWindowID;
nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError; nsRefPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
}; };
typedef enum { typedef enum {
@ -298,24 +299,24 @@ class MediaManager;
class GetUserMediaTask; class GetUserMediaTask;
/** /**
* Send an error back to content. The error is the form a string. * Send an error back to content.
* Do this only on the main thread. The success callback is also passed here * Do this only on the main thread. The onSuccess callback is also passed here
* so it can be released correctly. * so it can be released correctly.
*/ */
class ErrorCallbackRunnable : public nsRunnable class ErrorCallbackRunnable : public nsRunnable
{ {
public: public:
ErrorCallbackRunnable( ErrorCallbackRunnable(
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess, nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError, nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
const nsAString& aErrorMsg, uint64_t aWindowID); MediaMgrError& aError, uint64_t aWindowID);
NS_IMETHOD Run(); NS_IMETHOD Run();
private: private:
~ErrorCallbackRunnable(); ~ErrorCallbackRunnable();
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
const nsString mErrorMsg; nsRefPtr<MediaMgrError> mError;
uint64_t mWindowID; uint64_t mWindowID;
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
}; };
@ -357,7 +358,7 @@ public:
, mListener(aListener) , mListener(aListener)
, mBool(aBool) , mBool(aBool)
, mWindowID(aWindowID) , mWindowID(aWindowID)
, mError(aError) , mOnFailure(aError)
{} {}
~MediaOperationTask() ~MediaOperationTask()
@ -373,10 +374,12 @@ public:
mOnTracksAvailableCallback.forget())); mOnTracksAvailableCallback.forget()));
nsString log; nsString log;
log.AssignASCII(errorLog, strlen(errorLog)); log.AssignASCII(errorLog);
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success; nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
NS_DispatchToMainThread(new ErrorCallbackRunnable(success, mError, nsRefPtr<MediaMgrError> error = new MediaMgrError(
log, mWindowID)); NS_LITERAL_STRING("InternalError"), log);
NS_DispatchToMainThread(new ErrorCallbackRunnable(onSuccess, mOnFailure,
*error, mWindowID));
} }
void void
@ -428,7 +431,7 @@ public:
mOnTracksAvailableCallback.forget(), mOnTracksAvailableCallback.forget(),
mAudioSource != nullptr, mAudioSource != nullptr,
mVideoSource != nullptr, mVideoSource != nullptr,
mWindowID, mError.forget()); mWindowID, mOnFailure.forget());
// event must always be released on mainthread due to the JS callbacks // event must always be released on mainthread due to the JS callbacks
// in the TracksAvailableCallback // in the TracksAvailableCallback
NS_DispatchToMainThread(event); NS_DispatchToMainThread(event);
@ -490,7 +493,7 @@ private:
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
bool mBool; bool mBool;
uint64_t mWindowID; uint64_t mWindowID;
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError; nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
}; };
typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners; typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;

Просмотреть файл

@ -17,6 +17,7 @@
#include "GetUserMediaRequest.h" #include "GetUserMediaRequest.h"
#include "mozilla/dom/PBrowserChild.h" #include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
#include "nsISupportsPrimitives.h" #include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsArrayUtils.h" #include "nsArrayUtils.h"
@ -224,7 +225,7 @@ MediaPermissionRequest::Cancel()
{ {
nsString callID; nsString callID;
mRequest->GetCallID(callID); mRequest->GetCallID(callID);
NotifyPermissionDeny(callID, NS_LITERAL_STRING("Permission Denied")); NotifyPermissionDeny(callID, NS_LITERAL_STRING("PermissionDeniedError"));
return NS_OK; return NS_OK;
} }
@ -393,9 +394,17 @@ NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
// nsIDOMGetUserMediaErrorCallback method // nsIDOMGetUserMediaErrorCallback method
NS_IMETHODIMP 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 } // 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(); 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; } bool IsMediaSeekable() { return true; }
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE; nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;

Просмотреть файл

@ -143,6 +143,8 @@ EXPORTS.mozilla.dom += [
'AudioTrack.h', 'AudioTrack.h',
'AudioTrackList.h', 'AudioTrackList.h',
'GetUserMediaRequest.h', 'GetUserMediaRequest.h',
'MediaDevices.h',
'MediaStreamError.h',
'MediaStreamTrack.h', 'MediaStreamTrack.h',
'TextTrack.h', 'TextTrack.h',
'TextTrackCue.h', 'TextTrackCue.h',
@ -177,10 +179,12 @@ UNIFIED_SOURCES += [
'MediaDecoderReader.cpp', 'MediaDecoderReader.cpp',
'MediaDecoderStateMachine.cpp', 'MediaDecoderStateMachine.cpp',
'MediaDecoderStateMachineScheduler.cpp', 'MediaDecoderStateMachineScheduler.cpp',
'MediaDevices.cpp',
'MediaManager.cpp', 'MediaManager.cpp',
'MediaRecorder.cpp', 'MediaRecorder.cpp',
'MediaResource.cpp', 'MediaResource.cpp',
'MediaShutdownManager.cpp', 'MediaShutdownManager.cpp',
'MediaStreamError.cpp',
'MediaStreamGraph.cpp', 'MediaStreamGraph.cpp',
'MediaStreamTrack.cpp', 'MediaStreamTrack.cpp',
'MediaTaskQueue.cpp', 'MediaTaskQueue.cpp',

Просмотреть файл

@ -34,5 +34,5 @@ interface nsIDOMGetUserMediaSuccessCallback : nsISupports
[scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)] [scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)]
interface nsIDOMGetUserMediaErrorCallback : nsISupports 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", { message: "unknown required constraint on video fails",
constraints: { video: { somethingUnknown:0, require:["somethingUnknown"] }, constraints: { video: { somethingUnknown:0, require:["somethingUnknown"] },
fake: true }, fake: true },
error: "NO_DEVICES_FOUND" }, error: "NotFoundError" },
{ message: "unknown required constraint on audio fails", { message: "unknown required constraint on audio fails",
constraints: { audio: { somethingUnknown:0, require:["somethingUnknown"] }, constraints: { audio: { somethingUnknown:0, require:["somethingUnknown"] },
fake: true }, fake: true },
error: "NO_DEVICES_FOUND" }, error: "NotFoundError" },
{ message: "video overconstrained by facingMode fails", { message: "video overconstrained by facingMode fails",
constraints: { video: { facingMode:'left', require:["facingMode"] }, constraints: { video: { facingMode:'left', require:["facingMode"] },
fake: true }, fake: true },
error: "NO_DEVICES_FOUND" }, error: "NotFoundError" },
{ message: "audio overconstrained by facingMode fails", { message: "audio overconstrained by facingMode fails",
constraints: { audio: { facingMode:'left', require:["facingMode"] }, constraints: { audio: { facingMode:'left', require:["facingMode"] },
fake: true }, fake: true },
error: "NO_DEVICES_FOUND" }, error: "NotFoundError" },
{ message: "Success-path: optional video facingMode + audio ignoring facingMode", { message: "Success-path: optional video facingMode + audio ignoring facingMode",
constraints: { fake: true, constraints: { fake: true,
audio: { facingMode:'left', audio: { facingMode:'left',
@ -48,29 +48,27 @@ var common_tests = [
/** /**
* Starts the test run by running through each constraint * 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) { function testConstraints(tests) {
var i = 0; function testgum(p, test) {
next(); 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() { var p = new Promise(function(resolve) { resolve(); });
ok(!tests[i].error, tests[i].message); tests.forEach(function(test) {
i++; p = testgum(p, test);
next(); });
} p.catch(function(reason) {
function Failure(err) { ok(false, "Unexpected failure: " + reason.message);
ok(tests[i].error? (err === tests[i].error) : false, })
tests[i].message + " (err=" + err + ")"); .then(SimpleTest.finish);
i++; }
next();
}
function next() {
if (i < tests.length) {
navigator.mozGetUserMedia(tests[i].constraints, Success, Failure);
} else {
SimpleTest.finish();
}
}
};

Просмотреть файл

@ -26,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882145
var mobile_tests = [ var mobile_tests = [
{ message: "legacy facingMode overconstrains video (mobile)", { message: "legacy facingMode overconstrains video (mobile)",
constraints: { video: { mandatory: { facingMode:'left' } }, fake: true }, constraints: { video: { mandatory: { facingMode:'left' } }, fake: true },
error: "NO_DEVICES_FOUND" }, error: "NotFoundError" },
]; ];
runTest(function () { runTest(function () {

Просмотреть файл

@ -26,7 +26,7 @@ function theTest() {
config.peerIdentity = 'user@example.com'; config.peerIdentity = 'user@example.com';
} }
info('getting media with constraints: ' + JSON.stringify(config)); info('getting media with constraints: ' + JSON.stringify(config));
navigator.mozGetUserMedia(config, function(stream) { navigator.mediaDevices.getUserMedia(config).then(function(stream) {
var oneDone = false; var oneDone = false;
function checkDone() { function checkDone() {
if (oneDone) { if (oneDone) {
@ -38,7 +38,8 @@ function theTest() {
var cancelVideoCheck = videoIsBlack(withConstraint, stream, checkDone); var cancelVideoCheck = videoIsBlack(withConstraint, stream, checkDone);
setTimeout(cancelAudioCheck, 3*60*1000); setTimeout(cancelAudioCheck, 3*60*1000);
setTimeout(cancelVideoCheck, 3*60*1000); setTimeout(cancelVideoCheck, 3*60*1000);
}, function(e) { })
.catch(function(e) {
ok(false, 'gUM error: ' + e); ok(false, 'gUM error: ' + e);
}); });
}; };

Просмотреть файл

@ -37,23 +37,23 @@
var track = stream.getVideoTracks()[0]; var track = stream.getVideoTracks()[0];
var sender = test.pcLocal._pc.getSenders().find(isSenderOfTrack, track); var sender = test.pcLocal._pc.getSenders().find(isSenderOfTrack, track);
ok(sender, "track has a sender"); 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]; var newtrack = newStream.getVideoTracks()[0];
sender.replaceTrack(newtrack, return new Promise(function(resolve, reject) {
function() { sender.replaceTrack(newtrack, function() {
ok(true, "replaceTrack success callback is called"); resolve(newtrack);
is(sender.track, newtrack, "sender.track has been replaced"); }, reject);
test.next(); });
}, })
function(err) { .then(function(newtrack) {
ok(false, "replaceTrack failed with error = " + err); ok(true, "replaceTrack success callback is called");
test.next(); is(sender.track, newtrack, "sender.track has been replaced");
}); })
}, .catch(function(reason) {
function(err) { ok(false, "unexpected error = " + reason.message);
ok(false, "mozGetUserMedia failed. error = " + err); })
test.next(); .then(test.next.bind(test));
});
} }
]]); ]]);
test.chain.append(flowtest); test.chain.append(flowtest);

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/dom/SpeechRecognitionBinding.h" #include "mozilla/dom/SpeechRecognitionBinding.h"
#include "mozilla/dom/MediaStreamTrackBinding.h" #include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/MediaStreamError.h"
#include "mozilla/MediaManager.h" #include "mozilla/MediaManager.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
@ -23,6 +24,11 @@
#include <algorithm> #include <algorithm>
// Undo the windows.h damage
#if defined(XP_WIN) && defined(GetMessage)
#undef GetMessage
#endif
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -945,19 +951,26 @@ SpeechRecognition::GetUserMediaSuccessCallback::OnSuccess(nsISupports* aStream)
NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMediaErrorCallback) NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMediaErrorCallback)
NS_IMETHODIMP 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; SpeechRecognitionErrorCode errorCode;
if (aError.EqualsLiteral("PERMISSION_DENIED")) { nsString name;
error->GetName(name);
if (name.EqualsLiteral("PERMISSION_DENIED")) {
errorCode = SpeechRecognitionErrorCode::Not_allowed; errorCode = SpeechRecognitionErrorCode::Not_allowed;
} else { } else {
errorCode = SpeechRecognitionErrorCode::Audio_capture; errorCode = SpeechRecognitionErrorCode::Audio_capture;
} }
nsString message;
error->GetMessage(message);
mRecognition->DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR, errorCode, mRecognition->DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR, errorCode,
aError); message);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/dom/OwningNonNull.h" #include "mozilla/dom/OwningNonNull.h"
#include "mozilla/dom/PromiseBinding.h" #include "mozilla/dom/PromiseBinding.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/MediaStreamError.h"
#include "mozilla/CycleCollectedJSRuntime.h" #include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "PromiseCallback.h" #include "PromiseCallback.h"
@ -354,6 +355,11 @@ Promise::MaybeReject(JSContext* aCx,
MaybeRejectInternal(aCx, aValue); MaybeRejectInternal(aCx, aValue);
} }
void
Promise::MaybeReject(const nsRefPtr<MediaStreamError>& aArg) {
MaybeSomething(aArg, &Promise::MaybeReject);
}
void void
Promise::PerformMicroTaskCheckpoint() Promise::PerformMicroTaskCheckpoint()
{ {

Просмотреть файл

@ -29,6 +29,7 @@ namespace dom {
class AnyCallback; class AnyCallback;
class DOMError; class DOMError;
class MediaStreamError;
class PromiseCallback; class PromiseCallback;
class PromiseInit; class PromiseInit;
class PromiseNativeHandler; class PromiseNativeHandler;
@ -99,6 +100,9 @@ public:
MOZ_ASSERT(NS_FAILED(aArg)); MOZ_ASSERT(NS_FAILED(aArg));
MaybeSomething(aArg, &Promise::MaybeReject); MaybeSomething(aArg, &Promise::MaybeReject);
} }
void MaybeReject(const nsRefPtr<MediaStreamError>& aArg);
// DO NOT USE MaybeRejectBrokenly with in new code. Promises should be // DO NOT USE MaybeRejectBrokenly with in new code. Promises should be
// rejected with Error instances. // rejected with Error instances.
// Note: MaybeRejectBrokenly is a template so we can use it with DOMError // Note: MaybeRejectBrokenly is a template so we can use it with DOMError

Просмотреть файл

@ -1101,7 +1101,7 @@ QuotaManager::DecreaseUsageForOrigin(PersistenceType aPersistenceType,
const nsACString& aOrigin, const nsACString& aOrigin,
int64_t aSize) int64_t aSize)
{ {
AssertIsOnIOThread(); MOZ_ASSERT(!NS_IsMainThread());
MutexAutoLock lock(mQuotaMutex); MutexAutoLock lock(mQuotaMutex);

Просмотреть файл

@ -81,6 +81,34 @@ SVGCircleElement::GetLengthInfo()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGPathGeometryElement methods // 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> TemporaryRef<Path>
SVGCircleElement::BuildPath(PathBuilder* aBuilder) SVGCircleElement::BuildPath(PathBuilder* aBuilder)
{ {

Просмотреть файл

@ -30,6 +30,8 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE; virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

Просмотреть файл

@ -92,6 +92,35 @@ SVGEllipseElement::GetLengthInfo()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGPathGeometryElement methods // 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> TemporaryRef<Path>
SVGEllipseElement::BuildPath(PathBuilder* aBuilder) SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
{ {

Просмотреть файл

@ -30,6 +30,8 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE; virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods: // nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE; virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

Просмотреть файл

@ -70,6 +70,12 @@ public:
virtual bool IsMarkable(); virtual bool IsMarkable();
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks); 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, virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) { const Matrix& aTransform) {
return false; return false;

Просмотреть файл

@ -635,6 +635,8 @@ var interfaceNamesInGlobalScope =
"LocalMediaStream", "LocalMediaStream",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"Location", "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! // IMPORTANT: Do not change this list without review from a DOM peer!
"MediaElementAudioSourceNode", "MediaElementAudioSourceNode",
// IMPORTANT: Do not change this list without review from a DOM peer! // 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 #ifdef MOZ_MEDIA_NAVIGATOR
callback NavigatorUserMediaSuccessCallback = void (MediaStream stream); callback NavigatorUserMediaSuccessCallback = void (MediaStream stream);
callback NavigatorUserMediaErrorCallback = void (DOMString error); callback NavigatorUserMediaErrorCallback = void (MediaStreamError error);
partial interface Navigator { partial interface Navigator {
[Throws, Func="Navigator::HasUserMediaSupport"]
readonly attribute MediaDevices mediaDevices;
// Deprecated. Use mediaDevices.getUserMedia instead.
[Throws, Func="Navigator::HasUserMediaSupport"] [Throws, Func="Navigator::HasUserMediaSupport"]
void mozGetUserMedia(MediaStreamConstraints constraints, void mozGetUserMedia(MediaStreamConstraints constraints,
NavigatorUserMediaSuccessCallback successCallback, NavigatorUserMediaSuccessCallback successCallback,

Просмотреть файл

@ -255,6 +255,7 @@ WEBIDL_FILES = [
'ListBoxObject.webidl', 'ListBoxObject.webidl',
'LocalMediaStream.webidl', 'LocalMediaStream.webidl',
'Location.webidl', 'Location.webidl',
'MediaDevices.webidl',
'MediaElementAudioSourceNode.webidl', 'MediaElementAudioSourceNode.webidl',
'MediaError.webidl', 'MediaError.webidl',
'MediaList.webidl', 'MediaList.webidl',
@ -264,6 +265,7 @@ WEBIDL_FILES = [
'MediaStream.webidl', 'MediaStream.webidl',
'MediaStreamAudioDestinationNode.webidl', 'MediaStreamAudioDestinationNode.webidl',
'MediaStreamAudioSourceNode.webidl', 'MediaStreamAudioSourceNode.webidl',
'MediaStreamError.webidl',
'MediaStreamTrack.webidl', 'MediaStreamTrack.webidl',
'MediaTrackConstraintSet.webidl', 'MediaTrackConstraintSet.webidl',
'MenuBoxObject.webidl', 'MenuBoxObject.webidl',

Просмотреть файл

@ -45,6 +45,52 @@ class AutoRestoreTransform
Matrix mOldTransform; 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 gfx
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -7,6 +7,7 @@
#include <math.h> #include <math.h>
#include "DrawTargetCG.h" #include "DrawTargetCG.h"
#include "Logging.h" #include "Logging.h"
#include "PathHelpers.h"
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
@ -68,6 +69,10 @@ void
PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle, PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
Float aEndAngle, bool aAntiClockwise) 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 // 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 // y-axis down. Core Graphics therefore considers "clockwise" to mean "sweep
// in the direction of decreasing angle" whereas Moz2D considers it to mean // 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, aStartAngle,
aEndAngle, aEndAngle,
aAntiClockwise); aAntiClockwise);
#endif
ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
aAntiClockwise);
} }
Point Point

Просмотреть файл

@ -14,7 +14,6 @@ TransGaming Inc.
Adobe Systems Inc. Adobe Systems Inc.
Autodesk, Inc. Autodesk, Inc.
BlackBerry Limited BlackBerry Limited
Borbitsoft
Cable Television Laboratories, Inc. Cable Television Laboratories, Inc.
Cloud Party, Inc. Cloud Party, Inc.
Intel Corporation Intel Corporation
@ -22,10 +21,12 @@ Mozilla Corporation
Turbulenz Turbulenz
Klarälvdalens Datakonsult AB Klarälvdalens Datakonsult AB
Microsoft Open Technologies, Inc. Microsoft Open Technologies, Inc.
NVIDIA Corporation
Jacek Caban Jacek Caban
Mark Callow Mark Callow
Ginn Chen Ginn Chen
Tibor den Ouden
James Hauxwell James Hauxwell
Sam Hocevar Sam Hocevar
Pierre Leveille Pierre Leveille

Просмотреть файл

@ -49,9 +49,6 @@ Adobe Systems Inc.
Autodesk, Inc. Autodesk, Inc.
Ranger Harke Ranger Harke
Borbitsoft
Tibor den Ouden
Cloud Party, Inc. Cloud Party, Inc.
Conor Dickinson Conor Dickinson
@ -82,7 +79,11 @@ Ulrik Persson (ddefrostt)
Mark Banner (standard8mbp) Mark Banner (standard8mbp)
David Kilzer David Kilzer
Jacek Caban Jacek Caban
Tibor den Ouden
Microsoft Open Technologies, Inc. Microsoft Open Technologies, Inc.
Cooper Partin Cooper Partin
Austin Kinross Austin Kinross
NVIDIA Corporation
Olli Etuaho

Просмотреть файл

@ -246,6 +246,12 @@ typedef struct
int EXT_frag_depth; int EXT_frag_depth;
int EXT_shader_texture_lod; 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. // Set to 1 if highp precision is supported in the fragment language.
// Default is 0. // Default is 0.
int FragmentPrecisionHigh; int FragmentPrecisionHigh;

Просмотреть файл

@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable
unsigned int elementCount() const { return std::max(1u, arraySize); } unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isStruct() const { return !fields.empty(); } 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 type;
GLenum precision; GLenum precision;
std::string name; std::string name;
@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable
bool staticUse; bool staticUse;
std::vector<ShaderVariable> fields; std::vector<ShaderVariable> fields;
std::string structName; 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 struct COMPILER_EXPORT Uniform : public ShaderVariable
@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
~Uniform(); ~Uniform();
Uniform(const Uniform &other); Uniform(const Uniform &other);
Uniform &operator=(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 struct COMPILER_EXPORT Attribute : public ShaderVariable
@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable
~Attribute(); ~Attribute();
Attribute(const Attribute &other); Attribute(const Attribute &other);
Attribute &operator=(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; int location;
}; };
@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
~InterfaceBlockField(); ~InterfaceBlockField();
InterfaceBlockField(const InterfaceBlockField &other); InterfaceBlockField(const InterfaceBlockField &other);
InterfaceBlockField &operator=(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; bool isRowMajorLayout;
}; };
@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
{ {
Varying(); Varying();
~Varying(); ~Varying();
Varying(const Varying &other); Varying(const Varying &otherg);
Varying &operator=(const Varying &other); 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; InterpolationType interpolation;
bool isInvariant; 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_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 "common/angleutils.h"
#include <stdio.h>
#include <vector> #include <vector>
std::string FormatString(const char *fmt, va_list vararg) std::string FormatString(const char *fmt, va_list vararg)

Просмотреть файл

@ -360,7 +360,8 @@ void TCompiler::setResourceString()
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset; << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
builtInResourcesString = strstream.str(); builtInResourcesString = strstream.str();
} }

Просмотреть файл

@ -201,6 +201,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->EXT_frag_depth = 0; resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0; resources->EXT_shader_texture_lod = 0;
resources->NV_draw_buffers = 0;
// Disable highp precision in fragment shader by default. // Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0; resources->FragmentPrecisionHigh = 0;

Просмотреть файл

@ -9,6 +9,8 @@
#include <GLSLANG/ShaderLang.h> #include <GLSLANG/ShaderLang.h>
#include "compiler/translator/compilerdebug.h"
namespace sh namespace sh
{ {
@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
return *this; 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() Uniform::Uniform()
{} {}
@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other)
return *this; 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() Attribute::Attribute()
: location(-1) : location(-1)
{} {}
@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other)
return *this; return *this;
} }
bool Attribute::operator==(const Attribute &other) const
{
return (ShaderVariable::operator==(other) &&
location == other.location);
}
InterfaceBlockField::InterfaceBlockField() InterfaceBlockField::InterfaceBlockField()
: isRowMajorLayout(false) : isRowMajorLayout(false)
{} {}
@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o
return *this; 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() Varying::Varying()
: interpolation(INTERPOLATION_SMOOTH), : interpolation(INTERPOLATION_SMOOTH),
isInvariant(false) isInvariant(false)
@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other)
return *this; 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() InterfaceBlock::InterfaceBlock()
: arraySize(0), : arraySize(0),
layout(BLOCKLAYOUT_PACKED), layout(BLOCKLAYOUT_PACKED),

Просмотреть файл

@ -37,8 +37,13 @@ void TranslatorESSL::writeExtensionBehavior() {
for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
iter != extensionBehavior.end(); ++iter) { iter != extensionBehavior.end(); ++iter) {
if (iter->second != EBhUndefined) { if (iter->second != EBhUndefined) {
sink << "#extension " << iter->first << " : " if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
<< getBehaviorString(iter->second) << "\n"; 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); bindRenderbuffer(0);
bindGenericUniformBuffer(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); bindIndexedUniformBuffer(0, i, 0, -1);
} }
bindGenericTransformFeedbackBuffer(0); 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); bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
} }
@ -119,8 +119,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
mResetStatus = GL_NO_ERROR; mResetStatus = GL_NO_ERROR;
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
mRobustAccess = robustAccess; mRobustAccess = robustAccess;
mState.setContext(this);
} }
Context::~Context() 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); 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 // if the current program was relinked successfully we
// need to install the new executables // need to install the new executables
if (linked && program == mState.getCurrentProgramId()) if (programObject->isLinked() && program == mState.getCurrentProgramId())
{ {
mState.setCurrentProgramBinary(programObject->getProgramBinary()); 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); 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 // if the current program was reloaded successfully we
// need to install the new executables // need to install the new executables
if (loaded && program == mState.getCurrentProgramId()) if (programObject->isLinked() && program == mState.getCurrentProgramId())
{ {
mState.setCurrentProgramBinary(programObject->getProgramBinary()); mState.setCurrentProgramBinary(programObject->getProgramBinary());
} }
return Error(GL_NO_ERROR);
} }
void Context::bindTransformFeedback(GLuint transformFeedback) 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 // Applies the shaders and shader constants to the Direct3D 9 device
Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
{ {
const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes();
VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); VertexFormat::GetInputLayout(inputLayout, programBinary, mState);
const Framebuffer *fbo = mState.getDrawFramebuffer(); const Framebuffer *fbo = mState.getDrawFramebuffer();
@ -1584,14 +1591,7 @@ bool Context::applyTransformFeedbackBuffers()
TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback();
if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
{ {
Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; mRenderer->applyTransformFeedbackBuffers(mState);
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);
return true; return true;
} }
else else
@ -1602,7 +1602,7 @@ bool Context::applyTransformFeedbackBuffers()
void Context::markTransformFeedbackUsage() 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); Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i);
if (buffer) if (buffer)
@ -1771,7 +1771,7 @@ Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei insta
return error; return error;
} }
error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); error = mRenderer->applyVertexBuffer(mState, first, count, instances);
if (error.isError()) if (error.isError())
{ {
return error; return error;
@ -1856,9 +1856,7 @@ Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
} }
GLsizei vertexCount = indexInfo.indexRange.length() + 1; GLsizei vertexCount = indexInfo.indexRange.length() + 1;
error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), error = mRenderer->applyVertexBuffer(mState, indexInfo.indexRange.start, vertexCount, instances);
mState.getVertexAttribCurrentValues(),
indexInfo.indexRange.start, vertexCount, instances);
if (error.isError()) if (error.isError())
{ {
return error; return error;

Просмотреть файл

@ -130,8 +130,8 @@ class Context
void bindPixelPackBuffer(GLuint buffer); void bindPixelPackBuffer(GLuint buffer);
void bindPixelUnpackBuffer(GLuint buffer); void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program); void useProgram(GLuint program);
void linkProgram(GLuint program); Error linkProgram(GLuint program);
void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
void bindTransformFeedback(GLuint transformFeedback); void bindTransformFeedback(GLuint transformFeedback);
Error beginQuery(GLenum target, GLuint query); Error beginQuery(GLenum target, GLuint query);

Просмотреть файл

@ -48,6 +48,11 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
return ImageIndex(GL_TEXTURE_3D, mipIndex, 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) ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
: type(typeIn), : type(typeIn),
mipIndex(mipIndexIn), mipIndex(mipIndexIn),

Просмотреть файл

@ -31,6 +31,7 @@ struct ImageIndex
static ImageIndex MakeCube(GLenum target, GLint mipIndex); static ImageIndex MakeCube(GLenum target, GLint mipIndex);
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
static ImageIndex MakeInvalid();
static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1); 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, // 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 // compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms // a list of uniforms
bool Program::link(const Caps &caps) Error Program::link(const Caps &caps)
{ {
unlink(false); unlink(false);
@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
resetUniformBlockBindings(); resetUniformBlockBindings();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, LinkResult result = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); 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 int AttributeBindings::getAttributeBinding(const std::string &name) const
@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
return mProgramBinary.get(); 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); unlink(false);
mInfoLog.reset(); mInfoLog.reset();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (result.error.isError())
if (!mLinked)
{ {
mProgramBinary.set(NULL); mProgramBinary.set(NULL);
return result.error;
} }
return mLinked; mLinked = result.linkSuccess;
return Error(GL_NO_ERROR);
} }
void Program::release() void Program::release()

Просмотреть файл

@ -77,9 +77,9 @@ class Program
void bindAttributeLocation(GLuint index, const char *name); void bindAttributeLocation(GLuint index, const char *name);
bool link(const Caps &caps); Error link(const Caps &caps);
bool isLinked(); bool isLinked();
bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
ProgramBinary *getProgramBinary() const; ProgramBinary *getProgramBinary() const;
int getInfoLogLength() 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; unsigned int ProgramBinary::mCurrentSerial = 1;
ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
@ -854,10 +860,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade
return true; 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 #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
return false; return LinkResult(false, Error(GL_NO_ERROR));
#else #else
ASSERT(binaryFormat == mProgram->getBinaryFormat()); ASSERT(binaryFormat == mProgram->getBinaryFormat());
@ -869,7 +875,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (format != mProgram->getBinaryFormat()) if (format != mProgram->getBinaryFormat())
{ {
infoLog.append("Invalid program binary format."); infoLog.append("Invalid program binary format.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
int majorVersion = stream.readInt<int>(); 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) if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
{ {
infoLog.append("Invalid program binary version."); infoLog.append("Invalid program binary version.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; 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) if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
{ {
infoLog.append("Invalid program binary version."); infoLog.append("Invalid program binary version.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
int compileFlags = stream.readInt<int>(); int compileFlags = stream.readInt<int>();
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{ {
infoLog.append("Mismatched compilation flags."); infoLog.append("Mismatched compilation flags.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) 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()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniforms.resize(uniformCount); mUniforms.resize(uniformCount);
@ -965,7 +971,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniformBlocks.resize(uniformBlockCount); mUniformBlocks.resize(uniformBlockCount);
@ -994,7 +1000,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
if (stream.error()) if (stream.error())
{ {
infoLog.append("Invalid program binary."); infoLog.append("Invalid program binary.");
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
mUniformIndex.resize(uniformIndexCount); mUniformIndex.resize(uniformIndexCount);
@ -1005,18 +1011,19 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
stream.readInt(&mUniformIndex[uniformIndexIndex].index); 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); mProgram->initializeUniformStorage(mUniforms);
return true; return LinkResult(true, Error(GL_NO_ERROR));
#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD #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) if (binaryFormat)
{ {
@ -1108,15 +1115,7 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
stream.writeInt(mUniformIndex[i].index); stream.writeInt(mUniformIndex[i].index);
} }
if (!mProgram->save(&stream)) mProgram->save(&stream);
{
if (length)
{
*length = 0;
}
return false;
}
GLsizei streamLength = stream.length(); GLsizei streamLength = stream.length();
const void *streamData = stream.data(); const void *streamData = stream.data();
@ -1128,7 +1127,10 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*length = 0; *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) if (binary)
@ -1146,34 +1148,33 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL
*length = streamLength; *length = streamLength;
} }
return true; return Error(GL_NO_ERROR);
} }
GLint ProgramBinary::getLength() GLint ProgramBinary::getLength()
{ {
GLint length; GLint length;
if (save(NULL, NULL, INT_MAX, &length)) Error error = save(NULL, NULL, INT_MAX, &length);
{ if (error.isError())
return length;
}
else
{ {
return 0; 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) const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
{ {
if (!fragmentShader || !fragmentShader->isCompiled()) if (!fragmentShader || !fragmentShader->isCompiled())
{ {
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
if (!vertexShader || !vertexShader->isCompiled()) if (!vertexShader || !vertexShader->isCompiled())
{ {
return false; return LinkResult(false, Error(GL_NO_ERROR));
} }
ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
@ -1187,22 +1188,21 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
int registers; int registers;
std::vector<LinkedVarying> linkedVaryings; std::vector<LinkedVarying> linkedVaryings;
if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode, LinkResult result = mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
&registers, &linkedVaryings, &mOutputVariables, caps)) &registers, &linkedVaryings, &mOutputVariables, caps);
if (result.error.isError() || !result.linkSuccess)
{ {
return false; return result;
} }
bool success = true;
if (!linkAttributes(infoLog, attributeBindings, vertexShader)) if (!linkAttributes(infoLog, attributeBindings, vertexShader))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) 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) // 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)) if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
{ {
success = false; return LinkResult(false, Error(GL_NO_ERROR));
} }
if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), caps)) 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.
result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
if (result.error.isError() || !result.linkSuccess)
{ {
// TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, infoLog.append("Failed to create D3D shaders.");
// however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. reset();
if (!mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers)) return result;
{
infoLog.append("Failed to create D3D shaders.");
success = false;
reset();
}
} }
return success; return LinkResult(true, Error(GL_NO_ERROR));
} }
// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices

Просмотреть файл

@ -86,6 +86,14 @@ struct LinkedVarying
unsigned int semanticIndexCount; 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. // This is the result of linking a program. It is the state that would be passed to ProgramBinary.
class ProgramBinary : public RefCountObject class ProgramBinary : public RefCountObject
{ {
@ -138,12 +146,13 @@ class ProgramBinary : public RefCountObject
Error applyUniforms(); Error applyUniforms();
Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps); Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
GLint getLength(); GLint getLength();
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, LinkResult link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
const Caps &caps);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;

Просмотреть файл

@ -22,6 +22,8 @@ namespace gl
State::State() State::State()
{ {
mMaxDrawBuffers = 0;
mMaxCombinedTextureImageUnits = 0;
} }
State::~State() State::~State()
@ -31,7 +33,8 @@ State::~State()
void State::initialize(const Caps& caps, GLuint clientVersion) 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); setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
mActiveSampler = 0; mActiveSampler = 0;
const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 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); mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
} }
mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
if (clientVersion >= 3) if (clientVersion >= 3)
@ -153,12 +160,6 @@ void State::reset()
mSamplers[samplerIdx].set(NULL); 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); mArrayBuffer.set(NULL);
mRenderbuffer.set(NULL); mRenderbuffer.set(NULL);
@ -170,15 +171,15 @@ void State::reset()
} }
mGenericUniformBuffer.set(NULL); 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 (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
{ {
mTransformFeedbackBuffers[i].set(NULL); bufItr->set(NULL);
} }
mCopyReadBuffer.set(NULL); mCopyReadBuffer.set(NULL);
@ -947,14 +948,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt
GLuint State::getIndexedUniformBufferId(GLuint index) const 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(); return mUniformBuffers[index].id();
} }
Buffer *State::getIndexedUniformBuffer(GLuint index) const 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(); return mUniformBuffers[index].get();
} }
@ -971,25 +972,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe
GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const 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(); return mTransformFeedbackBuffers[index].id();
} }
Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const 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(); return mTransformFeedbackBuffers[index].get();
} }
GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const 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(); return mTransformFeedbackBuffers[index].getOffset();
} }
size_t State::getTransformFeedbackBufferIndexRange() const
{
return mTransformFeedbackBuffers.size();
}
void State::setCopyReadBufferBinding(Buffer *buffer) void State::setCopyReadBufferBinding(Buffer *buffer)
{ {
mCopyReadBuffer.set(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]) 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); mVertexAttribCurrentValues[index].setFloatValues(values);
} }
void State::setVertexAttribu(GLuint index, const GLuint values[4]) 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); mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
} }
void State::setVertexAttribi(GLuint index, const GLint values[4]) 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); mVertexAttribCurrentValues[index].setIntValues(values);
} }
@ -1062,15 +1068,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(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]; return mVertexAttribCurrentValues[attribNum];
} }
const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const
{
return mVertexAttribCurrentValues;
}
const void *State::getVertexAttribPointer(unsigned int attribNum) const const void *State::getVertexAttribPointer(unsigned int attribNum) const
{ {
return getVertexArray()->getVertexAttribute(attribNum).pointer; 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) if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
{ {
unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers); ASSERT(colorAttachment < mMaxDrawBuffers);
Framebuffer *framebuffer = mDrawFramebuffer; Framebuffer *framebuffer = mDrawFramebuffer;
*params = framebuffer->getDrawBufferState(colorAttachment); *params = framebuffer->getDrawBufferState(colorAttachment);
return; return;
@ -1332,19 +1333,19 @@ void State::getIntegerv(GLenum pname, GLint *params)
} }
break; break;
case GL_TEXTURE_BINDING_2D: case GL_TEXTURE_BINDING_2D:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
break; break;
case GL_TEXTURE_BINDING_CUBE_MAP: case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
break; break;
case GL_TEXTURE_BINDING_3D: case GL_TEXTURE_BINDING_3D:
ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits); ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
break; break;
case GL_TEXTURE_BINDING_2D_ARRAY: case GL_TEXTURE_BINDING_2D_ARRAY:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
break; break;
case GL_UNIFORM_BUFFER_BINDING: case GL_UNIFORM_BUFFER_BINDING:
@ -1376,13 +1377,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: 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(); *data = mTransformFeedbackBuffers[index].id();
} }
break; break;
case GL_UNIFORM_BUFFER_BINDING: 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(); *data = mUniformBuffers[index].id();
} }
@ -1399,25 +1400,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER_START: 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(); *data = mTransformFeedbackBuffers[index].getOffset();
} }
break; break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: 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(); *data = mTransformFeedbackBuffers[index].getSize();
} }
break; break;
case GL_UNIFORM_BUFFER_START: 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(); *data = mUniformBuffers[index].getOffset();
} }
break; break;
case GL_UNIFORM_BUFFER_SIZE: 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(); *data = mUniformBuffers[index].getSize();
} }
@ -1433,9 +1434,9 @@ bool State::hasMappedBuffer(GLenum target) const
{ {
if (target == GL_ARRAY_BUFFER) 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(); gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
{ {

Просмотреть файл

@ -35,8 +35,6 @@ class State
void initialize(const Caps& caps, GLuint clientVersion); void initialize(const Caps& caps, GLuint clientVersion);
void reset(); void reset();
void setContext(Context *context) { mContext = context; }
// State chunk getters // State chunk getters
const RasterizerState &getRasterizerState() const; const RasterizerState &getRasterizerState() const;
const BlendState &getBlendState() const; const BlendState &getBlendState() const;
@ -199,6 +197,7 @@ class State
GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const;
size_t getTransformFeedbackBufferIndexRange() const;
// GL_COPY_[READ/WRITE]_BUFFER // GL_COPY_[READ/WRITE]_BUFFER
void setCopyReadBufferBinding(Buffer *buffer); void setCopyReadBufferBinding(Buffer *buffer);
@ -220,7 +219,6 @@ class State
bool normalized, bool pureInteger, GLsizei stride, const void *pointer); bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const;
const void *getVertexAttribPointer(unsigned int attribNum) const; const void *getVertexAttribPointer(unsigned int attribNum) const;
// Pixel pack state manipulation // Pixel pack state manipulation
@ -247,7 +245,9 @@ class State
private: private:
DISALLOW_COPY_AND_ASSIGN(State); DISALLOW_COPY_AND_ASSIGN(State);
Context *mContext; // Cached values from Context's caps
GLuint mMaxDrawBuffers;
GLuint mMaxCombinedTextureImageUnits;
ColorF mColorClearValue; ColorF mColorClearValue;
GLclampf mDepthClearValue; GLclampf mDepthClearValue;
@ -283,7 +283,8 @@ class State
GLuint mCurrentProgramId; GLuint mCurrentProgramId;
BindingPointer<ProgramBinary> mCurrentProgramBinary; BindingPointer<ProgramBinary> mCurrentProgramBinary;
VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
VertexArray *mVertexArray; VertexArray *mVertexArray;
// Texture and sampler bindings // Texture and sampler bindings
@ -300,11 +301,12 @@ class State
ActiveQueryMap mActiveQueries; ActiveQueryMap mActiveQueries;
BindingPointer<Buffer> mGenericUniformBuffer; BindingPointer<Buffer> mGenericUniformBuffer;
OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; typedef std::vector< OffsetBindingPointer<Buffer> > BufferVector;
BufferVector mUniformBuffers;
BindingPointer<TransformFeedback> mTransformFeedback; BindingPointer<TransformFeedback> mTransformFeedback;
BindingPointer<Buffer> mGenericTransformFeedbackBuffer; BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; BufferVector mTransformFeedbackBuffers;
BindingPointer<Buffer> mCopyReadBuffer; BindingPointer<Buffer> mCopyReadBuffer;
BindingPointer<Buffer> mCopyWriteBuffer; BindingPointer<Buffer> mCopyWriteBuffer;

Просмотреть файл

@ -9,6 +9,8 @@
#include "libGLESv2/angletypes.h" #include "libGLESv2/angletypes.h"
#include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/VertexAttribute.h" #include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/State.h"
#include "libGLESv2/VertexArray.h"
namespace gl namespace gl
{ {
@ -148,16 +150,16 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp
void VertexFormat::GetInputLayout(VertexFormat *inputLayout, void VertexFormat::GetInputLayout(VertexFormat *inputLayout,
ProgramBinary *programBinary, ProgramBinary *programBinary,
const VertexAttribute *attributes, const State &state)
const gl::VertexAttribCurrentValueData *currentValues)
{ {
const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes();
for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{ {
int semanticIndex = programBinary->getSemanticIndex(attributeIndex); int semanticIndex = programBinary->getSemanticIndex(attributeIndex);
if (semanticIndex != -1) 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 namespace gl
{ {
class Buffer; class Buffer;
class State;
class ProgramBinary; class ProgramBinary;
struct VertexAttribute; struct VertexAttribute;
struct VertexAttribCurrentValueData; struct VertexAttribCurrentValueData;
@ -229,8 +230,7 @@ struct VertexFormat
static void GetInputLayout(VertexFormat *inputLayout, static void GetInputLayout(VertexFormat *inputLayout,
ProgramBinary *programBinary, ProgramBinary *programBinary,
const VertexAttribute *attributes, const State& currentValues);
const gl::VertexAttribCurrentValueData *currentValues);
bool operator==(const VertexFormat &other) const; bool operator==(const VertexFormat &other) const;
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; 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; return;
} }
} }
@ -8433,7 +8439,12 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
return; 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. // surfaces or resources.
#include "libGLESv2/renderer/Image.h" #include "libGLESv2/renderer/Image.h"
#include "libGLESv2/Framebuffer.h"
#include "libGLESv2/main.h"
namespace rx namespace rx
{ {
@ -25,4 +27,18 @@ Image::Image()
mDirty = false; 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 namespace gl
{ {
class Framebuffer; class Framebuffer;
struct Rectangle;
struct ImageIndex;
} }
namespace rx namespace rx
{ {
class Renderer; class Renderer;
class RenderTarget;
class TextureStorage;
class Image class Image
{ {
@ -51,7 +54,10 @@ class Image
virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
const void *input) = 0; 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: protected:
GLsizei mWidth; GLsizei mWidth;

Просмотреть файл

@ -32,16 +32,16 @@ public:
virtual sh::Attribute *getShaderAttributes() = 0; virtual sh::Attribute *getShaderAttributes() = 0;
virtual GLenum getBinaryFormat() = 0; virtual GLenum getBinaryFormat() = 0;
virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual bool save(gl::BinaryOutputStream *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; 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, const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0; std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) = 0;
virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0; virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;

Просмотреть файл

@ -132,10 +132,9 @@ class Renderer
bool rasterizerDiscard, bool transformFeedbackActive) = 0; bool rasterizerDiscard, bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0; virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0;
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 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 drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
@ -197,12 +196,13 @@ class Renderer
// Shader operations // Shader operations
virtual void releaseShaderCompiler() = 0; 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, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) = 0; bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type, virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, 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; virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
// Image operations // Image operations

Просмотреть файл

@ -26,10 +26,12 @@ enum D3DWorkaroundType
struct Workarounds struct Workarounds
{ {
Workarounds() Workarounds()
: mrtPerfWorkaround(false) : mrtPerfWorkaround(false),
setDataFasterThanImageUpload(false)
{} {}
bool mrtPerfWorkaround; 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, gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
const std::vector<CompileConfig> &configs) const const std::vector<CompileConfig> &configs, ID3DBlob **outCompiledBlob) const
{ {
ASSERT(mD3DCompilerModule && mD3DCompileFunc); ASSERT(mD3DCompilerModule && mD3DCompileFunc);
@ -115,13 +115,15 @@ ID3DBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
return binary; *outCompiledBlob = binary;
return gl::Error(GL_NO_ERROR);
} }
else else
{ {
if (result == E_OUTOFMEMORY) 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()); 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_ #ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ #define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/platform.h" #include "common/platform.h"
@ -33,8 +35,10 @@ class HLSLCompiler
bool initialize(); bool initialize();
void release(); void release();
ID3DBlob *compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
const std::vector<CompileConfig> &configs) const; // 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: private:
DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);

Просмотреть файл

@ -17,6 +17,8 @@
namespace gl namespace gl
{ {
class Framebuffer; class Framebuffer;
struct ImageIndex;
struct Box;
} }
namespace rx namespace rx
@ -37,10 +39,10 @@ class ImageD3D : public Image
virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {}; virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {};
virtual void setManagedSurface3D(TextureStorage *storage, int level) {}; virtual void setManagedSurface3D(TextureStorage *storage, int level) {};
virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, 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 copyToStorage2D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
virtual gl::Error copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; virtual gl::Error copyToStorageCube(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 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 copyToStorage3D(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
virtual gl::Error copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; virtual gl::Error copyToStorage2DArray(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(ImageD3D); DISALLOW_COPY_AND_ASSIGN(ImageD3D);

Просмотреть файл

@ -147,7 +147,7 @@ bool ProgramD3D::usesGeometryShader() const
return usesPointSpriteEmulation(); return usesPointSpriteEmulation();
} }
bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
{ {
stream->readInt(&mShaderVersion); stream->readInt(&mShaderVersion);
@ -201,14 +201,22 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
unsigned int vertexShaderSize = stream->readInt<unsigned int>(); unsigned int vertexShaderSize = stream->readInt<unsigned int>();
const unsigned char *vertexShaderFunction = binary + stream->offset(); const unsigned char *vertexShaderFunction = binary + stream->offset();
ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
SHADER_VERTEX, ShaderExecutable *shaderExecutable = NULL;
mTransformFeedbackLinkedVaryings, gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); SHADER_VERTEX,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
&shaderExecutable);
if (error.isError())
{
return gl::LinkResult(false, error);
}
if (!shaderExecutable) if (!shaderExecutable)
{ {
infoLog.append("Could not create vertex shader."); infoLog.append("Could not create vertex shader.");
return false; return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
} }
// generated converted input layout // 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 size_t pixelShaderSize = stream->readInt<unsigned int>();
const unsigned char *pixelShaderFunction = binary + stream->offset(); const unsigned char *pixelShaderFunction = binary + stream->offset();
ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, ShaderExecutable *shaderExecutable = NULL;
SHADER_PIXEL, gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
mTransformFeedbackLinkedVaryings, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
&shaderExecutable);
if (error.isError())
{
return gl::LinkResult(false, error);
}
if (!shaderExecutable) if (!shaderExecutable)
{ {
infoLog.append("Could not create pixel shader."); infoLog.append("Could not create pixel shader.");
return false; return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
} }
// add new binary // add new binary
@ -255,15 +268,19 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
if (geometryShaderSize > 0) if (geometryShaderSize > 0)
{ {
const unsigned char *geometryShaderFunction = binary + stream->offset(); const unsigned char *geometryShaderFunction = binary + stream->offset();
mGeometryExecutable = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); &mGeometryExecutable);
if (error.isError())
{
return gl::LinkResult(false, error);
}
if (!mGeometryExecutable) if (!mGeometryExecutable)
{ {
infoLog.append("Could not create geometry shader."); infoLog.append("Could not create geometry shader.");
return false; return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
} }
stream->skip(geometryShaderSize); stream->skip(geometryShaderSize);
} }
@ -275,13 +292,13 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
{ {
infoLog.append("Invalid program binary."); 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); stream->writeInt(mShaderVersion);
@ -367,12 +384,12 @@ bool ProgramD3D::save(gl::BinaryOutputStream *stream)
} }
GUID binaryIdentifier = mRenderer->getAdapterIdentifier(); GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID)); 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; 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++) for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
{ {
if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) 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 // Generate new pixel executable
gl::InfoLog tempInfoLog; gl::InfoLog tempInfoLog;
ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL, ShaderExecutable *pixelExecutable = NULL;
mTransformFeedbackLinkedVaryings, gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), mTransformFeedbackLinkedVaryings,
mPixelWorkarounds); (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
mPixelWorkarounds, &pixelExecutable);
if (error.isError())
{
return error;
}
if (!pixelExecutable) if (!pixelExecutable)
{ {
@ -426,10 +449,11 @@ ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(const std::vecto
mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); 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]; GLenum signature[gl::MAX_VERTEX_ATTRIBS];
getInputLayoutSignature(inputLayout, signature); getInputLayoutSignature(inputLayout, signature);
@ -438,7 +462,8 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::Vertex
{ {
if (mVertexExecutables[executableIndex]->matchesSignature(signature)) 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 // Generate new vertex executable
gl::InfoLog tempInfoLog; gl::InfoLog tempInfoLog;
ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, ShaderExecutable *vertexExecutable = NULL;
SHADER_VERTEX, gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
mTransformFeedbackLinkedVaryings, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
mVertexWorkarounds); mVertexWorkarounds, &vertexExecutable);
if (error.isError())
{
return error;
}
if (!vertexExecutable) if (!vertexExecutable)
{ {
std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3); std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
@ -463,39 +493,55 @@ ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(const gl::Vertex
mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); 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) int registers)
{ {
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); 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()); 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()) if (usesGeometryShader())
{ {
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); 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), (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, const std::vector<std::string> &transformFeedbackVaryings, GLenum transformFeedbackBufferMode,
int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps) std::map<int, gl::VariableLocation> *outputVariables, const gl::Caps &caps)
{ {
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
@ -515,24 +561,24 @@ bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shad
if (*registers < 0) if (*registers < 0)
{ {
return false; return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
} }
if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) 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, if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
{ {
return false; return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
} }
mUsesPointSize = vertexShaderD3D->usesPointSize(); mUsesPointSize = vertexShaderD3D->usesPointSize();
return true; return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
} }
void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше